diff mbox series

[ovs-dev,RFC] ovn: Fix ovn check-kmod tests

Message ID 1567635352-9536-1-git-send-email-gvrose8192@gmail.com
State RFC
Headers show
Series [ovs-dev,RFC] ovn: Fix ovn check-kmod tests | expand

Commit Message

Gregory Rose Sept. 4, 2019, 10:15 p.m. UTC
There are a lot of failures of ovn tests in the 'check-kmod' kernel
datapath test.  This patch attempts to fix that.

I don't claim to know all the details of the split between ovs and
ovn since I don't use ovn but since the split these errors have begun
occurring.  Let's use the RFC patch to begin discussion on how to fix
the ovs 'check-kmod' errors for ovn.

Current master branch:
$ sudo make check-kmod TESTSUITEFLAGS="-k ovn"
...

system-ovn

128: ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT FAILED
(system-ovn.at:175)
129: ovn -- 2 LRs connected via LS, gateway router, easy SNAT FAILED
(system-ovn.at:285)
130: ovn -- multiple gateway routers, SNAT and DNAT  FAILED
(system-ovn.at:505)
131: ovn -- load-balancing                           FAILED
(system-ovn.at:653)
132: ovn -- load-balancing - same subnet.            FAILED
(system-ovn.at:760)
133: ovn -- load balancing in gateway router         FAILED
(system-ovn.at:910)
134: ovn -- multiple gateway routers, load-balancing FAILED
(system-ovn.at:1079)
135: ovn -- load balancing in router with gateway router port FAILED
(system-ovn.at:1220)
136: ovn -- DNAT and SNAT on distributed router - N/S FAILED
(system-ovn.at:1369)
137: ovn -- DNAT and SNAT on distributed router - E/W FAILED
(system-ovn.at:1546)
138: ovn -- 2 LSs IGMP                               ok

ERROR: All 11 tests were run,
10 failed unexpectedly.

With this patch applied:
$ sudo make check-kmod TESTSUITEFLAGS="-k ovn"
...

system-ovn

128: ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT ok
129: ovn -- 2 LRs connected via LS, gateway router, easy SNAT ok
130: ovn -- multiple gateway routers, SNAT and DNAT  ok
131: ovn -- load-balancing                           ok
132: ovn -- load-balancing - same subnet.            ok
133: ovn -- load balancing in gateway router         ok
134: ovn -- multiple gateway routers, load-balancing ok
135: ovn -- load balancing in router with gateway router port ok
136: ovn -- DNAT and SNAT on distributed router - N/S FAILED
(system-ovn.at:1337)
137: ovn -- DNAT and SNAT on distributed router - E/W FAILED
(system-ovn.at:1512)
138: ovn -- 2 LSs IGMP                               FAILED
(ovs-macros.at:241)

ERROR: All 11 tests were run,
3 failed unexpectedly.

We still have failures on 136 and 137 and with this patch test and
138 begins to fail even though it passes on the master branch.
But there is improvement on the others

This RFC is intended to start the discussion of cleaning up the
'check-kmod' ovn testing. I've missed some of the discussions
during the time when ovn was separated out to its own project.
I probably missed something important and will see if I can get
this fixed up.

I have a new test I'm working on that will make sure we don't have
regressions in conntrack reassembly and would like to have this
cleaned up before hand.

Signed-off-by: Greg Rose <gvrose8192@gmail.com>
---
 tests/automake.mk            |    23 +-
 tests/ovn-controller-vtep.at |   467 --
 tests/ovn-controller.at      |   294 -
 tests/ovn-macros.at          |   180 -
 tests/ovn-nbctl.at           |  1660 -----
 tests/ovn-northd.at          |   900 ---
 tests/ovn-performance.at     |   424 --
 tests/ovn-sbctl.at           |   150 -
 tests/ovn.at                 | 14702 -----------------------------------------
 tests/system-ovn.at          |  1667 -----
 tests/test-ovn.c             |  1584 -----
 tests/testsuite.at           |     8 -
 12 files changed, 4 insertions(+), 22055 deletions(-)
 delete mode 100644 tests/ovn-controller-vtep.at
 delete mode 100644 tests/ovn-controller.at
 delete mode 100644 tests/ovn-macros.at
 delete mode 100644 tests/ovn-nbctl.at
 delete mode 100644 tests/ovn-northd.at
 delete mode 100644 tests/ovn-performance.at
 delete mode 100644 tests/ovn-sbctl.at
 delete mode 100644 tests/ovn.at
 delete mode 100644 tests/system-ovn.at
 delete mode 100644 tests/test-ovn.c

Comments

Numan Siddique Sept. 5, 2019, 7 p.m. UTC | #1
On Thu, Sep 5, 2019 at 3:48 AM Greg Rose <gvrose8192@gmail.com> wrote:

> There are a lot of failures of ovn tests in the 'check-kmod' kernel
> datapath test.  This patch attempts to fix that.
>
> I don't claim to know all the details of the split between ovs and
> ovn since I don't use ovn but since the split these errors have begun
> occurring.  Let's use the RFC patch to begin discussion on how to fix
> the ovs 'check-kmod' errors for ovn.
>
> Current master branch:
> $ sudo make check-kmod TESTSUITEFLAGS="-k ovn"
> ...
>
> system-ovn
>
> 128: ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT FAILED
> (system-ovn.at:175)
> 129: ovn -- 2 LRs connected via LS, gateway router, easy SNAT FAILED
> (system-ovn.at:285)
> 130: ovn -- multiple gateway routers, SNAT and DNAT  FAILED
> (system-ovn.at:505)
> 131: ovn -- load-balancing                           FAILED
> (system-ovn.at:653)
> 132: ovn -- load-balancing - same subnet.            FAILED
> (system-ovn.at:760)
> 133: ovn -- load balancing in gateway router         FAILED
> (system-ovn.at:910)
> 134: ovn -- multiple gateway routers, load-balancing FAILED
> (system-ovn.at:1079)
> 135: ovn -- load balancing in router with gateway router port FAILED
> (system-ovn.at:1220)
> 136: ovn -- DNAT and SNAT on distributed router - N/S FAILED
> (system-ovn.at:1369)
> 137: ovn -- DNAT and SNAT on distributed router - E/W FAILED
> (system-ovn.at:1546)
> 138: ovn -- 2 LSs IGMP                               ok
>
> ERROR: All 11 tests were run,
> 10 failed unexpectedly.
>
> With this patch applied:
> $ sudo make check-kmod TESTSUITEFLAGS="-k ovn"
> ...
>
> system-ovn
>
> 128: ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT ok
> 129: ovn -- 2 LRs connected via LS, gateway router, easy SNAT ok
> 130: ovn -- multiple gateway routers, SNAT and DNAT  ok
> 131: ovn -- load-balancing                           ok
> 132: ovn -- load-balancing - same subnet.            ok
> 133: ovn -- load balancing in gateway router         ok
> 134: ovn -- multiple gateway routers, load-balancing ok
> 135: ovn -- load balancing in router with gateway router port ok
> 136: ovn -- DNAT and SNAT on distributed router - N/S FAILED
> (system-ovn.at:1337)
> 137: ovn -- DNAT and SNAT on distributed router - E/W FAILED
> (system-ovn.at:1512)
> 138: ovn -- 2 LSs IGMP                               FAILED
> (ovs-macros.at:241)
>
> ERROR: All 11 tests were run,
> 3 failed unexpectedly.
>
> We still have failures on 136 and 137 and with this patch test and
> 138 begins to fail even though it passes on the master branch.
> But there is improvement on the others
>
> This RFC is intended to start the discussion of cleaning up the
> 'check-kmod' ovn testing. I've missed some of the discussions
> during the time when ovn was separated out to its own project.
> I probably missed something important and will see if I can get
> this fixed up.
>
> I have a new test I'm working on that will make sure we don't have
> regressions in conntrack reassembly and would like to have this
> cleaned up before hand.
>
> Signed-off-by: Greg Rose <gvrose8192@gmail.com>
>


Hi Greg,

This seems reasonable to me. Mark has already submitted a patch to delete
the OVN folder. But we may have to keep ovn-nbctl/ovn-sbctl utilities
and OVN schema files for ovsdb-server RAFT tests.

Until that patch is merged, this seems fine to me.

Can you please provide the steps you use to run the system tests ?
I will try to run in the new ovn repo and see if we see failures there.
I tried sometime back and all the tests fail for me. Probably I wasn't
running as expected.

Thanks
Numan



> ---
>  tests/automake.mk            |    23 +-
>  tests/ovn-controller-vtep.at |   467 --
>  tests/ovn-controller.at      |   294 -
>  tests/ovn-macros.at          |   180 -
>  tests/ovn-nbctl.at           |  1660 -----
>  tests/ovn-northd.at          |   900 ---
>  tests/ovn-performance.at     |   424 --
>  tests/ovn-sbctl.at           |   150 -
>  tests/ovn.at                 | 14702
> -----------------------------------------
>  tests/system-ovn.at          |  1667 -----
>  tests/test-ovn.c             |  1584 -----
>  tests/testsuite.at           |     8 -
>  12 files changed, 4 insertions(+), 22055 deletions(-)
>  delete mode 100644 tests/ovn-controller-vtep.at
>  delete mode 100644 tests/ovn-controller.at
>  delete mode 100644 tests/ovn-macros.at
>  delete mode 100644 tests/ovn-nbctl.at
>  delete mode 100644 tests/ovn-northd.at
>  delete mode 100644 tests/ovn-performance.at
>  delete mode 100644 tests/ovn-sbctl.at
>  delete mode 100644 tests/ovn.at
>  delete mode 100644 tests/system-ovn.at
>  delete mode 100644 tests/test-ovn.c
>
> diff --git a/tests/automake.mk b/tests/automake.mk
> index d6ab517..decca46 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -23,8 +23,7 @@ EXTRA_DIST += \
>  COMMON_MACROS_AT = \
>         tests/ovsdb-macros.at \
>         tests/ovs-macros.at \
> -       tests/ofproto-macros.at \
> -       tests/ovn-macros.at
> +       tests/ofproto-macros.at
>
>  TESTSUITE_AT = \
>         tests/testsuite.at \
> @@ -104,16 +103,9 @@ TESTSUITE_AT = \
>         tests/vlog.at \
>         tests/vtep-ctl.at \
>         tests/auto-attach.at \
> -       tests/ovn.at \
> -       tests/ovn-northd.at \
> -       tests/ovn-nbctl.at \
> -       tests/ovn-sbctl.at \
> -       tests/ovn-controller.at \
> -       tests/ovn-controller-vtep.at \
>         tests/mcast-snooping.at \
>         tests/packet-type-aware.at \
> -       tests/nsh.at \
> -       tests/ovn-performance.at
> +       tests/nsh.at
>
>  EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
>  FUZZ_REGRESSION_TESTS = \
> @@ -158,7 +150,6 @@ SYSTEM_KMOD_TESTSUITE_AT = \
>
>  SYSTEM_USERSPACE_TESTSUITE_AT = \
>         tests/system-userspace-testsuite.at \
> -       tests/system-ovn.at \
>         tests/system-userspace-macros.at \
>         tests/system-userspace-packet-type-aware.at
>
> @@ -169,7 +160,6 @@ SYSTEM_AFXDP_TESTSUITE_AT = \
>
>  SYSTEM_TESTSUITE_AT = \
>         tests/system-common-macros.at \
> -       tests/system-ovn.at \
>         tests/system-layer3-tunnels.at \
>         tests/system-traffic.at \
>         tests/system-interface.at
> @@ -197,7 +187,7 @@ SYSTEM_DPDK_TESTSUITE =
> $(srcdir)/tests/system-dpdk-testsuite
>  OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
>  DISTCLEANFILES += tests/atconfig tests/atlocal
>
> -AUTOTEST_PATH =
> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller
> +AUTOTEST_PATH =
> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR)
>
>  check-local:
>         set $(SHELL) '$(TESTSUITE)' -C tests
> AUTOTEST_PATH=$(AUTOTEST_PATH); \
> @@ -238,10 +228,6 @@ check-lcov: all $(check_DATA) clean-lcov
>  # valgrind support
>
>  valgrind_wrappers = \
> -       tests/valgrind/ovn-controller \
> -       tests/valgrind/ovn-nbctl \
> -       tests/valgrind/ovn-northd \
> -       tests/valgrind/ovn-sbctl \
>         tests/valgrind/ovs-appctl \
>         tests/valgrind/ovs-ofctl \
>         tests/valgrind/ovs-vsctl \
> @@ -446,7 +432,6 @@ tests_ovstest_SOURCES = \
>         tests/test-netflow.c \
>         tests/test-odp.c \
>         tests/test-ofpbuf.c \
> -       tests/test-ovn.c \
>         tests/test-packets.c \
>         tests/test-random.c \
>         tests/test-rcu.c \
> @@ -474,7 +459,7 @@ tests_ovstest_SOURCES += \
>         tests/test-netlink-conntrack.c
>  endif
>
> -tests_ovstest_LDADD = lib/libopenvswitch.la ovn/lib/libovn.la
> +tests_ovstest_LDADD = lib/libopenvswitch.la
>
>  noinst_PROGRAMS += tests/test-stream
>  tests_test_stream_SOURCES = tests/test-stream.c
> diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at
> deleted file mode 100644
> index a3fe8cb..0000000
> --- a/tests/ovn-controller-vtep.at
> +++ /dev/null
> @@ -1,467 +0,0 @@
> -AT_BANNER([ovn_controller_vtep])
> -
> -# OVN_CONTROLLER_VTEP_START
> -#
> -# Starts the test with a setup with vtep device.  Each test case must
> first
> -# call this macro.
> -#
> -# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two physical
> ports
> -# 'p0', 'p1'.
> -#
> -# Configures ovn-nb with a logical switch 'br-test'.
> -#
> -#
> -m4_define([OVN_CONTROLLER_VTEP_START],
> -  [
> -   AT_KEYWORDS([ovn])
> -   # this will cause skip when 'make check' using Windows setup.
> -   AT_SKIP_IF([test $HAVE_PYTHON = no])
> -
> -   dnl Create databases (ovn-nb, ovn-sb, vtep).
> -   AT_CHECK([ovsdb-tool create vswitchd.db
> $abs_top_srcdir/vswitchd/vswitch.ovsschema])
> -   for daemon in ovn-nb ovn-sb vtep; do
> -      AT_CHECK([ovsdb-tool create $daemon.db
> $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
> -   done
> -
> -   dnl Start ovsdb-server.
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
> --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db vtep.db], [0], [], [stderr])
> -   AT_CHECK([ovsdb-server --detach --no-chdir
> --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log
> --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
> -   AT_CHECK([ovsdb-server --detach --no-chdir
> --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log
> --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db], [0], [],
> [stderr])
> -   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid` `cat
> ovsdb-sb-server.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d
> -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
> -   AT_CAPTURE_FILE([ovsdb-server.log])
> -
> -   dnl Start ovs-vswitchd.
> -   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system --detach
> --no-chdir --pidfile --log-file -vvconn -vofproto_dpif], [0], [], [stderr])
> -   AT_CAPTURE_FILE([ovs-vswitchd.log])
> -   on_exit "kill `cat ovs-vswitchd.pid`"
> -   AT_CHECK([[sed < stderr '
> -/ovs_numa|INFO|Discovered /d
> -/vlog|INFO|opened log file/d
> -/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
> -/reconnect|INFO|/d
> -/ofproto|INFO|using datapath ID/d
> -/netlink_socket|INFO|netlink: could not enable listening to all nsid/d
> -/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
> -   AT_CHECK([ovs-vsctl -- add-br br-vtep \
> -              -- set bridge br-vtep datapath-type=dummy
> other-config:datapath-id=fedcba9876543210
> other-config:hwaddr=aa:55:aa:55:00:00
> protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]]
> fail-mode=secure \
> -              -- add-port br-vtep p0 -- set Interface p0 type=dummy
> ofport_request=1 \
> -              -- add-port br-vtep p1 -- set Interface p1 type=dummy
> ofport_request=2])
> -
> -   dnl Start ovs-vtep.
> -   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch br-vtep
> tunnel_ips=1.2.3.4])
> -   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log --pidfile=ovs-vtep.pid
> --detach --no-chdir br-vtep \], [0], [], [stderr])
> -   on_exit "kill `cat ovs-vtep.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d']])
> -   # waits until ovs-vtep starts up.
> -   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])
> -
> -   dnl Start ovn-northd.
> -   AT_CHECK([ovn-nbctl ls-add br-test])
> -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file], [0],
> [], [stderr])
> -   on_exit "kill `cat ovn-northd.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d']])
> -   AT_CAPTURE_FILE([ovn-northd.log])
> -
> -   dnl Start ovn-controllger-vtep.
> -   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile --log-file
> --vtep-db=unix:$OVS_RUNDIR/db.sock
> --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
> -   AT_CAPTURE_FILE([ovn-controller-vtep.log])
> -   on_exit "kill `cat ovn-controller-vtep.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d
> -/reconnect|INFO|/d']])
> -])
> -
> -# OVN_CONTROLLER_VTEP_STOP
> -#
> -# So many exits... Yeah, we started a lot daemons~
> -#
> -m4_define([OVN_CONTROLLER_VTEP_STOP],
> -  [AT_CHECK([check_logs "$1"])
> -   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
> -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
> -   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
> -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
> -
> -# Adds logical port for a vtep gateway chassis in ovn-nb database.
> -#
> -# $1: logical switch name in ovn-nb database
> -# $2: logical port name
> -# $3: physical vtep gateway name
> -# $4: logical switch name on vtep gateway chassis
> -m4_define([OVN_NB_ADD_VTEP_PORT], [
> -AT_CHECK([ovn-nbctl lsp-add $1 $2])
> -
> -AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
> -AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3
> vtep-logical-switch=$4])
> -])
> -
> -##############################################
> -
> -# tests chassis related updates.
> -AT_SETUP([ovn-controller-vtep - chassis])
> -OVN_CONTROLLER_VTEP_START
> -
> -# verifies the initial ovn-sb db configuration.
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
> -AT_CHECK([ovn-sbctl show], [0], [dnl
> -Chassis br-vtep
> -    Encap vxlan
> -        ip: "1.2.3.4"
> -        options: {csum="false"}
> -])
> -
> -# deletes the chassis via ovn-sbctl and check that it is readded back
> -# with the log.
> -AT_CHECK([ovn-sbctl chassis-del br-vtep])
> -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
> -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log], [0],
> [dnl
> -|WARN|Chassis for VTEP physical switch (br-vtep) disappears, maybe
> deleted by ovn-sbctl, adding it back
> -])
> -
> -# changes the tunnel_ip on physical switch, watches the update of
> chassis's
> -# encap.
> -AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
> -AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr -d '
> '], [0], [dnl
> -"1.2.3.5"
> -])
> -
> -# adds vlan_bindings to physical ports.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 --
> bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch0`"])
> -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d
> ':' -f2 | tr -d ' ' ], [0], [dnl
> -[[lswitch0]]
> -])
> -
> -# adds another logical switch and new vlan_bindings.
> -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300 lswitch1])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch1`"])
> -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d
> ':' -f2 | tr -d ' '], [0], [dnl
> -[[lswitch0,lswitch1]]
> -])
> -
> -# unbinds one port from lswitch0, nothing should change.
> -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list
> physical_port p0 | grep -- '200='`"])
> -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d
> ':' -f2 | tr -d ' ' ], [0], [dnl
> -[[lswitch0,lswitch1]]
> -])
> -
> -# unbinds all ports from lswitch0.
> -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep p1 300])
> -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
> br-vtep_lswitch0`"])
> -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d
> ':' -f2 | tr -d ' ' ], [0], [dnl
> -[[lswitch1]]
> -])
> -
> -# unbinds all ports from lswitch1.
> -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
> -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
> br-vtep_lswitch1`"])
> -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d
> ':' -f2 | tr -d ' '], [0], [dnl
> -[[]]
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch (br-vtep)
> disappears/d])
> -AT_CLEANUP
> -
> -
> -# Tests binding updates.
> -AT_SETUP([ovn-controller-vtep - binding 1])
> -OVN_CONTROLLER_VTEP_START
> -
> -# adds logical switch 'lswitch0' and vlan_bindings.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 --
> bind-ls br-vtep p1 300 lswitch0])
> -# adds logical switch port in ovn-nb database, and sets the type and
> options.
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
> -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
> chassis!='[[]]'
> -# should see one binding, associated to chassis of 'br-vtep'.
> -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d
> ':' -f2 | tr -d ' ')
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
> br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
> -${chassis_uuid}
> -])
> -
> -# adds another logical switch 'lswitch1' and vlan_bindings.
> -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
> -# adds logical switch port in ovn-nb database for lswitch1.
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep], [lswitch1])
> -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1
> chassis!='[[]]'
> -# This is allowed, but not recommended, to have two vlan_bindings (to
> different vtep logical switches)
> -# from one vtep gateway physical port in one ovn-nb logical swithch.
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d
> ':' -f2 | tr -d ' ' | sort], [0], [dnl
> -
> -${chassis_uuid}
> -${chassis_uuid}
> -])
> -
> -# adds another logical switch port in ovn-nb database for lswitch0.
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup], [br-vtep],
> [lswitch0])
> -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0_dup
> chassis!='[[]]'
> -# it is not allowed to have more than one ovn-nb logical port for the same
> -# vtep logical switch on a vtep gateway chassis, so should still see only
> -# two port_binding entries bound.
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d
> ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
> -
> -
> -[[]]
> -${chassis_uuid}
> -${chassis_uuid}
> -])
> -# confirms the warning log.
> -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed
> 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g' | uniq], [0], [dnl
> -|WARN|logical switch (), on vtep gateway chassis () has already been
> associated with logical port (), ignore logical port ()
> -])
> -
> -# deletes physical ports from vtep.
> -AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
> -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
> br-vtep_lswitch`"])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
> -# should see empty chassis column in both binding entries.
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d
> ':' -f2 | tr -d ' ' | sort], [0], [dnl
> -
> -
> -[[]]
> -[[]]
> -[[]]
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical
> port/d])
> -AT_CLEANUP
> -
> -
> -# Tests corner case: Binding the vtep logical switch from two different
> -# datapath.
> -AT_SETUP([ovn-controller-vtep - binding 2])
> -OVN_CONTROLLER_VTEP_START
> -
> -# adds logical switch 'lswitch0' and vlan_bindings.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> -# adds logical switch port in ovn-nb database, and sets the type and
> options.
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
> -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
> chassis!='[[]]'
> -
> -# adds another lswitch 'br-void' in ovn-nb database.
> -AT_CHECK([ovn-nbctl ls-add br-void])
> -# adds another vtep pswitch 'br-vtep-void' in vtep database.
> -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0-void
> -- bind-ls br-vtep-void p0-void 100 lswitch0])
> -# adds a conflicting logical port (both br-vtep_lswitch0 and
> br-vtep-void_lswitch0
> -# are bound to the same logical switch, but they are on different
> datapath).
> -OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0], [br-vtep-void],
> [lswitch0])
> -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
> -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
> -# confirms the warning log.
> -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed
> 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key
> [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
> -|WARN|logical switch (), on vtep gateway chassis () has already been
> associated with logical datapath (), ignore logical port () which belongs
> to logical datapath ()
> -])
> -
> -# then deletes 'br-void' and 'br-vtep-void', should see 'br-vtep_lswitch0'
> -# bound correctly.
> -AT_CHECK([ovn-nbctl ls-del br-void])
> -# adds another vtep pswitch 'br-vtep-void' in vtep database.
> -AT_CHECK([vtep-ctl del-ps br-vtep-void])
> -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep
> br-vtep-void_lswitch0`"])
> -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d
> ':' -f2 | tr -d ' ')
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
> br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
> -${chassis_uuid}
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical
> datapath/d])
> -AT_CLEANUP
> -
> -
> -# Tests vtep module vtep logical switch tunnel key update.
> -AT_SETUP([ovn-controller-vtep - vtep-lswitch])
> -OVN_CONTROLLER_VTEP_START
> -
> -# creates the logical switch in vtep and adds the corresponding logical
> -# port to 'br-test'.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
> br-vtep_lswitch0`"])
> -
> -# retrieves the expected tunnel key.
> -datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding
> br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
> -tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding
> ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
> Logical_Switch | grep 0`"])
> -# checks the vtep logical switch tunnel key configuration.
> -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch |
> cut -d ':' -f2 | tr -d ' '], [0], [dnl
> -${tunnel_key}
> -])
> -
> -# creates a second physical switch in vtep database, and binds its p0
> vlan-100
> -# to the same logical switch 'lswitch0'.
> -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0 --
> bind-ls br-vtep-void p0 100 lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis  | grep
> -- br-vtep-void`"])
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0], [br-vtep-void],
> [lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
> br-vtep-void_lswitch0`"])
> -
> -# checks the vtep logical switch tunnel key configuration.
> -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch |
> cut -d ':' -f2 | tr -d ' '], [0], [dnl
> -${tunnel_key}
> -])
> -
> -# now, deletes br-vtep-void.
> -AT_CHECK([vtep-ctl del-ps br-vtep-void])
> -OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis  | grep
> -- br-vtep-void`"])
> -# checks the vtep logical switch tunnel key configuration.
> -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch |
> cut -d ':' -f2 | tr -d ' '], [0], [dnl
> -${tunnel_key}
> -])
> -
> -# changes the ovn-nb logical port type so that it is no longer
> -# vtep port.
> -AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
> Logical_Switch | grep 1`"])
> -# now should see the tunnel key reset.
> -AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':'
> -f2 | tr -d ' '], [0], [dnl
> -0
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP
> -AT_CLEANUP
> -
> -
> -# Tests vtep module 'Ucast_Macs_Remote's.
> -AT_SETUP([ovn-controller-vtep - vtep-macs 1])
> -OVN_CONTROLLER_VTEP_START
> -
> -# creates a simple logical network with the vtep device and a fake hv
> chassis
> -# 'ch0'.
> -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
> -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
> -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
> -
> -# creates the logical switch in vtep and adds the corresponding logical
> -# port to 'br-test'.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
> br-vtep_lswitch0`"])
> -
> -# adds another lswitch 'br-void' in ovn-nb database.
> -AT_CHECK([ovn-nbctl ls-add br-void])
> -# adds fake hv chassis 'ch1'.
> -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
> -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
> -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
> -
> -# checks Ucast_Macs_Remote creation.
> -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' '], [0], [dnl
> -"f0:ab:cd:ef:01:02"
> -])
> -
> -# checks physical locator creation.
> -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep _uuid`"])
> -AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut -d ':'
> -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
> -"1.2.3.5"
> -])
> -
> -# checks tunnel creation by ovs-vtep.
> -OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
> -AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 | cut -d
> ':' -f2 | tr -d ' '], [0], [dnl
> -{remote_ip="1.2.3.5"}
> -])
> -
> -# adds another mac to logical switch port.
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02
> f0:ab:cd:ef:01:03])
> -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep 03`"])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' ' | sort], [0], [dnl
> -
> -"f0:ab:cd:ef:01:02"
> -"f0:ab:cd:ef:01:03"
> -])
> -
> -# removes one mac to logical switch port.
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote |
> grep 02`"])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' ' | sort], [0], [dnl
> -"f0:ab:cd:ef:01:03"
> -])
> -
> -# migrates mac to logical switch port vif1 on 'br-void'.
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
> -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote |
> grep 03`"])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' ' | sort], [0], [dnl
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP
> -AT_CLEANUP
> -
> -
> -# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
> -AT_SETUP([ovn-controller-vtep - vtep-macs 2])
> -OVN_CONTROLLER_VTEP_START
> -
> -# creates a simple logical network with the vtep device and a fake hv
> chassis
> -# 'ch0'.
> -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
> -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
> -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
> -
> -# creates another vif in the same logical switch with duplicate mac.
> -AT_CHECK([ovn-nbctl lsp-add br-test vif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
> -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
> -
> -# creates the logical switch in vtep and adds the corresponding logical
> -# port to 'br-test'.
> -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
> -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
> br-vtep_lswitch0`"])
> -
> -# checks Ucast_Macs_Remote creation.  Should still only be one entry,
> since duplicate
> -# mac in the same logical switch is not allowed.
> -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' '], [0], [dnl
> -"f0:ab:cd:ef:01:02"
> -])
> -# confirms the warning log.
> -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
> -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed
> 's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
> -|WARN|MAC address () has already been known to be on logical port () in
> the same logical datapath, so just ignore this logical port ()
> -])
> -
> -# deletes vif1.
> -AT_CHECK([ovn-nbctl lsp-del vif1])
> -
> -# adds another lswitch 'br-void' in ovn-nb database.
> -AT_CHECK([ovn-nbctl ls-add br-void])
> -# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
> -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
> -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
> -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])
> -
> -# creates another logical switch in vtep and adds the corresponding
> logical
> -# port to 'br-void'.
> -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
> -OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep], [lswitch1])
> -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
> br-void_lswitch1`"])
> -
> -# checks Ucast_Macs_Remote creation.  Should see two entries since it is
> allowed
> -# to have duplicate macs in different logical switches.
> -OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list Ucast_Macs_Remote |
> grep 02 | wc -l` -gt 1])
> -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2-
> | tr -d ' ' | sort], [0], [dnl
> -
> -"f0:ab:cd:ef:01:02"
> -"f0:ab:cd:ef:01:02"
> -])
> -
> -OVN_CONTROLLER_VTEP_STOP([/has already been known to be on logical
> port/d])
> -AT_CLEANUP
> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
> deleted file mode 100644
> index 343c2ab..0000000
> --- a/tests/ovn-controller.at
> +++ /dev/null
> @@ -1,294 +0,0 @@
> -AT_BANNER([ovn-controller])
> -
> -AT_SETUP([ovn-controller - ovn-bridge-mappings])
> -AT_KEYWORDS([ovn])
> -ovn_init_db ovn-sb
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0 \
> -    -- add-br br-eth1 \
> -    -- add-br br-eth2
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -# Waits until the OVS database contains exactly the specified patch ports.
> -# Each argument should be of the form BRIDGE PORT PEER.
> -check_patches () {
> -    # Generate code to check that the set of patch ports is exactly as
> -    # specified.
> -    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name find
> Interface type=patch | sort' > query
> -    for patch
> -    do
> -        echo $patch
> -    done | cut -d' ' -f 2 | sort > expout
> -
> -    # Generate code to verify that the configuration of each patch
> -    # port is correct.
> -    for patch
> -    do
> -        set $patch; bridge=$1 port=$2 peer=$3
> -        echo >>query "ovs-vsctl iface-to-br $port -- get Interface $port
> type options"
> -        echo >>expout "$bridge
> -patch
> -{peer=$peer}"
> -    done
> -
> -    # Run the query until we get the expected result (or until a timeout).
> -    #
> -    # (We use sed to drop all "s from output because ovs-vsctl quotes some
> -    # of the port names but not others.)
> -    AT_CAPTURE_FILE([query])
> -    AT_CAPTURE_FILE([expout])
> -    AT_CAPTURE_FILE([stdout])
> -    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
> -                    diff -u stdout expout >/dev/null])
> -}
> -
> -# Make sure that the configured bridge mappings in the Open_vSwitch db
> -# is mirrored into the Chassis record in the OVN_Southbound db.
> -check_bridge_mappings () {
> -    local_mappings=$1
> -    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
> -    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get Chassis
> ${sysid} external_ids:ovn-bridge-mappings | sed -e 's/\"//g')])
> -}
> -
> -# Initially there should be no patch ports.
> -check_patches
> -
> -# Configure two ovn-bridge mappings, but no patch ports should be created
> yet
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
> -check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
> -check_patches
> -
> -# Create a localnet port, but we should still have no patch ports, as they
> -# won't be created until there's a localnet port on a logical switch with
> -# another logical port bound to this chassis.
> -ovn-sbctl \
> -    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
> -    -- create Port_Binding datapath=@dp101 logical_port=localnet1
> tunnel_key=1 \
> -        type=localnet options:network_name=physnet1
> -check_patches
> -
> -# Create a localnet port on a logical switch with a port bound to this
> chassis.
> -# Now we should get some patch ports created.
> -ovn-sbctl \
> -    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
> -    -- create Port_Binding datapath=@dp102 logical_port=localnet2
> tunnel_key=1 \
> -        type=localnet options:network_name=physnet1 \
> -    -- create Port_Binding datapath=@dp102 logical_port=localvif2
> tunnel_key=2
> -ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
> external_ids:iface-id=localvif2
> -check_patches \
> -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
> -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
> -
> -# Add logical patch ports to connect new logical datapath.
> -#
> -# OVN no longer uses OVS patch ports to implement logical patch ports, so
> -# the set of OVS patch ports doesn't change.
> -AT_CHECK([ovn-sbctl \
> -    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
> -    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
> -    -- create Port_Binding datapath=@dp1 logical_port=foo tunnel_key=1
> type=patch options:peer=bar \
> -    -- create Port_Binding datapath=@dp2 logical_port=bar tunnel_key=2
> type=patch options:peer=foo \
> -    -- create Port_Binding datapath=@dp1 logical_port=dp1vif tunnel_key=3
> \
> -| uuidfilt], [0], [<0>
> -<1>
> -<2>
> -<3>
> -<4>
> -])
> -ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif
> external_ids:iface-id=dp1vif
> -check_patches \
> -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
> -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
> -
> -# Delete the mapping and the ovn-bridge-mapping patch ports should go
> away.
> -AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids
> ovn-bridge-mappings])
> -check_bridge_mappings
> -check_patches
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP_SBOX([hv])
> -OVN_CLEANUP_VSWITCH([main])
> -as ovn-sb
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -
> -AT_CLEANUP
> -
> -# Checks that ovn-controller populates datapath-type and iface-types
> -# correctly in the Chassis external-ids column.
> -AT_SETUP([ovn-controller - Chassis external_ids])
> -AT_KEYWORDS([ovn])
> -ovn_init_db ovn-sb
> -
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0 \
> -    -- add-br br-eth1 \
> -    -- add-br br-eth2
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
> -
> -# Make sure that the datapath_type set in the Bridge table
> -# is mirrored into the Chassis record in the OVN_Southbound db.
> -check_datapath_type () {
> -    datapath_type=$1
> -    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid}
> external_ids:datapath-type | sed -e 's/"//g') #"
> -    test "${datapath_type}" = "${chassis_datapath_type}"
> -}
> -
> -OVS_WAIT_UNTIL([check_datapath_type ""])
> -
> -ovs-vsctl set Bridge br-int datapath-type=foo
> -OVS_WAIT_UNTIL([check_datapath_type foo])
> -
> -# Change "ovn-bridge-mappings" value. It should not change the
> "datapath-type".
> -ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-mappings=foo-mapping
> -check_datapath_type foo
> -
> -ovs-vsctl set Bridge br-int datapath-type=bar
> -OVS_WAIT_UNTIL([check_datapath_type bar])
> -
> -ovs-vsctl set Bridge br-int datapath-type=\"\"
> -OVS_WAIT_UNTIL([check_datapath_type ""])
> -
> -# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
> -ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-datapath-type=foo
> -OVS_WAIT_UNTIL([check_datapath_type foo])
> -
> -# Change the br-int's datapath type to bar.
> -# It should be reset to foo since ovn-bridge-datapath-type is configured.
> -ovs-vsctl set Bridge br-int datapath-type=bar
> -OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int datapath-type`])
> -OVS_WAIT_UNTIL([check_datapath_type foo])
> -
> -ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-datapath-type=foobar
> -OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int datapath-type`])
> -OVS_WAIT_UNTIL([check_datapath_type foobar])
> -
> -expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types | tr -d
> '[[]] ""')
> -echo "expected_iface_types = ${expected_iface_types}"
> -chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
> external_ids:iface-types | sed -e 's/\"//g')
> -echo "chassis_iface_types = ${chassis_iface_types}"
> -AT_CHECK([test "${expected_iface_types}" = "${chassis_iface_types}"])
> -
> -# Change the value of external_ids:iface-types using ovn-sbctl.
> -# ovn-controller should again set it back to proper one.
> -ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
> -OVS_WAIT_UNTIL([
> -    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
> external_ids:iface-types | sed -e 's/\"//g')
> -    echo "chassis_iface_types = ${chassis_iface_types}"
> -    test "${expected_iface_types}" = "${chassis_iface_types}"
> -])
> -
> -# Change the value of external_ids:system-id and make sure it's mirrored
> -# in the Chassis record in the OVN_Southbound database.
> -sysid=${sysid}-foo
> -ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
> -OVS_WAIT_UNTIL([
> -    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
> -    test "${sysid}" = "${chassis_id}"
> -])
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP_SBOX([hv])
> -OVN_CLEANUP_VSWITCH([main])
> -as ovn-sb
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -
> -AT_CLEANUP
> -
> -# Checks that ovn-controller correctly maintains the mapping from the
> Encap
> -# table in the Southbound database to OVS in the face of changes on both
> sides
> -AT_SETUP([ovn-controller - change Encap properties])
> -AT_KEYWORDS([ovn])
> -ovn_init_db ovn-sb
> -
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0 \
> -    -- add-br br-eth1 \
> -    -- add-br br-eth2
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -check_tunnel_property () {
> -    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
> -}
> -
> -# Start off with a remote chassis supporting STT
> -ovn-sbctl chassis-add fakechassis stt 192.168.0.2
> -OVS_WAIT_UNTIL([check_tunnel_property type stt])
> -
> -# See if we switch to Geneve as the first choice when it is available
> -# With multi-VTEP support we support tunnels with different IPs to the
> -# same chassis, and hence use the IP to annotate the tunnel (along with
> -# the chassis-id in ovn-chassis-id); if we supply a different IP here
> -# we won't be able to co-relate this to the tunnel port that was created
> -# in the previous step and, as a result, will end up creating another
> tunnel,
> -# ie. we can't just lookup using "ovn-fakech-0". So, need to use the same
> IP
> -# as above, i.e 192.168.0.2, here.
> -encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap --
> --id=@encap create encap type=geneve ip="192.168.0.2")
> -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
> -
> -# Check that changes within an encap row are propagated
> -ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
> -OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip
> "\"192.168.0.2\""])
> -
> -# Change the type on the OVS side and check than OVN fixes it
> -ovs-vsctl set interface ovn-fakech-0 type=vxlan
> -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
> -
> -# Delete the port entirely and it should be resurrected
> -ovs-vsctl del-port ovn-fakech-0
> -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP_SBOX([hv])
> -OVN_CLEANUP_VSWITCH([main])
> -as ovn-sb
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -
> -AT_CLEANUP
> -
> -# Check ovn-controller connection status to Southbound database
> -AT_SETUP([ovn-controller - check sbdb connection])
> -AT_KEYWORDS([ovn])
> -ovn_init_db ovn-sb
> -
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0 \
> -    -- add-br br-eth1 \
> -    -- add-br br-eth2
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -check_sbdb_connection () {
> -    test "$(ovs-appctl -t ovn-controller connection-status)" = "$1"
> -}
> -
> -OVS_WAIT_UNTIL([check_sbdb_connection connected])
> -
> -ovs-vsctl set open . external_ids:ovn-remote=tcp:192.168.0.10:6642
> -OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
> -
> -# reset the remote for clean-up
> -ovs-vsctl set open .
> external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
> -# Gracefully terminate daemons
> -OVN_CLEANUP_SBOX([hv])
> -OVN_CLEANUP_VSWITCH([main])
> -as ovn-sb
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -
> -AT_CLEANUP
> diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
> deleted file mode 100644
> index 7dba42c..0000000
> --- a/tests/ovn-macros.at
> +++ /dev/null
> @@ -1,180 +0,0 @@
> -# OVN_CLEANUP_VSWITCH(sim)
> -#
> -# Gracefully terminate vswitch daemons in the
> -# specified sandbox.
> -m4_define([OVN_CLEANUP_VSWITCH],[
> -    as $1
> -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> -    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -])
> -
> -# OVN_CLEANUP_SBOX(sbox)
> -#
> -# Gracefully terminate OVN daemons in the specified
> -# sandbox instance. The sandbox name "vtep" is treated
> -# as a special case, and is assumed to have ovn-controller-vtep
> -# and ovs-vtep daemons running instead of ovn-controller.
> -m4_define([OVN_CLEANUP_SBOX],[
> -    as $1
> -    if test "$1" = "vtep"; then
> -        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
> -        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
> -    else
> -        OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -    fi
> -    OVN_CLEANUP_VSWITCH([$1])
> -])
> -
> -# OVN_CLEANUP(sim [, sim ...])
> -#
> -# Gracefully terminate all OVN daemons, including those in the
> -# specified sandbox instances.
> -m4_define([OVN_CLEANUP],[
> -    m4_foreach([sbox], [$@], [
> -        OVN_CLEANUP_SBOX([sbox])
> -    ])
> -    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 northd-backup
> -    OVS_APP_EXIT_AND_WAIT([ovn-northd])
> -
> -    OVN_CLEANUP_VSWITCH([main])
> -])
> -
> -m4_divert_push([PREPARE_TESTS])
> -
> -# ovn_init_db DATABASE
> -#
> -# Creates and initializes the given DATABASE (one of "ovn-sb" or
> "ovn-nb"),
> -# starts its ovsdb-server instance, and sets the appropriate environment
> -# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or ovn-nbctl uses
> the
> -# database by default.
> -#
> -# Usually invoked from ovn_start.
> -ovn_init_db () {
> -    echo "creating $1 database"
> -    local d=$ovs_base/$1
> -    mkdir "$d" || return 1
> -    : > "$d"/.$1.db.~lock~
> -    as $1 ovsdb-tool create "$d"/$1.db "$abs_top_srcdir"/ovn/$1.ovsschema
> -    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock "$d"/$1.db
> -    local var=`echo $1_db | tr a-z- A-Z_`
> -    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
> -}
> -
> -# ovn_start
> -#
> -# Creates and initializes ovn-sb and ovn-nb databases and starts their
> -# ovsdb-server instance, sets appropriate environment variables so that
> -# ovn-sbctl and ovn-nbctl use them by default, and starts ovn-northd
> running
> -# against them.
> -ovn_start () {
> -    ovn_init_db ovn-sb; ovn-sbctl init
> -    ovn_init_db ovn-nb; ovn-nbctl init
> -
> -    echo "starting ovn-northd"
> -    mkdir "$ovs_base"/northd
> -    as northd start_daemon ovn-northd -v \
> -               --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
> -               --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -
> -    echo "starting backup ovn-northd"
> -    mkdir "$ovs_base"/northd-backup
> -    as northd-backup start_daemon ovn-northd -v \
> -               --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
> -               --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -}
> -
> -# Interconnection networks.
> -#
> -# When multiple sandboxed Open vSwitch instances exist, one will
> inevitably
> -# want to connect them together.  These commands allow for that.
> Conceptually,
> -# an interconnection network is a switch for which these functions make
> it easy
> -# to plug into other switches in other sandboxed Open vSwitch instances.
> -# Interconnection networks are implemented as bridges in a switch named
> "main",
> -# so to use interconnection networks please avoid working with that switch
> -# directly.
> -
> -# net_add NETWORK
> -#
> -# Creates a new interconnection network named NETWORK.
> -net_add () {
> -    test -d "$ovs_base"/main || sim_add main || return 1
> -    as main ovs-vsctl add-br "$1"
> -}
> -
> -# net_attach NETWORK BRIDGE
> -#
> -# Adds a new port to BRIDGE in the default sandbox (as set with as()) and
> plugs
> -# it into the NETWORK interconnection network.  NETWORK must already have
> been
> -# created by a previous invocation of net_add.  The default sandbox must
> not be
> -# "main".
> -net_attach () {
> -    local net=$1 bridge=$2
> -
> -    local port=${sandbox}_$bridge
> -    as main ovs-vsctl \
> -        -- add-port $net $port \
> -        -- set Interface $port
> options:pstream="punix:$ovs_base/main/$port.sock"
> options:rxq_pcap="$ovs_base/main/$port-rx.pcap"
> options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
> -        || return 1
> -
> -    ovs-vsctl \
> -        -- set Interface $bridge
> options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap"
> options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
> -        -- add-port $bridge ${bridge}_$net \
> -        -- set Interface ${bridge}_$net
> options:stream="unix:$ovs_base/main/$port.sock"
> options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap"
> options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
> -        || return 1
> -}
> -
> -# ovn_attach NETWORK BRIDGE IP [MASKLEN]
> -#
> -# First, this command attaches BRIDGE to interconnection network NETWORK,
> just
> -# like "net_attach NETWORK BRIDGE".  Second, it configures (simulated) IP
> -# address IP (with network mask length MASKLEN, which defaults to 24) on
> -# BRIDGE.  Finally, it configures the Open vSwitch database to work with
> OVN
> -# and starts ovn-controller.
> -ovn_attach() {
> -    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
> -    net_attach $net $bridge || return 1
> -
> -    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g`
> -    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
> -    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen >/dev/null ||
> return 1
> -    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null || return 1
> -    ovs-vsctl \
> -        -- set Open_vSwitch . external-ids:system-id=$sandbox \
> -        -- set Open_vSwitch .
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> -        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve,vxlan \
> -        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
> -        -- add-br br-int \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true \
> -        || return 1
> -    start_daemon ovn-controller || return 1
> -}
> -
> -# OVN_POPULATE_ARP
> -#
> -# This pre-populates the ARP tables of all of the OVN instances that have
> been
> -# started with ovn_attach().  That means that packets sent from one
> hypervisor
> -# to another never get dropped or delayed by ARP resolution, which makes
> -# testing easier.
> -ovn_populate_arp__() {
> -    for e1 in $arp_table; do
> -        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4
> -        for e2 in $arp_table; do
> -            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
> -            if test $sb1,$br1 != $sb2,$br2; then
> -                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac || return 1
> -            fi
> -        done
> -    done
> -}
> -m4_divert_pop([PREPARE_TESTS])
> -
> -m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0],
> [ignore])])
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> deleted file mode 100644
> index d99d3af..0000000
> --- a/tests/ovn-nbctl.at
> +++ /dev/null
> @@ -1,1660 +0,0 @@
> -AT_BANNER([ovn-nbctl])
> -
> -OVS_START_SHELL_HELPERS
> -# OVN_NBCTL_TEST_START
> -m4_define([OVN_NBCTL_TEST_START],
> -  [AT_KEYWORDS([ovn])
> -   AT_CAPTURE_FILE([ovsdb-server.log])
> -   ovn_nbctl_test_start $1])
> -ovn_nbctl_test_start() {
> -   dnl Create ovn-nb database.
> -   AT_CHECK([ovsdb-tool create ovn-nb.db
> $abs_top_srcdir/ovn/ovn-nb.ovsschema])
> -
> -   dnl Start ovsdb-server.
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
> --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
> -   on_exit "kill `cat ovsdb-server.pid`"
> -   AS_CASE([$1],
> -     [daemon],
> -       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach --no-chdir
> --log-file -vsocket_util:off)
> -        on_exit "kill `cat ovn-nbctl.pid`"],
> -     [direct], [],
> -     [*], [AT_FAIL_IF(:)])
> -   AT_CHECK([ovn-nbctl init])
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d
> -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
> -}
> -
> -# OVN_NBCTL_TEST_STOP
> -m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
> -ovn_nbctl_test_stop() {
> -   AT_CHECK([check_logs "$1"])
> -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -}
> -OVS_END_SHELL_HELPERS
> -
> -# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
> -m4_define([OVN_NBCTL_TEST],
> -   [OVS_START_SHELL_HELPERS
> -    $1() {
> -      $3
> -    }
> -    OVS_END_SHELL_HELPERS
> -
> -    AT_SETUP([ovn-nbctl - $2 - direct])
> -    OVN_NBCTL_TEST_START direct
> -    $1
> -    OVN_NBCTL_TEST_STOP
> -    AT_CLEANUP
> -
> -    AT_SETUP([ovn-nbctl - $2 - daemon])
> -    OVN_NBCTL_TEST_START daemon
> -    $1
> -    OVN_NBCTL_TEST_STOP
> -    AT_CLEANUP])
> -
> -OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)
> -])
> -
> -AT_CHECK([ovn-nbctl ls-add ls1])
> -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)
> -<1> (ls1)
> -])
> -
> -AT_CHECK([ovn-nbctl ls-del ls0])
> -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
> -<0> (ls1)
> -])
> -
> -AT_CHECK([ovn-nbctl show ls0])
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
> -  [switch <0> (ls0)
> -])
> -AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
> -  [ovn-nbctl: ls0: a switch with this name already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
> -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
> -  [switch <0> (ls0)
> -])
> -AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
> -AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], [1], [],
> -  [ovn-nbctl: --may-exist and --add-duplicate may not be used together
> -])
> -AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
> -  [ovn-nbctl: Multiple logical switches named 'ls0'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
> -  [ovn-nbctl: ls2: switch name not found
> -])
> -AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
> -
> -AT_CHECK([ovn-nbctl ls-add])
> -AT_CHECK([ovn-nbctl ls-add])
> -AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
> -  [ovn-nbctl: --add-duplicate requires specifying a name
> -])
> -AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
> -  [ovn-nbctl: --may-exist requires specifying a name
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port
> commands], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
> -  [ovn-nbctl: lp0: a port with this name already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
> -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
> -<0> (lp0)
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
> -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
> -<0> (lp0)
> -<1> (lp1)
> -])
> -
> -AT_CHECK([ovn-nbctl ls-add ls1])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
> -  [ovn-nbctl: lp1: a port with this name already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
> -  [ovn-nbctl: lp1: port already exists but in switch ls0
> -])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
> -  [ovn-nbctl: lp1: port already exists but has no parent
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-del lp1])
> -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
> -<0> (lp0)
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
> -  [ovn-nbctl: lp2: port already exists with different parent lp3
> -])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
> -  [ovn-nbctl: lp2: port already exists with different tag_request 5
> -])
> -AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
> -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
> -  [ovn-nbctl: lp2: port already exists but has no tag_request
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -
> -AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
> -<0> (ls0)
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
> -  [ovn-nbctl: lp1: port name not found
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 unknown])
> -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
> -00:11:22:33:44:55
> -unknown
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
> -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff
> 00:11:22:33:44:55])
> -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
> -00:11:22:33:44:55
> -aa:bb:cc:dd:ee:ff
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
> -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
> -ovn_nbctl_test_acl() {
> -   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop])
> -   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info acl-add $1
> to-lport 500 udp drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
> -   dnl Add duplicated ACL
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1], [],
> [stderr])
> -   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
> -   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip drop])
> -
> -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
> -from-lport   600 (udp) drop log()
> -from-lport   400 (tcp) drop
> -from-lport   200 (ip) drop
> -  to-lport   500 (udp) drop log(name=test,severity=info)
> -  to-lport   300 (tcp) drop
> -  to-lport   100 (ip) drop
> -])
> -
> -   dnl Delete in one direction.
> -   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
> -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
> -from-lport   600 (udp) drop log()
> -from-lport   400 (tcp) drop
> -from-lport   200 (ip) drop
> -])
> -
> -   dnl Delete all ACLs.
> -   AT_CHECK([ovn-nbctl $2 acl-del $1])
> -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
> -])
> -
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
> -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
> -
> -   dnl Delete a single flow.
> -   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
> -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
> -from-lport   600 (udp) drop
> -from-lport   200 (ip) drop
> -])
> -}
> -
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -ovn_nbctl_test_acl ls0
> -AT_CHECK([ovn-nbctl ls-add ls1])
> -ovn_nbctl_test_acl ls1 --type=switch
> -AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
> -ovn_nbctl_test_acl pg0 --type=port-group
> -
> -dnl Test when port group doesn't exist
> -AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip drop],
> [1], [], [dnl
> -ovn-nbctl: pg1: port group name not found
> -])
> -
> -dnl Test when same name exists in logical switches and portgroups
> -AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
> -AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [], [stderr])
> -AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
> -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip drop],
> [0], [ignore])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100 burst=1000])
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0 rate=300
> burst=3000])
> -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
> -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
> -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301
> burst=30000])
> -
> -dnl Add duplicated qos
> -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302
> burst=30002], [1], [], [stderr])
> -AT_CHECK([grep 'already existed' stderr], [0], [ignore])
> -AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4 dscp=11
> rate=302 burst=30002])
> -
> -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
> -from-lport   600 (tcp) dscp=63
> -from-lport   500 (udp) rate=100 burst=1000
> -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
> -  to-lport   300 (tcp) dscp=48
> -  to-lport   200 (ip) rate=101
> -  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
> -])
> -
> -dnl Delete in one direction.
> -AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
> -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
> -from-lport   600 (tcp) dscp=63
> -from-lport   500 (udp) rate=100 burst=1000
> -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
> -])
> -
> -dnl Delete all qos_rules.
> -AT_CHECK([ovn-nbctl qos-del ls0])
> -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102 rate=301
> dscp=19])
> -
> -dnl Delete a single flow.
> -AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
> -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
> -from-lport   600 (ip) rate=1000101
> -from-lport   200 (ip) rate=301 burst=1000102 dscp=19
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=100010111111],
> [1], [],
> -[ovn-nbctl: 100010111111: rate must be in the range 1...4294967295
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=100010111112
> rate=100010], [1], [],
> -[ovn-nbctl: 100010111112: burst must be in the range 1...4294967295
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], [1], [],
> -[ovn-nbctl: -1: dscp must be in the range 0...63
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], [],
> -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=", and
> "burst="
> -])
> -
> -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123], [1], [],
> -[ovn-nbctl: Either "rate" and/or "dscp" must be specified
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
> -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
> -AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
> -AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
> -AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
> -
> -dnl Add duplicate meter name
> -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [], [stderr])
> -AT_CHECK([grep 'already exists' stderr], [0], [ignore])
> -
> -dnl Add reserved meter name
> -AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [], [stderr])
> -AT_CHECK([grep 'reserved' stderr], [0], [ignore])
> -
> -dnl Add meter with invalid rates
> -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps], [1], [],
> -[ovn-nbctl: rate must be in the range 1...4294967295
> -])
> -
> -dnl Add meter with invalid rates
> -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], [1], [],
> -[ovn-nbctl: rate must be in the range 1...4294967295
> -])
> -
> -AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
> -[ovn-nbctl: rate must be in the range 1...4294967295
> -])
> -
> -dnl Add meter with invalid burst
> -AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps], [1], [],
> -[ovn-nbctl: unit must be "kbps" or "pktps"
> -])
> -
> -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
> -meter1: bands:
> -  drop: 10 kbps
> -meter2: bands:
> -  drop: 3 kbps, 2 kb burst
> -meter3: bands:
> -  drop: 100 kbps, 200 kb burst
> -meter4: bands:
> -  drop: 10 pktps, 30 packet burst
> -])
> -
> -dnl Delete a single meter.
> -AT_CHECK([ovn-nbctl meter-del meter2])
> -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
> -meter1: bands:
> -  drop: 10 kbps
> -meter3: bands:
> -  drop: 100 kbps, 200 kb burst
> -meter4: bands:
> -  drop: 10 pktps, 30 packet burst
> -])
> -
> -dnl Delete all meters.
> -AT_CHECK([ovn-nbctl meter-del])
> -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2], [1], [],
> -[ovn-nbctl: snatt: type must be one of "dnat", "snat" and "dnat_and_snat".
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2], [1], [],
> -[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], [1], [],
> -[ovn-nbctl: 30.0.0: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24 192.168.1.2], [1],
> [],
> -[ovn-nbctl: 30.0.0.2/24: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80 192.168.1.2], [1],
> [],
> -[ovn-nbctl: 30.0.0.2:80: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a], [1], [],
> -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], [1], [],
> -[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80], [1],
> [],
> -[ovn-nbctl: 192.168.1.2:80: should be an IPv4 address or network.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a], [1], [],
> -[ovn-nbctl: 192.168.1.2/a: should be an IPv4 address or network.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a], [1], [],
> -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], [1], [],
> -[ovn-nbctl: 192.168.1: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80], [1],
> [],
> -[ovn-nbctl: 192.168.1.2:80: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24], [1],
> [],
> -[ovn-nbctl: 192.168.1.2/24: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2/24],
> [1], [],
> -[ovn-nbctl: 192.168.1.2/24: should be an IPv4 address.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2
> lp0], [1], [],
> -[ovn-nbctl: lr-nat-add with logical_port must also specify external_mac.
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> -[ovn-nbctl: logical_port and external_mac are only valid when type is
> "dnat_and_snat".
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> -[ovn-nbctl: logical_port and external_mac are only valid when type is
> "dnat_and_snat".
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> -[ovn-nbctl: lp0: port name not found
> -])
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02], [1], [],
> -[ovn-nbctl: invalid mac address 00:00:00:01:02.
> -])
> -
> -dnl Add snat and dnat
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0
> 00:00:00:01:02:03])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> -dnat             30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.2           192.168.1.3
>  00:00:00:01:02:03    lp0
> -snat             30.0.0.1           192.168.1.0/24
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24], [1],
> [],
> -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24: a NAT with this external_ip and
> logical_ip already exists
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24], [1],
> [],
> -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24: a NAT with this external_ip and
> logical_ip already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1
> 192.168.1.0/24])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24], [1],
> [],
> -[ovn-nbctl: a NAT with this type (snat) and logical_ip (192.168.1.0/24)
> already exists
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2], [1], [],
> -[ovn-nbctl: 30.0.0.1, 192.168.1.2: a NAT with this external_ip and
> logical_ip already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3], [1], [],
> -[ovn-nbctl: a NAT with this type (dnat) and external_ip (30.0.0.1)
> already exists
> -])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2],
> [1], [],
> -[ovn-nbctl: 30.0.0.1, 192.168.1.2: a NAT with this external_ip and
> logical_ip already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.1
> 192.168.1.2])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.3],
> [1], [],
> -[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
> (30.0.0.1) already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2
> 192.168.1.3 lp0 00:00:00:04:05:06])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> -dnat             30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.2           192.168.1.3
>  00:00:00:04:05:06    lp0
> -snat             30.0.0.1           192.168.1.0/24
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2
> 192.168.1.3])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> -dnat             30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.2           192.168.1.3
> -snat             30.0.0.1           192.168.1.0/24
> -])
> -
> -dnl Deletes the NATs
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
> -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and external_ip
> (30.0.0.3)
> -])
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
> -[ovn-nbctl: no matching NAT with the type (dnat) and external_ip
> (30.0.0.2)
> -])
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24], [1], [],
> -[ovn-nbctl: no matching NAT with the type (snat) and logical_ip (
> 192.168.10.0/24)
> -])
> -AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat 192.168.10.0/24])
> -
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> -dnat             30.0.0.1           192.168.1.2
> -dnat_and_snat    30.0.0.2           192.168.1.3
> -snat             30.0.0.1           192.168.1.0/24
> -])
> -
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> -dnat_and_snat    30.0.0.2           192.168.1.3
> -snat             30.0.0.1           192.168.1.0/24
> -])
> -
> -AT_CHECK([ovn-nbctl lr-nat-del lr0])
> -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
> -AT_CHECK([ovn-nbctl lr-nat-del lr0])
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
> -dnl Add two LBs.
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a
> 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> -[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP address and
> a port number with : as a separator).
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80
> 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> -[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP address and
> a port number with : as a separator).
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80
> 192.168.10.10:80,192.168.10.20 tcp], [1], [],
> -[ovn-nbctl: 192.168.10.20: should be an IP address and a port number
> with : as a separator.
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a
> 192.168.10.10:80,192.168.10.20:80], [1], [],
> -[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address and a
> port number with : as a separator).
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0 192.168.10.10:80,
> 192.168.10.20:80], [1], [],
> -[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and a port
> number with : as a separator).
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10,
> 192.168.10.20:80], [1], [],
> -[ovn-nbctl: 192.168.10.20:80: should be an IP address.
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:a80],
> [1], [],
> -[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:],
> [1], [],
> -[ovn-nbctl: 192.168.10.10:: should be an IP address.
> -])
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
> 192.168.10.1a], [1], [],
> -[ovn-nbctl: 192.168.10.1a: should be an IP address.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10: 192.168.10.10:80,
> 192.168.10.20:80 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -dnl Add ips to lb
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 ,,,192.168.10.10:80,,,,,])
> -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 ,,,192.168.10.10:80,,,,
> 192.168.10.20:80,,,,])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80
> -<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -])
> -AT_CHECK([ovn-nbctl lb-del lb0])
> -AT_CHECK([ovn-nbctl lb-del lb1])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:80])
> -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:80 tcp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -])
> -
> -dnl Update the VIP of the lb1.
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:8080])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:8080
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:8080 udp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:8080
> -])
> -
> -dnl Config lb1 with another VIP.
> -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 192.168.10.10:80 udp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:8080
> -                                                            udp
> 30.0.0.20:80    192.168.10.10:80
> -])
> -
> -AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:8080
> -])
> -
> -dnl Add LBs whose vip is just an IP address.
> -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
> -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:8080
> -<2>    lb2                 tcp/udp    30.0.0.30       192.168.10.10
> -<3>    lb3                 tcp/udp    30.0.0.30       192.168.10.10
> -])
> -AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
> -AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
> -
> -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080 192.168.10.10:80,
> 192.168.10.20:80 tcp])
> -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080
> 192.168.10.10:80,192.168.10.20:80 tcp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP               IPs
> -<0>    lb0                 tcp        30.0.0.10:80      192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80      192.168.10.10:80,
> 192.168.10.20:8080
> -<2>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,
> 192.168.10.20:80
> -<3>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,
> 192.168.10.20:80
> -])
> -
> -dnl If there are multiple load balancers with the same name, use a UUID
> to update/delete.
> -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080 192.168.10.10:80,
> 192.168.10.20:80 tcp], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
> 192.168.10.10:8080,192.168.10.20:8080 udp])
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080
> 192.168.10.10:8080,192.168.10.20:8080 udp])
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090
> 192.168.10.10:8080,192.168.10.20:8080 udp])
> -AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80])
> -AT_CHECK([ovn-nbctl lb-del lb1])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP               IPs
> -<0>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,
> 192.168.10.20:80
> -])
> -
> -dnl Add load balancer to logical switch.
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:80])
> -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 192.168.10.10:80,
> 192.168.10.20:80 udp])
> -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10 192.168.10.10,192.168.10.20])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
> -
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<2>    lb3                 tcp/udp    30.0.0.10
>  192.168.10.10,192.168.10.20
> -])
> -
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb3                 tcp/udp    30.0.0.10
>  192.168.10.10,192.168.10.20
> -])
> -
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
> -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
> -
> -dnl Remove all load balancers from logical switch.
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
> -AT_CHECK([ovn-nbctl ls-lb-del ls0])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
> -
> -dnl Add load balancer to logical router.
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
> -
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<2>    lb3                 tcp/udp    30.0.0.10
>  192.168.10.10,192.168.10.20
> -])
> -
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP             IPs
> -<0>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,
> 192.168.10.20:80
> -<1>    lb3                 tcp/udp    30.0.0.10
>  192.168.10.10,192.168.10.20
> -])
> -
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
> -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
> -
> -dnl Remove all load balancers from logical router.
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
> -AT_CHECK([ovn-nbctl lr-lb-del lr0])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
> -
> -dnl Remove load balancers after adding them to a logical router/switch.
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl lb-del lb0])
> -AT_CHECK([ovn-nbctl lb-del lb1])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
> -dnl A bunch of commands that should fail
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> -[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP address
> and a port number with : as a separator).
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> -[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP address
> and a port number with : as a separator).
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80
> [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> -[ovn-nbctl: fd0f::20: should be an IP address and a port number with : as
> a separator.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff
> [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> -[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP address and a
> port number with : as a separator).
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
> [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
> -[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
> fd0f::10,[[fd0f::20]]:80], [1], [],
> -[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
> [[fd0f::10]]:a80], [1], [],
> -[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:],
> [1], [],
> -[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 fd0f::1001a],
> [1], [],
> -[ovn-nbctl: fd0f::1001a: should be an IP address.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp], [1], [],
> -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
> -[ovn-nbctl: 192.168.10.10: IP address family is different from VIP
> ae0f::10.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
> -[ovn-nbctl: 192.168.10.10: IP address family is different from VIP
> ae0f::10.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80], [1],
> [],
> -[ovn-nbctl: 192.168.10.10:80: IP address family is different from VIP
> [[ae0f::10]]:80.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
> -[ovn-nbctl: ae0f::10: IP address family is different from VIP 30.0.0.10.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 [[ae0f::10]]:80], [1], [],
> -[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from VIP
> 30.0.0.10:80.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f:0000:0000:0000:0000:0000:0000:0010
> fd0f::20],
> -[1], [], [ovn-nbctl: lb0: a load balancer with this vip (ae0f::10)
> already exists
> -])
> -
> -AT_CHECK([ovn-nbctl lb-del lb0])
> -
> -dnl Add ips to lb
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 ,,,[[fd0f::10]]:80,,,,,])
> -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
> ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80
> -<1>    lb1                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -])
> -AT_CHECK([ovn-nbctl lb-del lb0])
> -AT_CHECK([ovn-nbctl lb-del lb1])
> -
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80])
> -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -])
> -
> -dnl Update the VIP of the lb1.
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -])
> -
> -dnl Config lb1 with another VIP.
> -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 udp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -                                                            udp
> [[ae0f::20]]:80    [[fd0f::10]]:80
> -])
> -
> -AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -])
> -
> -dnl Add LBs whose vip is just an IP address.
> -AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
> -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -<2>    lb2                 tcp/udp    ae0f::30         fd0f::10
> -<3>    lb3                 tcp/udp    ae0f::30         fd0f::10
> -])
> -AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
> -AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
> -
> -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
> -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP                IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:8080
> -<2>    lb2                 tcp        [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<3>    lb2                 tcp        [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -])
> -
> -dnl If there are multiple load balancers with the same name, use a UUID
> to update/delete.
> -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
> [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080
> [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
> -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090
> [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
> -AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
> -AT_CHECK([ovn-nbctl lb-del lb1])
> -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP                IPs
> -<0>    lb2                 tcp        [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb2                 tcp        [[ae0f::10]]:8080
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -])
> -
> -dnl Add load balancer to logical switch.
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80])
> -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
> -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
> -
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<2>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
> -])
> -
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
> -])
> -
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
> -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
> -
> -dnl Remove all load balancers from logical switch.
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
> -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
> -AT_CHECK([ovn-nbctl ls-lb-del ls0])
> -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
> -
> -dnl Add load balancer to logical router.
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
> -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
> -])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
> -
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb0                 tcp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<2>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
> -])
> -
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
> -UUID                                    LB                  PROTO
> VIP              IPs
> -<0>    lb1                 udp        [[ae0f::10]]:80
> [[fd0f::10]]:80,[[fd0f::20]]:80
> -<1>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
> -])
> -
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
> -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
> -
> -dnl Remove all load balancers from logical router.
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
> -AT_CHECK([ovn-nbctl lr-lb-del lr0])
> -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router commands], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
> -<0> (lr0)
> -])
> -
> -AT_CHECK([ovn-nbctl lr-add lr1])
> -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
> -<0> (lr0)
> -<1> (lr1)
> -])
> -
> -AT_CHECK([ovn-nbctl lr-del lr0])
> -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
> -<0> (lr1)
> -])
> -
> -AT_CHECK([ovn-nbctl show lr0])
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
> -  [router <0> (lr0)
> -])
> -AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
> -  [ovn-nbctl: lr0: a router with this name already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
> -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
> -  [router <0> (lr0)
> -])
> -AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
> -AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], [1], [],
> -  [ovn-nbctl: --may-exist and --add-duplicate may not be used together
> -])
> -AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
> -  [ovn-nbctl: Multiple logical routers named 'lr0'.  Use a UUID.
> -])
> -
> -AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
> -  [ovn-nbctl: lr2: router name not found
> -])
> -AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
> -
> -AT_CHECK([ovn-nbctl lr-add])
> -AT_CHECK([ovn-nbctl lr-add])
> -AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
> -  [ovn-nbctl: --add-duplicate requires specifying a name
> -])
> -AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
> -  [ovn-nbctl: --may-exist requires specifying a name
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port
> commands], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02 192.168.1.1/24],
> [1], [],
> -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
> -])
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04 192.168.1.1/24],
> [1], [],
> -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
> -
> -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
> -router <0> (lr0)
> -    port lrp0
> -        mac: "00:00:00:01:02:03"
> -        networks: [["192.168.1.1/24"]]
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24],
> [1], [],
> -  [ovn-nbctl: lrp0: a port with this name already exists
> -])
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0 00:00:00:01:02:03
> 192.168.1.1/24])
> -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
> -<0> (lrp0)
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24
> peer=lrp1-peer])
> -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
> -<0> (lrp0)
> -<1> (lrp1)
> -])
> -
> -AT_CHECK([ovn-nbctl lr-add lr1])
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24],
> [1], [],
> -  [ovn-nbctl: lrp1: a port with this name already exists
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1 00:00:00:01:02:03
> 192.168.1.1/24], [1], [],
> -  [ovn-nbctl: lrp1: port already exists but in router lr0
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:04:05:06
> 192.168.1.1/24], [1], [],
> -  [ovn-nbctl: lrp1: port already exists with mac 00:00:00:01:02:03
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 192.168.1.1/24], [1], [],
> -  [ovn-nbctl: lrp1: port already exists with mismatching peer
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 10.0.0.1/24 peer=lrp1-peer], [1], [],
> -  [ovn-nbctl: lrp1: port already exists with different network
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 192.168.1.1/24 peer=lrp1-peer])
> -
> -AT_CHECK([ovn-nbctl lrp-del lrp1])
> -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
> -<0> (lrp0)
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 192.168.1.1/24 10.0.0.1/24 peer=lrp1-peer])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 192.168.1.1/24 172.16.0.1/24 peer=lrp1-peer], [1], [],
> -  [ovn-nbctl: lrp1: port already exists with different network
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03
> 10.0.0.1/24 192.168.1.1/24 peer=lrp1-peer])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port gateway
> chassis], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
> -
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], [],
> -[ovn-nbctl: lp0: port name not found
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
> -[ovn-nbctl: lp0: port name not found
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], [],
> -[ovn-nbctl: lp0: port name not found
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], [1], [],
> -[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
> -])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
> -
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis1     0
> -])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
> -
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis1    10
> -])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
> -
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis1    20
> -])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis1    20
> -lrp0-chassis2     5
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis2     5
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
> -
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
> -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
> -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
> -lrp0-chassis2    10
> -lrp0-chassis3     5
> -lrp0-chassis1     1
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port enable and
> disable], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
> -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
> -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
> -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
> -])
> -
> -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
> -  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -
> -dnl Check IPv4 routes
> -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24 11.0.1.1 lp0])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.2])
> -
> -dnl Add overlapping route with 10.0.0.1/24
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1], [1], [],
> -  [ovn-nbctl: duplicate prefix: 10.0.0.0/24
> -])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1], [1], [],
> -  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
> -])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a 11.0.0.1], [1], [],
> -  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
> -])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1a], [1], [],
> -  [ovn-nbctl: bad next hop argument: 11.0.0.1a
> -])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1/24], [1], [],
> -  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
> -])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
> 2001:0db8:0:f103::1/64], [1], [],
> -  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24 11.0.0.1])
> -AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24
> 11.0.0.1])
> -
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv4 Routes
> -              10.0.0.0/24                  11.0.0.1 dst-ip
> -              10.0.1.0/24                  11.0.1.1 dst-ip lp0
> -              9.16.1.0/24                  11.0.0.1 src-ip
> -                0.0.0.0/0               192.168.0.1 dst-ip
> -])
> -
> -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24 11.0.0.1
> lp1])
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv4 Routes
> -              10.0.0.0/24                  11.0.0.1 dst-ip lp1
> -              10.0.1.0/24                  11.0.1.1 dst-ip lp0
> -              9.16.1.0/24                  11.0.0.1 src-ip
> -                0.0.0.0/0               192.168.0.1 dst-ip
> -])
> -
> -dnl Delete non-existent prefix
> -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24], [1], [],
> -  [ovn-nbctl: no matching prefix: 10.0.2.0/24
> -])
> -AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24])
> -
> -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24])
> -AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24])
> -
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv4 Routes
> -              10.0.0.0/24                  11.0.0.1 dst-ip lp1
> -                0.0.0.0/0               192.168.0.1 dst-ip
> -])
> -
> -AT_CHECK([ovn-nbctl lr-route-del lr0])
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -])
> -
> -dnl Check IPv6 routes
> -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
> 2001:0db8:0:f101::1])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1
> lp0])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
> 2001:0db8:0:f103::1])
> -
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv6 Routes
> -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
> -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
> -                     ::/0        2001:db8:0:f101::1 dst-ip
> -])
> -
> -AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
> -
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv6 Routes
> -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
> -                     ::/0        2001:db8:0:f101::1 dst-ip
> -])
> -
> -AT_CHECK([ovn-nbctl lr-route-del lr0])
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -])
> -
> -dnl Check IPv4 and IPv6 routes
> -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.1])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
> 2001:0db8:0:f101::1])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1
> lp0])
> -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
> 2001:0db8:0:f103::1])
> -
> -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
> -IPv4 Routes
> -              10.0.0.0/24                  11.0.0.1 dst-ip
> -              10.0.1.0/24                  11.0.1.1 dst-ip lp0
> -                0.0.0.0/0               192.168.0.1 dst-ip
> -
> -IPv6 Routes
> -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
> -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
> -                     ::/0        2001:db8:0:f101::1 dst-ip
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
> -AT_CHECK([ovn-nbctl lr-add lr0])
> -
> -dnl Add policies with allow and drop actions
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24" drop])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24" allow])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24" allow])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" drop])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64" drop])
> -
> -dnl Add duplicated policy
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24" drop],
> [1], [],
> -  [ovn-nbctl: Same routing policy already existed on the logical router
> lr0.
> -])
> -
> -dnl Add duplicated policy
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24" deny],
> [1], [],
> -  [ovn-nbctl: deny: action must be one of "allow", "drop", and "reroute"
> -])
> -
> -dnl Delete by priority and match string
> -AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24"])
> -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
> -Routing Policies
> -       101                              ip4.src == 2.1.1.0/24
>  allow
> -       101                              ip4.src == 2.1.2.0/24
> drop
> -       101                               ip6.src == 2002::/64
> drop
> -       100                              ip4.src == 1.1.2.0/24
>  allow
> -])
> -
> -dnl Delete all policies for given priority
> -AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
> -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
> -Routing Policies
> -       100                              ip4.src == 1.1.2.0/24
>  allow
> -])
> -
> -dnl Add policy with reroute action
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24"
> reroute 3.3.3.3])
> -
> -dnl Add policy with invalid reroute ip
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24"
> reroute 3.3.3.x], [1], [],
> -  [ovn-nbctl: bad next hop argument: 3.3.3.x
> -])
> -
> -dnl Add policy with reroute action
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64" reroute
> 2002::5])
> -
> -dnl Add policy with invalid reroute ip
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64" reroute
> 2002::x], [1], [],
> -  [ovn-nbctl: bad next hop argument: 2002::x
> -])
> -
> -])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> -
> -dnl switchport type defaults to empty
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -
> -])
> -
> -dnl The following are the valid entries for
> -dnl switchport type
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -l2gateway
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -router
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -localnet
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -localport
> -])
> -
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -vtep
> -])
> -
> -dnl All of these are valid southbound port types but
> -dnl should be rejected for northbound logical switch
> -dnl ports.
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
> -ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized. Not
> setting type.
> -])
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
> -ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not setting
> type.
> -])
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], [], [dnl
> -ovn-nbctl: Logical switch port type 'chassisredirect' is unrecognized.
> Not setting type.
> -])
> -
> -dnl switch port type should still be "vtep" since previous
> -dnl commands failed.
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -vtep
> -])
> -
> -dnl Attempt a nonsense type
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
> -ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not setting
> type.
> -])
> -
> -dnl Empty string should work too
> -AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
> -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
> -
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
> -AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection
> ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
> -AT_CHECK([ovn-nbctl list connection | grep inactivity_probe], [0], [dnl
> -inactivity_probe    : 30000
> -inactivity_probe    : 30000
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
> -dnl Check that dry run has no permanent effect.
> -AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)
> -])
> -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
> -])
> -
> -dnl Check that dry-run mode is not sticky.
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
> -AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
> -
> -dnl Expect one line for one command.
> -AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)\n<1> (ls1)
> -])
> -
> -dnl Expect lines for two commands.
> -AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt], [0], [dnl
> -<0> (ls0)\n<1> (ls1)
> -<0> (ls0)\n<1> (ls1)
> -])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error paths], [
> -dnl FIXME: Duplicate options are allowed when passed with global options.
> -dnl        For example: ovn-nbctl --if-exists --if-exists list
> Logical_Switch
> -
> -dnl Duplicate option
> -AT_CHECK([ovn-nbctl -- --if-exists --if-exists list Logical_Switch], [1],
> [], [stderr])
> -AT_CHECK([grep 'option specified multiple times' stderr], [0], [ignore])
> -
> -dnl Missing command
> -AT_CHECK([ovn-nbctl], [1], [], [stderr])
> -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
> -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl --], [1], [], [stderr])
> -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
> -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
> -
> -dnl Unknown command
> -AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
> -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
> -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
> -
> -dnl Unknown option
> -AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], [stderr])
> -AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], [stderr])
> -AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
> -
> -dnl Missing option argument
> -AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
> -AT_CHECK([grep 'option .* requires an argument' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [], [stderr])
> -AT_CHECK([grep 'missing argument to .* option' stderr], [0], [ignore])
> -
> -dnl Unexpected option argument
> -AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1], [],
> [stderr])
> -AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .*
> requires an argument' stderr], [0], [ignore])
> -
> -AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1], [],
> [stderr])
> -AT_CHECK([grep 'option on .* does not accept an argument' stderr], [0],
> [ignore])
> -
> -dnl Not enough arguments
> -AT_CHECK([ovn-nbctl list], [1], [], [stderr])
> -AT_CHECK([grep 'command requires at least .* arguments' stderr], [0],
> [ignore])
> -
> -AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
> -AT_CHECK([grep 'command requires at least .* arguments' stderr], [0],
> [ignore])
> -
> -dnl Too many arguments
> -AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
> -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
> [ignore])
> -
> -AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
> -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
> [ignore])
> -
> -AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
> -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
> [ignore])
> -
> -AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
> -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
> [ignore])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
> -dnl Check that port group can be looked up by name
> -AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
> -AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
> -pg0
> -])])
> -
> -OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
> -dnl This test addresses a specific issue seen when running ovn-nbctl in
> -dnl daemon mode. All we have to do is ensure that each time we list
> database
> -dnl information, there is not an extra newline at the beginning of the
> output.
> -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
> -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
> -name                : sw1
> -])
> -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
> -name                : sw1
> -])])
> -
> -OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
> -dnl This test addresses a specific issue seen when running ovn-nbctl in
> -dnl daemon mode. We need to ensure that table formatting options are
> honored
> -dnl when listing database information.
> -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
> -AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch sw1], [0],
> [dnl
> -sw1
> -])])
> -dnl ---------------------------------------------------------------------
> -
> -OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group commands], [
> -AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
> -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],
> -[pg1
> -])
> -
> -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
> -AT_CHECK([ovn-nbctl list port_group], [0], [])
> -
> -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
> -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
> -SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port sw1-p1)
> -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
> -SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port sw1-p2)
> -
> -AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
> -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],[dnl
> -pg1
> -])
> -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1],
> [0], [dnl
> -$SW1P1
> -])
> -
> -AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
> -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1],
> [0], [dnl
> -$SW1P2
> -])
> -
> -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
> -AT_CHECK([ovn-nbctl list port_group], [0], [])
> -])
> -
> -AT_SETUP([ovn-nbctl - daemon retry connection])
> -OVN_NBCTL_TEST_START daemon
> -AT_CHECK([kill `cat ovsdb-server.pid`])
> -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
> --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
> -AT_CHECK([ovn-nbctl show], [0], [ignore])
> -OVN_NBCTL_TEST_STOP /Terminated/d
> -AT_CLEANUP
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> deleted file mode 100644
> index 62e58fd..0000000
> --- a/tests/ovn-northd.at
> +++ /dev/null
> @@ -1,900 +0,0 @@
> -AT_BANNER([OVN northd])
> -AT_SETUP([ovn -- check   from NBDB to SBDB])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
> -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
> -
> -# Connect alice to R1 as distributed router gateway port on hv2
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
> -
> -ovn-nbctl --wait=sb \
> -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
> -                                     chassis_name=gw1 \
> -                                     priority=20 -- \
> -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
> -                                     chassis_name=gw2 \
> -                                     priority=10 -- \
> -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
> -
> -nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find Gateway_Chassis
> name="alice_gw1"`
> -
> -# With the new ha_chassis_group table added, there should be no rows in
> -# gateway_chassis table in SB DB.
> -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
> -])
> -
> -# There should be one ha_chassis_group with the name "alice"
> -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="alice"`
> -
> -AT_CHECK([test $ha_chassi_grp_name = alice])
> -
> -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group
> name=alice`
> -
> -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
> -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
> -])
> -
> -# There should be one ha_chassis_group with the name "alice"
> -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="alice"`
> -
> -AT_CHECK([test $ha_chassi_grp_name = alice])
> -
> -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group
> name=alice`
> -
> -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
> -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
> -])
> -
> -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
> -# Trim the spaces.
> -ha_ch=`echo $ha_ch | sed 's/ //g'`
> -
> -ha_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list="$ha_ch_list $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
> -
> -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
> -
> -# Delete chassis - gw2 in SB DB.
> -# ovn-northd should not recreate ha_chassis rows
> -# repeatedly when gw2 is deleted.
> -ovn-sbctl chassis-del gw2
> -
> -ha_ch_list_1=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list_1="$ha_ch_list_1 $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
> -
> -ha_ch_list_2=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list_2="$ha_ch_list_2 $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
> -
> -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
> -
> -# Add back the gw2 chassis
> -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
> -
> -# delete the 2nd Gateway_Chassis on NBDB for alice port
> -gw_ch=`ovn-sbctl --bare --columns gateway_chassis find port_binding \
> -logical_port="cr-alice"`
> -AT_CHECK([test "$gw_ch" = ""])
> -
> -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
> -ha_ch=`echo $ha_ch | sed 's/ //g'`
> -# Trim the spaces.
> -echo "ha ch in grp = $ha_ch"
> -
> -ha_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list="$ha_ch_list $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
> -
> -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
> -
> -# delete the 2nd Gateway_Chassis on NBDB for alice port
> -ovn-nbctl --wait=sb set Logical_Router_Port alice
> gateway_chassis=${nb_gwc1_uuid}
> -
> -# There should be only 1 row in ha_chassis SB DB table.
> -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0],
> [1
> -])
> -
> -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
> -])
> -
> -# There should be only 1 row in ha_chassis SB DB table.
> -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0],
> [1
> -])
> -
> -# delete all the gateway_chassis on NBDB for alice port
> -
> -ovn-nbctl --wait=sb clear Logical_Router_Port alice gateway_chassis
> -
> -# expect that the ha_chassis doesn't exist anymore
> -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
> -])
> -
> -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
> -])
> -
> -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
> -])
> -
> -# expect that the ha_chassis doesn't exist anymore
> -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
> -])
> -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to SBDB
> backwards compatibility])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
> -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
> -
> -ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
> -
> -
> -# It should be converted to ha_chassis_group entries in SBDB, and
> -# still redirect-chassis is kept for backwards compatibility
> -
> -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
> -])
> -
> -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0],
> [1
> -])
> -
> -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group | wc
> -l], [0], [1
> -])
> -
> -# There should be one ha_chassis_group with the name "bob_gw1"
> -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="bob_gw1"`
> -
> -AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
> -
> -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group
> name=bob_gw1`
> -
> -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
> -logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
> -])
> -
> -ovn-nbctl --wait=sb remove Logical_Router_Port bob options
> redirect-chassis
> -
> -# expect that the ha_chassis/ha_chassis_group doesn't exist anymore
> -
> -AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
> -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
> -])
> -
> -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check up state of VIF LSP])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add S1
> -ovn-nbctl --wait=sb lsp-add S1 S1-vm1
> -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
> -
> -ovn-sbctl chassis-add hv1 geneve 127.0.0.1
> -ovn-sbctl lsp-bind S1-vm1 hv1
> -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check up state of router LSP linked to a distributed LR])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
> -
> -ovn-nbctl ls-add S1
> -ovn-nbctl lsp-add S1 S1-R1
> -ovn-nbctl lsp-set-type S1-R1 router
> -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
> -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
> -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check up state of router LSP linked to a gateway LR])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
> -
> -ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
> -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
> -
> -ovn-nbctl ls-add S1
> -ovn-nbctl lsp-add S1 S1-R1
> -ovn-nbctl lsp-set-type S1-R1 router
> -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
> -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
> -
> -ovn-sbctl lsp-bind S1-R1 gw1
> -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check up state of router LSP linked to an LRP with set
> Gateway Chassis])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
> -ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
> -
> -ovn-nbctl ls-add S1
> -ovn-nbctl lsp-add S1 S1-R1
> -ovn-nbctl lsp-set-type S1-R1 router
> -ovn-nbctl lsp-set-addresses S1-R1 router
> -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
> -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
> -ovn_start
> -
> -ovn-nbctl lr-add ro
> -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
> -ovn-nbctl ls-add sw
> -ovn-nbctl lsp-add sw sw-ro
> -ovn-nbctl lsp-set-type sw-ro router
> -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
> -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
> -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:mtu=1280
> -
> -uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding
> logical_port=ro-sw)
> -
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_send_periodic],
> -[0], ["true"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_address_mode],
> -[0], [slaac
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[0], ["600"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[0], ["200"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
> -[0], ["1280"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_eth],
> -[0], ["00:00:00:00:00:01"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_addr],
> -[0], ["fe80::200:ff:fe00:1"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_prefixes],
> -[0], ["aef0::/64"
> -])
> -
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=300
> -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
> ipv6_ra_configs:min_interval=600
> -
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[0], ["300"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[0], ["225"
> -])
> -
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=300
> -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
> ipv6_ra_configs:min_interval=250
> -
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[0], ["300"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[0], ["225"
> -])
> -
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=0
> -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
> ipv6_ra_configs:min_interval=0
> -
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[0], ["4"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[0], ["3"
> -])
> -
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=3600
> -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
> ipv6_ra_configs:min_interval=2400
> -
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[0], ["1800"
> -])
> -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[0], ["1350"
> -])
> -
> -ovn-nbctl --wait=sb set Logical_Router_port ro-sw
> ipv6_ra_configs:send_periodic=false
> -
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_send_periodic],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in Port_Binding
> record "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_max_interval],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_min_interval],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_mtu],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_address_mode],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_src_eth],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_src_addr],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding record
> "${uuid}" column options
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
> options:ipv6_ra_prefixes],
> -[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding record
> "${uuid}" column options
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- test unixctl])
> -ovn_init_db ovn-sb; ovn-sbctl init
> -ovn_init_db ovn-nb; ovn-nbctl init
> -
> -# test unixctl option
> -mkdir "$ovs_base"/northd
> -as northd start_daemon ovn-northd
> --unixctl="$ovs_base"/northd/ovn-northd.ctl
> --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
> --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -ovn-nbctl ls-add sw
> -ovn-nbctl --wait=sb lsp-add sw p1
> -# northd created with unixctl option successfully created port_binding
> entry
> -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
> logical_port="p1" | wc -l], [0], [1
> -])
> -AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
> -
> -# ovs-appctl exit with unixctl option
> -OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl],
> ["$ovs_base"/northd/ovn-northd.pid])
> -
> -# Check no port_binding entry for new port as ovn-northd is not running
> -ovn-nbctl lsp-add sw p2
> -ovn-nbctl --timeout=10 --wait=sb sync
> -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
> logical_port="p2" | wc -l], [0], [0
> -])
> -
> -# test default unixctl path
> -as northd start_daemon ovn-northd
> --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
> --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -ovn-nbctl --wait=sb lsp-add sw p3
> -# northd created with default unixctl path successfully created
> port_binding entry
> -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
> logical_port="p3" | wc -l], [0], [1
> -])
> -
> -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])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to SBDB])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
> -
> -# ovn-northd should not create HA chassis group and HA chassis rows
> -# unless the HA chassis group in OVN NB DB is associated to
> -# a logical router port or logical port of type external.
> -AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group
> name="hagrp1" \
> -| wc -l], [0], [0
> -])
> -
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
> -
> -# There should be no HA_Chassis rows in SB DB.
> -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
> -| grep -v '-' | wc -l ], [0], [0
> -])
> -
> -# Add chassis ch1.
> -ovn-sbctl chassis-add ch1 geneve 127.0.0.2
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc -l`])
> -
> -# There should be no HA_Chassis rows
> -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
> -| grep -v '-' | wc -l ], [0], [0
> -])
> -
> -# Create a logical router port and attach ha chassis group.
> -ovn-nbctl lr-add lr0
> -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
> -
> -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group
> name=hagrp1`
> -ovn-nbctl set logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Make sure that ovn-northd doesn't recreate the ha_chassis
> -# records if the chassis record is missing in SB DB.
> -
> -ha_ch_list_1=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list_1="$ha_ch_list_1 $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
> -
> -ha_ch_list_2=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list_2="$ha_ch_list_2 $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
> -
> -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
> -
> -# 2 HA chassis should be created with 'chassis' column empty because
> -# we have not added hv1 and hv2 chassis to the SB DB.
> -AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis | awk
> '{print $3}' \
> -| grep -v '-' | wc -l`])
> -
> -# We should have 1 ha chassis with 'chassis' column set for hv1
> -AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | awk '{print $3}' \
> -| grep '-' | wc -l`])
> -
> -# Create another logical router port and associate to the same
> ha_chasis_group
> -ovn-nbctl lr-add lr1
> -ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14 182.168.0.100/24
> -
> -ovn-nbctl set logical_router_port lr1-public ha_chassis_group=$hagrp1_uuid
> -
> -# We should still have 1 HA chassis group and 3 HA chassis in SB DB.
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Change the priority of ch1 - ha chassis in NB DB. It should get
> -# reflected in SB DB.
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority find \
> -ha_chassis | grep 100 | wc -l`])
> -
> -# Delete ch1 HA chassis in NB DB.
> -ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
> -
> -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Add back the ha chassis
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
> -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Delete lr0-public. We should still have 1 HA chassis group and
> -# 3 HA chassis in SB DB.
> -ovn-nbctl --wait=sb lrp-del lr0-public
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Delete lr1-public. There should be no HA chassis group in SB DB.
> -ovn-nbctl --wait=sb lrp-del lr1-public
> -
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc -l`])
> -
> -# Add lr0-public again
> -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
> -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> set logical_router_port
> lr0-public ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Create a Gateway chassis. ovn-northd should ignore this.
> -ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
> -
> -# There should be only 1 HA chassis group in SB DB with the
> -# name hagrp1.
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group | wc -l`])
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Now delete HA chassis group. ovn-northd should create HA chassis group
> -# with the Gateway chassis name
> -ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
> -ovn-nbctl ha-chassis-group-del hagrp1
> -
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="lr0-public" | wc -l`])
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
> -find ha_chassis | wc -l`])
> -
> -ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="lr0-public" | wc -l`])
> -
> -ovn-sbctl --bare --columns _uuid find ha_chassis
> -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Test if 'ref_chassis' column is properly set or not in
> -# SB DB ha_chassis_group.
> -ovn-nbctl ls-add sw0
> -ovn-nbctl lsp-add sw0 sw0-p1
> -
> -ovn-sbctl chassis-add ch2 geneve 127.0.0.3
> -ovn-sbctl chassis-add ch3 geneve 127.0.0.4
> -ovn-sbctl chassis-add comp1 geneve 127.0.0.5
> -ovn-sbctl chassis-add comp2 geneve 127.0.0.6
> -
> -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
> -ovn-nbctl lsp-add sw0 sw0-lr0
> -ovn-nbctl lsp-set-type sw0-lr0 router
> -ovn-nbctl lsp-set-addresses sw0-lr0 router
> -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
> -
> -ovn-sbctl lsp-bind sw0-p1 comp1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
> -
> -comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp1"`
> -comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp2"`
> -ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp1"`
> -
> -echo "comp1_ch_uuid = $comp1_ch_uuid"
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp1_ch_uuid" = "$ref_ch_list"])
> -
> -# unbind sw0-p1
> -ovn-sbctl lsp-unbind sw0-p1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "" = "$ref_ch_list"])
> -
> -# Bind sw0-p1 in comp2
> -ovn-sbctl lsp-bind sw0-p1 comp2
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp2_ch_uuid" = "$ref_ch_list"])
> -
> -ovn-nbctl ls-add sw1
> -ovn-nbctl lsp-add sw1 sw1-p1
> -ovn-nbctl lr-add lr1
> -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
> -ovn-nbctl lsp-add sw1 sw1-lr1
> -ovn-nbctl lsp-set-type sw1-lr1 router
> -ovn-nbctl lsp-set-addresses sw1-lr1 router
> -ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
> -
> -# Bind sw1-p1 in comp1.
> -ovn-sbctl lsp-bind sw1-p1 comp1
> -# Wait until sw1-p1 is up
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
> -
> -# sw1-p1 is not connected to lr0. So comp1 should not be in 'ref_chassis'
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp2_ch_uuid" = "$ref_ch_list"])
> -
> -# Now attach sw0 to lr1
> -ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
> -ovn-nbctl lsp-add sw0 sw0-lr1
> -ovn-nbctl lsp-set-type sw0-lr1 router
> -ovn-nbctl lsp-set-addresses sw0-lr1 router
> -ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
> -
> -# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is indirectly
> -# connected to lr0
> -exp_ref_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
> -do
> -    if test $i = $comp1_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    elif test $i = $comp2_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    fi
> -done
> -
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# Unind sw1-p1. comp2 should not be in the ref_chassis.
> -ovn-sbctl lsp-unbind sw1-p1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp2_ch_uuid" = "$ref_ch_list"])
> -
> -# Create sw2 and attach it to lr2
> -ovn-nbctl ls-add sw2
> -ovn-nbctl lsp-add sw2 sw2-p1
> -ovn-nbctl lr-add lr2
> -ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
> -ovn-nbctl lsp-add sw2 sw2-lr2
> -ovn-nbctl lsp-set-type sw2-lr2 router
> -ovn-nbctl lsp-set-addresses sw2-lr2 router
> -ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
> -
> -# Bind sw2-p1 to comp1
> -ovn-sbctl lsp-bind sw2-p1 comp1
> -# Wait until sw2-p1 is up
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
> -
> -# sw2-p1 is not connected to lr0. So comp1 should not be in 'ref_chassis'
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp2_ch_uuid" = "$ref_ch_list"])
> -
> -# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected to lr0.
> -ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
> -ovn-nbctl lsp-add sw1 sw1-lr2
> -ovn-nbctl lsp-set-type sw1-lr2 router
> -ovn-nbctl lsp-set-addresses sw1-lr2 router
> -ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
> -
> -# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2) should be in
> -# 'ref_chassis'
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# Create sw0-p2 and bind it to comp1
> -ovn-nbctl lsp-add sw0 sw0-p2
> -ovn-sbctl lsp-bind sw0-p2 comp1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# unbind sw0-p2
> -ovn-sbctl lsp-unbind sw0-p2
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# Delete lr1-sw0. comp1 should be deleted from ref_chassis as there is no
> link
> -# from sw1 and sw2 to lr0.
> -ovn-nbctl lrp-del lr1-sw0
> -
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$comp2_ch_uuid" = "$ref_ch_list"])
> -
> -# Set redirect-chassis option to lr0-public. It should be ignored.
> -ovn-nbctl set logical_router_port lr0-public options:redirect-chassis=ch1
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group | wc -l`])
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="lr0-public" | wc -l`])
> -
> -ovn-sbctl --bare --columns _uuid find ha_chassis
> -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Delete the gateway chassis. HA chassis group should be created in SB DB
> -# for the redirect-chassis option.
> -ovn-nbctl clear logical_router_port lr0-public gateway_chassis
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group | wc -l`])
> -
> -ovn-sbctl list ha_chassis_group
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="lr0-public_ch1" | wc -l`])
> -
> -ovn-sbctl --bare --columns _uuid find ha_chassis
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep chassis |
> -grep -v chassis-name | wc -l`])
> -
> -# Clear the redirect-chassis option.
> -ovn-nbctl clear logical_router_port lr0-public options
> -
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
> -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
> -
> -# Delete old sw0.
> -ovn-nbctl ls-del sw0
> -
> -# Create external logical ports and associate ha_chassis_group
> -ovn-nbctl ls-add sw0
> -ovn-nbctl lsp-add sw0 sw0-pext1
> -ovn-nbctl lsp-add sw0 sw0-pext2
> -ovn-nbctl lsp-add sw0 sw0-p1
> -
> -ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 10.0.0.3"
> -ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 10.0.0.4"
> -ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
> -
> -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
> -
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
> -
> -# ovn-northd should not create HA chassis group and HA chassis rows
> -# unless the HA chassis group in OVN NB DB is associated to
> -# a logical router port or logical port of type external.
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
> -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
> -
> -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group \
> -name=hagrp1`
> -
> -# The type of the lsp - sw0-pext1 is still not set to external.
> -# So ha_chassis_group should be ignored.
> -ovn-nbctl set logical_switch_port sw0-pext1 ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc -l`])
> -
> -# Set the type of sw0-pext1 to external
> -ovn-nbctl lsp-set-type sw0-pext1 external
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group \
> -name=hagrp1`
> -
> -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
> -ha_chassis_group find port_binding logical_port=sw0-pext1`])
> -
> -# Set the type of sw0-pext2 to external and associate ha_chassis_group
> -ovn-nbctl lsp-set-type sw0-pext2 external
> -ovn-nbctl set logical_switch_port sw0-pext2 ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
> -grep -v chassis-name | wc -l`])
> -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
> -ha_chassis_group find port_binding logical_port=sw0-pext1`])
> -
> -OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
> -ha_chassis_group find port_binding logical_port=sw0-pext2`])
> -
> -# sw0-p1 is a normal port. So ha_chassis_group should not be set
> -# in port_binding.
> -ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
> -ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
> port_binding \
> -logical_port=sw0-p1) = x], [0], [])
> -
> -# Clear ha_chassis_group for sw0-pext1
> -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1 ha_chassis_group
> -
> -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
> port_binding \
> -logical_port=sw0-pext1) = x], [0], [])
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="hagrp1" | wc -l`])
> -
> -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -# Clear ha_chassis_group for sw0-pext2
> -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2 ha_chassis_group
> -
> -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
> port_binding \
> -logical_port=sw0-pext2) = x], [0], [])
> -
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
> -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
> -
> -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])
> -
> -AT_CLEANUP
> diff --git a/tests/ovn-performance.at b/tests/ovn-performance.at
> deleted file mode 100644
> index a8a15f8..0000000
> --- a/tests/ovn-performance.at
> +++ /dev/null
> @@ -1,424 +0,0 @@
> -#
> -# Tests targeting performance of OVN components.
> -#
> -
> -m4_divert_push([PREPARE_TESTS])
> -
> -# vec_cmp VALUE_VEC OP-VALUE_VEC
> -#
> -# Compares each value from VALUE_VEC to the operator-value pair from the
> -# OP-VALUE_VEC.
> -#
> -# VALUE_VEC must be a list of values separated by a character from $IFS.
> -# OP-VALUE_VEC must be a list of operator-value expressions separated by a
> -# character from $IFS.  Operator-value expressions cannot contain any
> characters
> -# from $IFS like spaces. '=' is treated as an equality operator ('==') for
> -# conciseness.
> -#
> -# Returns the result of each comparison as a list of boolean values (0 or
> 1)
> -# separated by a new-line character.
> -vec_cmp() {
> -    local a b i j
> -
> -    i=0
> -    for a in $1; do
> -        j=0
> -        for b in $2; do
> -            if test $i -eq $j; then
> -                # Replace assignment '=' with equality comparison '=='
> -                case "$b" in
> -                =[[0-9]]*) b="=$b" ;;
> -                esac
> -
> -                echo $(($a $b))
> -                break
> -            fi
> -            j=$((j + 1))
> -        done
> -        i=$((i + 1))
> -    done
> -}
> -
> -# vec_sub VEC_A VEC_B
> -#
> -# Subtracts two vectors:
> -#
> -#     VEC_A = [a1, a2, ...]
> -#     VEC_B = [b1, b2, ...]
> -#     OUT = [(a1 - b1), (a2 - b2), ...]
> -#
> -# VEC_A and VEC_B must be lists of values separated by a character from
> $IFS.
> -vec_sub() {
> -    local a b i j
> -
> -    i=0
> -    for a in $1; do
> -        j=0
> -        for b in $2; do
> -            if test $i -eq $j; then
> -                echo $((a - b))
> -                break
> -            fi
> -            j=$((j + 1))
> -        done
> -        i=$((i + 1))
> -    done
> -}
> -
> -# vec_fold VEC OP
> -#
> -# Reduces a vector to a single value by applying the binary operator OP
> (i.e.,
> -# one that requires two arguments) cumulatively to all vector elements
> from left
> -# to right:
> -#
> -#     VEC = [e1, e2, e3 ...]
> -#     OUT = (...((e1 OP e2) OP e3) OP ...)
> -#
> -# VEC must be a list of values separated by a character from $IFS.
> -vec_fold() {
> -    local first op prod
> -
> -    first=1
> -    op=$2
> -    for a in $1; do
> -        if test $first -eq 1; then
> -            prod=$a
> -            first=0
> -        else
> -            prod=$((prod $op a))
> -        fi
> -    done
> -    echo $prod
> -}
> -
> -# read_counters SANDBOXES TARGET COUNTER
> -#
> -# Prints out the coverage COUNTER for the TARGET in each of the SANDBOXES.
> -#
> -# SANDBOXES must be a list of strings separated by a character from $IFS.
> -read_counters() {
> -    local sims="$1" target="$2" counter="$3"
> -
> -    for sim in $sims; do
> -        as $sim ovs-appctl -t "$target" coverage/read-counter "$counter"
> || return 1
> -    done
> -}
> -
> -# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
> -#
> -# Runs the COMMAND and reports the COUNTER change registered during the
> command
> -# run for the given TARGET in each of the SANDBOXES.
> -counter_delta_() {
> -    local sims="$1" target="$2" counter="$3" cmd="$4"
> -    local before after
> -
> -    before=$(read_counters "$sims" "$target" "$counter") || return 1
> -    eval "$cmd" >/dev/null || return 1
> -    after=$(read_counters "$sims" "$target" "$counter") || return 1
> -
> -    vec_sub "$after" "$before"
> -}
> -
> -# counter_delta SANDBOXES TARGET COUNTER COMMAND
> -#
> -# Same as counter_delta_ but also prints the COUNTER values together with
> the
> -# COMMAND to standard error.
> -counter_delta() {
> -    local cmd="$4"
> -    local v
> -
> -    v=$(counter_delta_ "$@") || return 1
> -
> -    # Dump the counters and the command for troubleshooting
> -    echo "$v" | tr '\n' '\t' >&2
> -    echo "$cmd" >&2
> -
> -    echo "$v"
> -}
> -
> -# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
> -#
> -# Check if COUNTER change in the TARGET app in each of the SANDBOXES after
> -# running the COMMAND meets the conditions listed as operator-value pairs
> in
> -# CONDS.
> -vec_cmp_counter_delta() {
> -    local v
> -
> -    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
> -    v=$(vec_cmp "$v" "$4") || return 1
> -    v=$(vec_fold "$v" "&&") || return 1
> -
> -    echo "$v"
> -}
> -
> -# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
> -#
> -# Check if COUNTER change in the TARGET app in each of the SANDBOXES after
> -# running the COMMAND meets the COND condition given as a operator-value
> pair.
> -cmp_counter_delta() {
> -    local conds=""
> -
> -    # Use the same condition for each sandbox
> -    for _ in $1; do
> -        conds="$conds $4"
> -    done
> -
> -    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
> -}
> -
> -m4_divert_pop([PREPARE_TESTS])
> -
> -# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
> -#
> -# Runs the COMMAND and checks if the COUNTER value for the TARGET in all
> of
> -# the SANDBOXES did not change.
> -m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
> -    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
> -    rc=$?
> -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
> -])
> -
> -# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER COMMAND
> -#
> -# Runs the COMMAND and checks if the COUNTER value for the TARGET in
> -# all of the SANDBOXES has changed.
> -m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
> -    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
> -    rc=$?
> -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
> -])
> -
> -# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
> -#
> -# Runs the COMMAND and checks if the COUNTER value for the TARGET in all
> of the
> -# SANDBOXES satisfies the conditions listed in CONDS.
> -m4_define([CHECK_COUNTER_DELTA_COND],[
> -    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
> -    rc=$?
> -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
> -])
> -
> -# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
> -#
> -# Checks if the COUNTER value has changed for any of the ovn-controller
> -# processes in the SANDBOXES when the COMMAND was run.
> -m4_define([OVN_CONTROLLER_EXPECT_HIT],[
> -    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2], [$3])
> -])
> -
> -# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
> -#
> -# Checks if the COUNTER value has not changed for any of the
> ovn-controller
> -# processes in the SANDBOXES when the COMMAND was run.
> -m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
> -    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], [$3])
> -])
> -
> -# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
> -#
> -# Checks if the change of the COUNTER value, when the COMMAND was run, of
> the
> -# ovn-controller process in each of the SANDBOXES meets the conditions in
> -# CONDS. CONDS must be a list of operator-value pairs, for example "[>0
> =0]",
> -# following the same order as SANDBOXES.
> -m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
> -    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3], [$4])
> -])
> -
> -AT_SETUP([ovn -- ovn-controller incremental processing])
> -# Check which operations the trigger full logical flow processing.
> -#
> -# Create and destroy logical routers, switches, ports, address sets and
> ACLs
> -# while counting calls to lflow_run() in ovn-controller.
> -
> -ovn_start
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -done
> -
> -# Add router lr1
> -OVN_CONTROLLER_EXPECT_HIT(
> -    [hv1 hv2], [lflow_run],
> -    [ovn-nbctl --wait=hv lr-add lr1]
> -)
> -
> -for i in 1 2; do
> -    ls=ls$i
> -    lsp=$ls-lr1
> -    lrp=lr1-$ls
> -
> -    # Add switch $ls
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv ls-add $ls]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config
> subnet=10.0.$i.0/24]
> -    )
> -
> -    # Add router port to $ls
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01
> 10.0.$i.1/24]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
> -    )
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
> -    )
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-set-options $lsp router-port=$lrp]
> -    )
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
> -    )
> -done
> -
> -get_lsp_uuid () {
> -    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
> -}
> -
> -pg_ports=
> -
> -for i in 1 2; do
> -    j=$((i%2 + 1))
> -    as=as$i
> -    ls=ls$i
> -    lp=lp$i
> -    vif=vif$i
> -
> -    # Add port $lp
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-add $ls $lp]
> -    )
> -
> -    pg_ports="$pg_port `get_lsp_uuid $lp`"
> -
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl wait-until Logical_Switch_Port $lp
> dynamic_addresses!=[[]] &&
> -         ovn-nbctl --wait=hv sync]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl get Logical_Switch_Port $lp dynamic_addresses &&
> -         ovn-nbctl --wait=hv sync]
> -    )
> -
> -    # Add address set $as
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv create Address_Set name="$as"]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv add Address_Set "$as" addresses "10.0.$i.10"]
> -    )
> -
> -    # Add ACLs for port $lp
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport ==
> \"$lp\" && ip4.src == \$$as' allow]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport ==
> \"$lp\"' drop]
> -    )
> -
> -    # Bind port $lp and wait for it to come up
> -    OVN_CONTROLLER_EXPECT_HIT_COND(
> -        [hv$i hv$j], [lflow_run], [>0 =0],
> -        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface $vif
> external-ids:iface-id=$lp &&
> -         ovn-nbctl wait-until Logical_Switch_Port $lp 'up=true' &&
> -         ovn-nbctl --wait=hv sync]
> -    )
> -done
> -
> -for i in 1 2; do
> -    j=$((i%2 + 1))
> -    as=as$i
> -    ls=ls$i
> -    lp=lp$i
> -
> -    # Delete ACLs for port $lp
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport ==
> \"$lp\" && ip4.src == \$$as']
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport ==
> \"$lp\"']
> -    )
> -
> -    # Delete address set $as
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses
> "10.0.$i.10"]
> -    )
> -    OVN_CONTROLLER_EXPECT_NO_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
> -    )
> -done
> -
> -OVN_CONTROLLER_EXPECT_NO_HIT(
> -    [hv1 hv2], [lflow_run],
> -    [ovn-nbctl --wait=hv create Port_Group name=pg1 ports=\"$pg_ports\"]
> -)
> -
> -# Add ACLs for port group pg1
> -OVN_CONTROLLER_EXPECT_NO_HIT(
> -    [hv1 hv2], [lflow_run],
> -    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport == @pg1 &&
> ip4.src == $pg1_ip4' allow]
> -)
> -
> -for i in 1 2; do
> -    j=$((i%2 + 1))
> -    lp=lp$i
> -
> -    # Delete port $lp
> -    OVN_CONTROLLER_EXPECT_HIT_COND(
> -        [hv$i hv$j], [lflow_run], [>0 =0],
> -        [ovn-nbctl --wait=hv lsp-del $lp]
> -    )
> -done
> -
> -# Delete port group pg1
> -OVN_CONTROLLER_EXPECT_NO_HIT(
> -    [hv1 hv2], [lflow_run],
> -    [ovn-nbctl --wait=hv destroy Port_Group pg1]
> -)
> -
> -for i in 1 2; do
> -    ls=ls$i
> -
> -    # Delete switch $ls
> -    OVN_CONTROLLER_EXPECT_HIT(
> -        [hv1 hv2], [lflow_run],
> -        [ovn-nbctl --wait=hv ls-del $ls]
> -    )
> -done
> -
> -# Delete router lr1
> -OVN_CONTROLLER_EXPECT_HIT(
> -    [hv1 hv2], [lflow_run],
> -    [ovn-nbctl --wait=hv lr-del lr1]
> -)
> -
> -OVN_CLEANUP([hv1], [hv2])
> -
> -AT_CLEANUP
> diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at
> deleted file mode 100644
> index 650e357..0000000
> --- a/tests/ovn-sbctl.at
> +++ /dev/null
> @@ -1,150 +0,0 @@
> -AT_BANNER([ovn-sbctl])
> -
> -# OVN_SBCTL_TEST_START
> -m4_define([OVN_SBCTL_TEST_START],
> -  [dnl Create databases (ovn-nb, ovn-sb).
> -   AT_KEYWORDS([ovn])
> -   for daemon in ovn-nb ovn-sb; do
> -      AT_CHECK([ovsdb-tool create $daemon.db
> $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
> -   done
> -
> -   dnl Start ovsdb-servers.
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovnnb_db.pid
> --unixctl=$OVS_RUNDIR/ovnnb_db.ctl --log-file=ovsdb_nb.log
> --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db ], [0], [], [stderr])
> -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovnsb_db.pid
> --unixctl=$OVS_RUNDIR/ovnsb_db.ctl --log-file=ovsdb_sb.log
> --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db], [0], [], [stderr])
> -   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d
> -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
> -   AT_CAPTURE_FILE([ovsdb-server.log])
> -
> -   dnl Start ovn-northd.
> -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file
> --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock
> --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
> -   on_exit "kill `cat ovn-northd.pid`"
> -   AT_CHECK([[sed < stderr '
> -/vlog|INFO|opened log file/d']])
> -   AT_CAPTURE_FILE([ovn-northd.log])
> -])
> -
> -# OVN_SBCTL_TEST_STOP
> -m4_define([OVN_SBCTL_TEST_STOP],
> -  [AT_CHECK([check_logs "$1"])
> -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
> -   OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl],
> [$OVS_RUNDIR/ovnnb_db.pid])
> -   OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl],
> [$OVS_RUNDIR/ovnsb_db.pid])])
> -
> -dnl ---------------------------------------------------------------------
> -
> -AT_SETUP([ovn-sbctl - chassis commands])
> -OVN_SBCTL_TEST_START
> -ovn_init_db ovn-sb
> -
> -AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
> -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list
> encap | sort],
> -         [0], [dnl
> -1.2.3.4,geneve
> -])
> -
> -AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
> -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list
> encap | sort],
> -         [0], [dnl
> -1.2.3.4,geneve
> -1.2.3.5,geneve
> -1.2.3.5,stt
> -1.2.3.5,vxlan
> -])
> -
> -AT_CHECK([ovn-sbctl chassis-del ch0])
> -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list
> encap | sort],
> -         [0], [dnl
> -1.2.3.5,geneve
> -1.2.3.5,stt
> -1.2.3.5,vxlan
> -])
> -
> -OVN_SBCTL_TEST_STOP
> -as ovn-sb
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -AT_CLEANUP
> -
> -dnl ---------------------------------------------------------------------
> -
> -AT_SETUP([ovn-sbctl])
> -OVN_SBCTL_TEST_START
> -
> -AT_CHECK([ovn-nbctl ls-add br-test])
> -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
> -AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
> -AT_CHECK([ovn-nbctl --wait=sb sync])
> -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
> -
> -AT_CHECK([ovn-sbctl show], [0], [dnl
> -Chassis ch0
> -    Encap stt
> -        ip: "1.2.3.5"
> -        options: {csum="true"}
> -    Port_Binding vif0
> -])
> -
> -# adds another 'vif1'
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
> -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
> -
> -AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
> -Chassis ch0
> -    Encap stt
> -        ip: "1.2.3.5"
> -        options: {csum="true"}
> -    Port_Binding vif
> -    Port_Binding vif
> -])
> -
> -# deletes 'vif1'
> -AT_CHECK([ovn-nbctl lsp-del vif1])
> -AT_CHECK([ovn-nbctl --wait=sb sync])
> -
> -AT_CHECK([ovn-sbctl show], [0], [dnl
> -Chassis ch0
> -    Encap stt
> -        ip: "1.2.3.5"
> -        options: {csum="true"}
> -    Port_Binding vif0
> -])
> -
> -uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':' -f2 | tr
> -d ' ')
> -AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis list
> Port_Binding], [0], [dnl
> -logical_port        : vif0
> -mac                 : [["f0:ab:cd:ef:01:02"]]
> -chassis             : ${uuid}
> -])
> -
> -# test the passing down of logical port type and options.
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
> -AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
> -AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0
> vtep_logical_switch=l0])
> -
> -AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0
> options!={}])
> -AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list
> Port_Binding vtep0], [0], [dnl
> -logical_port        : vtep0
> -mac                 : [[]]
> -type                : vtep
> -options             : {vtep_logical_switch=l0, vtep_physical_switch=p0}
> -])
> -
> -OVN_SBCTL_TEST_STOP
> -AT_CLEANUP
> -
> -dnl ---------------------------------------------------------------------
> -
> -AT_SETUP([ovn-sbctl - connection])
> -OVN_SBCTL_TEST_START
> -
> -AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection
> ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
> -AT_CHECK([ovn-sbctl list connection | grep inactivity_probe], [0], [dnl
> -inactivity_probe    : 30000
> -inactivity_probe    : 30000
> -])
> -
> -OVN_SBCTL_TEST_STOP
> -AT_CLEANUP
> diff --git a/tests/ovn.at b/tests/ovn.at
> deleted file mode 100644
> index cb380d2..0000000
> --- a/tests/ovn.at
> +++ /dev/null
> @@ -1,14702 +0,0 @@
> -# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
> -#
> -# This compares packets read from PCAP, in pcap format, to those read
> -# from EXPECTED, which is a text file containing packets as hex
> -# strings, one per line.  If PCAP contains fewer packets than
> -# EXPECTED, it waits up to 10 seconds for more packets to appear.
> -#
> -# The implementation is an m4 macro that is mostly implemented in
> -# terms of a shell function.  This reduces the size of the generated
> -# testsuite file since the shell function is only emitted once even
> -# when this macro is invoked many times.
> -m4_divert_text([PREPARE_TESTS],
> -  [ovn_check_packets__ () {
> -     echo
> -     echo "checking packets in $1 against $2:"
> -     rcv_pcap=$1
> -     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
> -     exp_text=$2
> -     exp_n=`wc -l < "$exp_text"`
> -     OVS_WAIT_UNTIL(
> -       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
> -        rcv_n=`wc -l < "$rcv_text"`
> -        echo "rcv_n=$rcv_n exp_n=$exp_n"
> -        test $rcv_n -ge $exp_n])
> -     sort $exp_text > expout
> -   }
> -])
> -m4_define([OVN_CHECK_PACKETS],
> -  [ovn_check_packets__ "$1" "$2"
> -   AT_CHECK([sort $rcv_text], [0], [expout])])
> -
> -AT_BANNER([OVN components])
> -
> -AT_SETUP([ovn -- lexer])
> -dnl For lines without =>, input and expected output are identical.
> -dnl For lines with =>, input precedes => and expected output follows =>.
> -AT_DATA([test-cases.txt], [dnl
> -foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
> -"abc\u0020def" => "abc def"
> -" => error("Input ends inside quoted string.")dnl "
> -
> -$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
> -$1 => error("`$' must be followed by a valid identifier.") 1
> -
> -a/*b*/c => a c
> -a//b c => a
> -a/**/b => a b
> -a/*/b => a error("`/*' without matching `*/'.")
> -a/*/**/b => a b
> -a/b => a error("`/' is only valid as part of `//' or `/*'.") b
> -
> -0 1 12345 18446744073709551615
> -18446744073709551616 => error("Decimal constants must be less than
> 2**64.")
> -9999999999999999999999 => error("Decimal constants must be less than
> 2**64.")
> -01 => error("Decimal constants must not have leading zeros.")
> -
> -0/0
> -0/1
> -1/0 => error("Value contains unmasked 1-bits.")
> -1/1
> -128/384
> -1/3
> -1/ => error("Integer constant expected.")
> -
> -1/0x123 => error("Value and mask have incompatible formats.")
> -
> -0x1234
> -0x01234 => 0x1234
> -0x0 => 0
> -0x000 => 0
> -0xfedcba9876543210
> -0XFEDCBA9876543210 => 0xfedcba9876543210
> -0xfedcba9876543210fedcba9876543210
> -0x0000fedcba9876543210fedcba9876543210 =>
> 0xfedcba9876543210fedcba9876543210
> -0x => error("Hex digits expected following 0x.")
> -0X => error("Hex digits expected following 0X.")
> -0x0/0x0 => 0/0
> -0x0/0x1 => 0/0x1
> -0x1/0x0 => error("Value contains unmasked 1-bits.")
> -0xffff/0x1ffff
> -0x. => error("Invalid syntax in hexadecimal constant.")
> -
> -192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
> -256.1.2.3 => error("Invalid numeric constant.")
> -192.168.0.0/16
> -192.168.0.0/255.255.0.0 => 192.168.0.0/16
> -192.168.0.0/255.255.255.0 => 192.168.0.0/24
> -192.168.0.0/255.255.0.255
> -192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.")
> -192.168.0.0/32
> -192.168.0.0/255.255.255.255 => 192.168.0.0/32
> -1.2.3.4:5 => 1.2.3.4 : 5
> -
> -::
> -::1
> -ff00::1234 => ff00::1234
> -2001:db8:85a3::8a2e:370:7334
> -2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
> -2001:0db8:85a3:0000:0000:8a2e:0370:7334 => 2001:db8:85a3::8a2e:370:7334
> -::ffff:192.0.2.128
> -::ffff:c000:0280 => ::ffff:192.0.2.128
> -::1/::1
> -::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
> -::1/128
> -ff00::/8
> -ff00::/ff00:: => ff00::/8
> -
> -01:23:45:67:ab:cd
> -01:23:45:67:AB:CD => 01:23:45:67:ab:cd
> -fe:dc:ba:98:76:54
> -FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
> -01:00:00:00:00:00/01:00:00:00:00:00
> -ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
> -fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
> -ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked
> 1-bits.")
> -fe:x => error("Invalid numeric constant.")
> -00:01:02:03:04:x => error("Invalid numeric constant.")
> -
> -# Test that operators are tokenized as expected, even without white space.
> -(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= > >= ! &&
> || .. , ; = <-> -- :
> -& => error("`&' is only valid as part of `&&'.")
> -| => error("`|' is only valid as part of `||'.")
> -- => error("`-' is only valid as part of `--'.")
> -
> -^ => error("Invalid character `^' in input.")
> -])
> -AT_CAPTURE_FILE([input.txt])
> -sed 's/ =>.*//' test-cases.txt > input.txt
> -sed 's/.* => //' test-cases.txt > expout
> -AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
> -AT_CLEANUP
> -
> -dnl The OVN expression parser needs to know what fields overlap with one
> -dnl another.  This test therefore verifies that all the smaller registers
> -dnl are defined as terms of subfields of the larger ones.
> -dnl
> -dnl When we add or remove registers this test needs to be updated, of
> course.
> -AT_SETUP([ovn -- registers])
> -AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
> -[[reg0 = xxreg0[96..127]
> -reg1 = xxreg0[64..95]
> -reg2 = xxreg0[32..63]
> -reg3 = xxreg0[0..31]
> -reg4 = xxreg1[96..127]
> -reg5 = xxreg1[64..95]
> -reg6 = xxreg1[32..63]
> -reg7 = xxreg1[0..31]
> -reg8 = xreg4[32..63]
> -reg9 = xreg4[0..31]
> -xreg0 = xxreg0[64..127]
> -xreg1 = xxreg0[0..63]
> -xreg2 = xxreg1[64..127]
> -xreg3 = xxreg1[0..63]
> -xreg4 = OXM_OF_PKT_REG4
> -xxreg0 = NXM_NX_XXREG0
> -xxreg1 = NXM_NX_XXREG1
> -]])
> -AT_CLEANUP
> -
> -dnl Check that the OVN conntrack field definitions are correct.
> -AT_SETUP([ovn -- conntrack fields])
> -AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
> -[[ct.dnat = ct_state[7]
> -ct.est = ct_state[1]
> -ct.inv = ct_state[4]
> -ct.new = ct_state[0]
> -ct.rel = ct_state[2]
> -ct.rpl = ct_state[3]
> -ct.snat = ct_state[6]
> -ct.trk = ct_state[5]
> -ct_label = NXM_NX_CT_LABEL
> -ct_label.blocked = ct_label[0]
> -ct_mark = NXM_NX_CT_MARK
> -ct_state = NXM_NX_CT_STATE
> -]])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- composition])
> -AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- expression parser])
> -dnl For lines without =>, input and expected output are identical.
> -dnl For lines with =>, input precedes => and expected output follows =>.
> -AT_DATA([test-cases.txt], [[
> -eth.type == 0x800
> -eth.type==0x800 => eth.type == 0x800
> -eth.type[0..15] == 0x800 => eth.type == 0x800
> -
> -vlan.present
> -vlan.present == 1 => vlan.present
> -!(vlan.present == 0) => vlan.present
> -!(vlan.present != 1) => vlan.present
> -!vlan.present
> -vlan.present == 0 => !vlan.present
> -vlan.present != 1 => !vlan.present
> -!(vlan.present == 1) => !vlan.present
> -!(vlan.present != 0) => !vlan.present
> -
> -eth.dst[0]
> -eth.dst[0] == 1 => eth.dst[0]
> -eth.dst[0] != 0 => eth.dst[0]
> -!(eth.dst[0] == 0) => eth.dst[0]
> -!(eth.dst[0] != 1) => eth.dst[0]
> -
> -!eth.dst[0]
> -eth.dst[0] == 0 => !eth.dst[0]
> -eth.dst[0] != 1 => !eth.dst[0]
> -!(eth.dst[0] == 1) => !eth.dst[0]
> -!(eth.dst[0] != 0) => !eth.dst[0]
> -
> -vlan.tci[12..15] == 0x3
> -vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
> -vlan.tci[12..15] != 0x3
> -vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
> -
> -!vlan.pcp => vlan.pcp == 0
> -!(vlan.pcp) => vlan.pcp == 0
> -vlan.pcp == 0x4
> -vlan.pcp != 0x4
> -vlan.pcp > 0x4
> -vlan.pcp >= 0x4
> -vlan.pcp < 0x4
> -vlan.pcp <= 0x4
> -!(vlan.pcp != 0x4) => vlan.pcp == 0x4
> -!(vlan.pcp == 0x4) => vlan.pcp != 0x4
> -!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
> -!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
> -!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
> -!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
> -0x4 == vlan.pcp => vlan.pcp == 0x4
> -0x4 != vlan.pcp => vlan.pcp != 0x4
> -0x4 < vlan.pcp => vlan.pcp > 0x4
> -0x4 <= vlan.pcp => vlan.pcp >= 0x4
> -0x4 > vlan.pcp => vlan.pcp < 0x4
> -0x4 >= vlan.pcp => vlan.pcp <= 0x4
> -!(0x4 != vlan.pcp) => vlan.pcp == 0x4
> -!(0x4 == vlan.pcp) => vlan.pcp != 0x4
> -!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
> -!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
> -!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
> -!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
> -
> -1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
> -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
> -1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
> -1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
> -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
> -4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
> -4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
> -4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
> -4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
> -!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
> -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
> -!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
> -!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
> -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
> -!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
> -!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
> -!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
> -!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
> -
> -vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 ||
> vlan.pcp == 0x3 || vlan.pcp == 0x4
> -vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp == 4) =>
> vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
> -
> -vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 &&
> vlan.pcp != 0x3 && vlan.pcp != 0x4
> -vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) =>
> vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 && vlan.pcp == 0x4
> -
> -vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) =>
> vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 || vlan.pcp != 0x4)
> -vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) =>
> vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3) && vlan.pcp == 0x4
> -vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) =>
> vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3) || vlan.pcp != 0x4)
> -
> -ip4.src == {10.0.0.0/8, 192.168.0.0/16, 172.16.20.0/24, 8.8.8.8} =>
> ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 || ip4.src[8..31] ==
> 0xac1014 || ip4.src == 0x8080808
> -ip6.src == ::1 => ip6.src == 0x1
> -
> -ip4.src == 1.2.3.4 => ip4.src == 0x1020304
> -ip4.src == ::1.2.3.4/::ffff:ffff => ip4.src == 0x1020304
> -ip6.src == ::1 => ip6.src == 0x1
> -
> -1
> -0
> -!1 => 0
> -!0 => 1
> -
> -inport == "eth0"
> -!(inport != "eth0") => inport == "eth0"
> -
> -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
> => 0
> -
> -ip4.src == "eth0" => Integer field ip4.src is not compatible with string
> constant.
> -inport == 1 => String field inport is not compatible with integer
> constant.
> -ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational operator.
> -
> -ip4.src > {1, 2, 3} => Only == and != operators may be used with value
> sets.
> -eth.type > 0x800 => Only == and != operators may be used with nominal
> field eth.type.
> -vlan.present > 0 => Only == and != operators may be used with Boolean
> field vlan.present.
> -
> -inport != "eth0" => Nominal field inport may only be tested for equality
> (taking enclosing `!' operators into account).
> -!(inport == "eth0") => Nominal field inport may only be tested for
> equality (taking enclosing `!' operators into account).
> -eth.type != 0x800 => Nominal field eth.type may only be tested for
> equality (taking enclosing `!' operators into account).
> -!(eth.type == 0x800) => Nominal field eth.type may only be tested for
> equality (taking enclosing `!' operators into account).
> -inport = "eth0" => Syntax error at `=' expecting relational operator.
> -
> -123 == 123 => Syntax error at `123' expecting field name.
> -
> -$name => Syntax error at `$name' expecting address set name.
> -@name => Syntax error at `@name' expecting port group name.
> -
> -123 == xyzzy => Syntax error at `xyzzy' expecting field name.
> -xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
> -
> -inport[1] == 1 => Cannot select subfield of string field inport.
> -
> -eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
> -eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
> -eth.type[18446744073709551615] == 1 => Syntax error at
> `18446744073709551615' expecting small integer.
> -
> -eth.type[5!] => Syntax error at `!' expecting `@:>@'.
> -
> -eth.type[5..1] => Invalid bit range 5 to 1.
> -
> -eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field eth.type.
> -
> -eth.type[10] == 1 => Cannot select subfield of nominal field eth.type.
> -
> -eth.type => Explicit `!= 0' is required for inequality test of multibit
> field against 0.
> -
> -!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test of
> multibit field against 0.
> -
> -123 => Syntax error at end of input expecting relational operator.
> -
> -123 x => Syntax error at `x' expecting relational operator.
> -
> -{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
> -
> -eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
> -
> -(1 x) => Syntax error at `x' expecting `)'.
> -
> -!0x800 != eth.type => Missing parentheses around operand of !.
> -
> -eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => && and ||
> must be parenthesized when used together.
> -
> -eth.dst == {} => Syntax error at `}' expecting constant.
> -
> -eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators
> may be used with masked constants.  Consider using subfields instead (e.g.
> eth.src[0..15] > 0x1111 in place of eth.src >
> 00:00:00:00:11:11/00:00:00:00:ff:ff).
> -
> -ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field
> ip4.src.
> -
> -1 == eth.type == 2 => Range expressions must have the form `x < field <
> y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by
> `>=').
> -
> -eth.dst[40] x => Syntax error at `x' expecting end of input.
> -
> -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset'
> expecting address set name.
> -eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac'
> expecting constant.
> -
> -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
> => Parentheses nested too deeply.
> -
> -ct_label > $set4 => Only == and != operators may be used to compare a
> field against an empty value set.
> -]])
> -sed 's/ =>.*//' test-cases.txt > input.txt
> -sed 's/.* => //' test-cases.txt > expout
> -AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- expression annotation])
> -dnl Input precedes =>, expected output follows =>.
> -dnl Empty lines and lines starting with # are ignored.
> -AT_DATA([test-cases.txt], [[
> -ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
> -ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
> -ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 || eth.type ==
> 0x86dd)
> -ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea) &&
> (eth.type == 0x800 || eth.type == 0x86dd)
> -ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304 &&
> eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
> -
> -# Nested expressions over a single symbol should be annotated with
> symbol's
> -# prerequisites only once, at the top level.
> -tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1 ||
> (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 && (eth.type ==
> 0x800 || eth.type == 0x86dd)
> -
> -ip => eth.type == 0x800 || eth.type == 0x86dd
> -ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
> -ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
> -ip > 0 => Only == and != operators may be used with nominal field ip.
> -!ip => Nominal predicate ip may only be tested positively, e.g. `ip' or
> `ip == 1' but not `!ip' or `ip == 0'.
> -ip == 0 => Nominal predicate ip may only be tested positively, e.g. `ip'
> or `ip == 1' but not `!ip' or `ip == 0'.
> -
> -vlan.present => vlan.tci[12]
> -!vlan.present => !vlan.tci[12]
> -
> -!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
> -vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 && vlan.tci[12]
> && vlan.tci[0..11] == 0x2 && vlan.tci[12]
> -!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 &&
> xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
> -
> -ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type == 0x86dd)
> && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
> -!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type !=
> 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd))
> -ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd)
> -
> -bad_prereq != 0 => Error parsing expression `xyzzy' encountered as
> prerequisite or predicate of initial expression: Syntax error at `xyzzy'
> expecting field name.
> -self_recurse != 0 => Error parsing expression `self_recurse != 0'
> encountered as prerequisite or predicate of initial expression: Recursive
> expansion of symbol `self_recurse'.
> -mutual_recurse_1 != 0 => Error parsing expression `mutual_recurse_2 != 0'
> encountered as prerequisite or predicate of initial expression: Error
> parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or
> predicate of initial expression: Recursive expansion of symbol
> `mutual_recurse_1'.
> -mutual_recurse_2 != 0 => Error parsing expression `mutual_recurse_1 != 0'
> encountered as prerequisite or predicate of initial expression: Error
> parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or
> predicate of initial expression: Recursive expansion of symbol
> `mutual_recurse_2'.
> -]])
> -sed 's/ =>.*//' test-cases.txt > input.txt
> -sed 's/.* => //' test-cases.txt > expout
> -AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 1-term expression conversion])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
> -  [Tested converting all 1-terminal expressions with 2 numeric vars (each
> 3 bits) in terms of operators == != < <= > >= and 2 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2-term expression conversion])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
> -  [Tested converting 578 expressions of 2 terminals with 2 numeric vars
> (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 3-term expression conversion])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3],
> [0],
> -  [Tested converting 67410 expressions of 3 terminals with 2 numeric vars
> (each 2 bits) in terms of operators == != < <= > >= and 2 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 3-term numeric expression simplification])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=2
> --svars=0 3], [0],
> -  [Tested simplifying 490770 expressions of 3 terminals with 2 numeric
> vars (each 3 bits) in terms of operators == != < <= > >=.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term string expression simplification])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=0
> --svars=4 4], [0],
> -  [Tested simplifying 21978 expressions of 4 terminals with 4 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 3-term mixed expression simplification])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=1
> --svars=1 3], [0],
> -  [Tested simplifying 127890 expressions of 3 terminals with 1 numeric
> vars (each 3 bits) in terms of operators == != < <= > >= and 1 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- simplification special cases])
> -simplify() {
> -    echo "$1" | ovstest test-ovn simplify-expr
> -}
> -AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
> -])
> -AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
> -])
> -AT_CHECK([simplify 'tcp.dst >= 0'], [0],
> -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
> -])
> -AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
> -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
> -])
> -AT_CHECK([simplify 'tcp.dst > 0'], [0],
> -    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] || tcp.dst[4]
> || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8] || tcp.dst[9] ||
> tcp.dst[10] || tcp.dst[11] || tcp.dst[12] || tcp.dst[13] || tcp.dst[14] ||
> tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
> -]])
> -AT_CHECK([simplify 'tcp.dst < 65535'], [0],
> -    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3] ||
> !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] || !tcp.dst[8] ||
> !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] || !tcp.dst[12] || !tcp.dst[13]
> || !tcp.dst[14] || !tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800
> || eth.type == 0x86dd)
> -]])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- is_chassis_resident simplification])
> -simplify() {
> -    echo "$1" | ovstest test-ovn simplify-expr
> -}
> -AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
> -])
> -AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
> -])
> -AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
> -])
> -AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term numeric expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3
> --svars=0 --bits=1 4], [0],
> -  [Tested normalizing 1874026 expressions of 4 terminals with 3 numeric
> vars (each 1 bits) in terms of operators == != < <= > >=.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term string expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0
> --svars=3 --bits=1 4], [0],
> -  [Tested normalizing 11242 expressions of 4 terminals with 3 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term mixed expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1
> --bits=1 --svars=2 4], [0],
> -  [Tested normalizing 175978 expressions of 4 terminals with 1 numeric
> vars (each 1 bits) in terms of operators == != < <= > >= and 2 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 5-term numeric expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3
> --svars=0 --bits=1 --relops='==' 5], [0],
> -  [Tested normalizing 1317600 expressions of 5 terminals with 3 numeric
> vars (each 1 bits) in terms of operators ==.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 5-term string expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0
> --svars=3 --bits=1 --relops='==' 5], [0],
> -  [Tested normalizing 368550 expressions of 5 terminals with 3 string
> vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 5-term mixed expression normalization])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1
> --svars=1 --bits=1 --relops='==' 5], [0],
> -  [Tested normalizing 216000 expressions of 5 terminals with 1 numeric
> vars (each 1 bits) in terms of operators == and 1 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term numeric expressions to flows])
> -AT_KEYWORDS([expression])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2
> --svars=0 --bits=2 --relops='==' 4], [0],
> -  [Tested converting to flows 175978 expressions of 4 terminals with 2
> numeric vars (each 2 bits) in terms of operators ==.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term string expressions to flows])
> -AT_KEYWORDS([expression])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0
> --svars=4 4], [0],
> -  [Tested converting to flows 21978 expressions of 4 terminals with 4
> string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4-term mixed expressions to flows])
> -AT_KEYWORDS([expression])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1 --bits=2
> --svars=1 --relops='==' 4], [0],
> -  [Tested converting to flows 48312 expressions of 4 terminals with 1
> numeric vars (each 2 bits) in terms of operators == and 1 string vars.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 3-term numeric expressions to flows])
> -AT_KEYWORDS([expression])
> -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3
> --svars=0 --bits=3 --relops='==' 3], [0],
> -  [Tested converting to flows 41328 expressions of 3 terminals with 3
> numeric vars (each 3 bits) in terms of operators ==.
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- converting expressions to flows -- string fields])
> -AT_KEYWORDS([expression])
> -expr_to_flow () {
> -    echo "$1" | ovstest test-ovn expr-to-flows | sort
> -}
> -AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
> -ip,reg14=0x5
> -ipv6,reg14=0x5
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
> -ip,reg14=0x6
> -ipv6,reg14=0x6
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
> -])
> -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2", "LOCAL"}'],
> [0],
> -[reg14=0x5
> -reg14=0x6
> -reg14=0xfffe
> -])
> -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} && ip'], [0],
> [dnl
> -ip,reg14=0x5
> -ip,reg14=0x6
> -ipv6,reg14=0x5
> -ipv6,reg14=0x6
> -])
> -AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'], [0], [dnl
> -(no flows)
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- converting expressions to flows -- address sets])
> -AT_KEYWORDS([expression])
> -expr_to_flow () {
> -    echo "$1" | ovstest test-ovn expr-to-flows | sort
> -}
> -AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3}'], [0],
> [dnl
> -ip,nw_src=10.0.0.1
> -ip,nw_src=10.0.0.2
> -ip,nw_src=10.0.0.3
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
> -ip,nw_src=10.0.0.1
> -ip,nw_src=10.0.0.2
> -ip,nw_src=10.0.0.3
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
> -ip,nw_src=1.2.3.4
> -ip,nw_src=10.0.0.1
> -ip,nw_src=10.0.0.2
> -ip,nw_src=10.0.0.3
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20, 5.5.5.0/24, $set1}'],
> [0], [dnl
> -ip,nw_src=1.2.0.0/20
> -ip,nw_src=10.0.0.1
> -ip,nw_src=10.0.0.2
> -ip,nw_src=10.0.0.3
> -ip,nw_src=5.5.5.0/24
> -])
> -AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
> -ipv6,ipv6_src=::1
> -ipv6,ipv6_src=::2
> -ipv6,ipv6_src=::3
> -])
> -AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
> -ipv6,ipv6_src=::1
> -ipv6,ipv6_src=::2
> -ipv6,ipv6_src=::3
> -ipv6,ipv6_src=::4
> -])
> -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, 00:00:00:00:00:02,
> 00:00:00:00:00:03}'], [0], [dnl
> -dl_src=00:00:00:00:00:01
> -dl_src=00:00:00:00:00:02
> -dl_src=00:00:00:00:00:03
> -])
> -AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
> -dl_src=00:00:00:00:00:01
> -dl_src=00:00:00:00:00:02
> -dl_src=00:00:00:00:00:03
> -])
> -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3,
> ba:be:be:ef:de:ad, $set3}'], [0], [dnl
> -dl_src=00:00:00:00:00:01
> -dl_src=00:00:00:00:00:02
> -dl_src=00:00:00:00:00:03
> -dl_src=ba:be:be:ef:de:ad
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
> -(no flows)
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
> -ip,nw_src=1.2.3.4
> -])
> -AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src == {$set4}'], [0],
> [dnl
> -ip,nw_src=1.2.3.4
> -])
> -AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
> -
> -])
> -AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8, $set4}'], [0], [dnl
> -ip,nw_src=0.0.0.0/1.0.0.0
> -ip,nw_src=128.0.0.0/1
> -ip,nw_src=16.0.0.0/16.0.0.0
> -ip,nw_src=2.0.0.0/2.0.0.0
> -ip,nw_src=32.0.0.0/32.0.0.0
> -ip,nw_src=4.0.0.0/4.0.0.0
> -ip,nw_src=64.0.0.0/64.0.0.0
> -ip,nw_src=8.0.0.0/8.0.0.0
> -])
> -AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 && ip4.src != {$set4}'],
> [0], [dnl
> -ip,nw_src=0.0.0.0/1.0.0.0
> -ip,nw_src=128.0.0.0/1
> -ip,nw_src=16.0.0.0/16.0.0.0
> -ip,nw_src=2.0.0.0/2.0.0.0
> -ip,nw_src=32.0.0.0/32.0.0.0
> -ip,nw_src=4.0.0.0/4.0.0.0
> -ip,nw_src=64.0.0.0/64.0.0.0
> -ip,nw_src=8.0.0.0/8.0.0.0
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- converting expressions to flows -- port groups])
> -AT_KEYWORDS([expression])
> -expr_to_flow () {
> -    echo "$1" | ovstest test-ovn expr-to-flows | sort
> -}
> -AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
> -reg15=0x11
> -reg15=0x12
> -reg15=0x13
> -])
> -AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
> -(no flows)
> -])
> -AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], [dnl
> -reg15=0x11
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- converting expressions to flows -- conjunction])
> -AT_KEYWORDS([conjunction])
> -expr_to_flow () {
> -    echo "$1" | ovstest test-ovn expr-to-flows | sort
> -}
> -
> -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
> -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
> -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
> -conj_id=1,ip
> -ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
> -ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
> -ip,nw_dst=20.0.0.3: conjunction(1, 0/2)
> -ip,nw_src=10.0.0.1: conjunction(1, 1/2)
> -ip,nw_src=10.0.0.2: conjunction(1, 1/2)
> -ip,nw_src=10.0.0.3: conjunction(1, 1/2)
> -])
> -
> -lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
> -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
> -ct_state=+est+trk,ct_label=0x1/0x1,ip
> -ct_state=+est+trk,ct_label=0x1/0x1,ipv6
> -ct_state=-est+trk,ip
> -ct_state=-est+trk,ipv6
> -])
> -
> -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
> -ip4.dst == {20.0.0.1, 20.0.0.2}"
> -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
> -conj_id=1,ip
> -ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
> -ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
> -ip,nw_src=10.0.0.1: conjunction(1, 1/2)
> -ip,nw_src=10.0.0.2: conjunction(1, 1/2)
> -ip,nw_src=10.0.0.3: conjunction(1, 1/2)
> -])
> -
> -lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
> -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
> -tcp.dst >= 1000 && tcp.dst <= 1010"
> -
> -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
> -conj_id=1,tcp
> -tcp,nw_dst=20.0.0.1: conjunction(1, 0/3)
> -tcp,nw_dst=20.0.0.2: conjunction(1, 0/3)
> -tcp,nw_dst=20.0.0.3: conjunction(1, 0/3)
> -tcp,nw_src=10.0.0.1: conjunction(1, 1/3)
> -tcp,nw_src=10.0.0.2: conjunction(1, 1/3)
> -tcp,nw_src=10.0.0.3: conjunction(1, 1/3)
> -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
> -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
> -tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
> -tcp,tp_dst=1000: conjunction(1, 2/3)
> -tcp,tp_dst=1001: conjunction(1, 2/3)
> -tcp,tp_dst=1010: conjunction(1, 2/3)
> -])
> -
> -lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
> -((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 && \
> -tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
> -|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
> -
> -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
> -conj_id=1,tcp
> -ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
> -ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
> -ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
> -ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
> -ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
> -ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
> -tcp,nw_dst=20.0.0.4: conjunction(1, 0/4)
> -tcp,nw_dst=20.0.0.7: conjunction(1, 0/4)
> -tcp,nw_dst=20.0.0.8: conjunction(1, 0/4)
> -tcp,nw_src=10.0.0.4: conjunction(1, 1/4)
> -tcp,nw_src=10.0.0.5: conjunction(1, 1/4)
> -tcp,nw_src=10.0.0.6: conjunction(1, 1/4)
> -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
> -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
> -tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
> -tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
> -tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
> -tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
> -tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
> -tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
> -tcp,tp_dst=1000: conjunction(1, 2/4)
> -tcp,tp_dst=1001: conjunction(1, 2/4)
> -tcp,tp_dst=2000: conjunction(1, 2/4)
> -tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
> -tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
> -tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
> -tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
> -tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
> -tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
> -tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
> -tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
> -tcp,tp_src=1000: conjunction(1, 3/4)
> -tcp,tp_src=1001: conjunction(1, 3/4)
> -tcp,tp_src=2000: conjunction(1, 3/4)
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- action parsing])
> -dnl Unindented text is input (a set of OVN logical actions).
> -dnl Indented text is expected output.
> -AT_DATA([test-cases.txt],
> -[[# drop
> -drop;
> -    encodes as drop
> -drop; next;
> -    Syntax error at `next' expecting end of input.
> -next; drop;
> -    Syntax error at `drop' expecting action.
> -
> -# output
> -output;
> -    encodes as resubmit(,64)
> -
> -# next
> -next;
> -    encodes as resubmit(,19)
> -next(11);
> -    formats as next;
> -    encodes as resubmit(,19)
> -next(0);
> -    encodes as resubmit(,8)
> -next(23);
> -    encodes as resubmit(,31)
> -
> -next();
> -    Syntax error at `)' expecting "pipeline" or "table".
> -next(10;
> -    Syntax error at `;' expecting `)'.
> -next(24);
> -    "next" action cannot advance beyond table 23.
> -
> -next(table=11);
> -    formats as next;
> -    encodes as resubmit(,19)
> -next(pipeline=ingress);
> -    formats as next;
> -    encodes as resubmit(,19)
> -next(table=11, pipeline=ingress);
> -    formats as next;
> -    encodes as resubmit(,19)
> -next(pipeline=ingress, table=11);
> -    formats as next;
> -    encodes as resubmit(,19)
> -
> -next(pipeline=egress);
> -    "next" action cannot advance from ingress to egress pipeline (use
> "output" action instead)
> -
> -next(table=10);
> -    formats as next(10);
> -    encodes as resubmit(,18)
> -
> -# Loading a constant value.
> -tcp.dst=80;
> -    formats as tcp.dst = 80;
> -    encodes as set_field:80->tcp_dst
> -    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type ==
> 0x86dd)
> -eth.dst[40] = 1;
> -    encodes as set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
> -vlan.pcp = 2;
> -    encodes as set_field:0x4000/0xe000->vlan_tci
> -    has prereqs vlan.tci[12]
> -vlan.tci[13..15] = 2;
> -    encodes as set_field:0x4000/0xe000->vlan_tci
> -inport = "";
> -    encodes as set_field:0->reg14
> -ip.ttl=4;
> -    formats as ip.ttl = 4;
> -    encodes as set_field:4->nw_ttl
> -    has prereqs eth.type == 0x800 || eth.type == 0x86dd
> -outport="eth0"; next; outport="LOCAL"; next;
> -    formats as outport = "eth0"; next; outport = "LOCAL"; next;
> -    encodes as
> set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
> -
> -inport[1] = 1;
> -    Cannot select subfield of string field inport.
> -ip.proto[1] = 1;
> -    Cannot select subfield of nominal field ip.proto.
> -eth.dst[40] == 1;
> -    Syntax error at `==' expecting `=' or `<->'.
> -ip = 1;
> -    Predicate symbol ip used where lvalue required.
> -ip.proto = 6;
> -    Field ip.proto is not modifiable.
> -inport = {"a", "b"};
> -    Syntax error at `{' expecting constant.
> -inport = {};
> -    Syntax error at `{' expecting constant.
> -bad_prereq = 123;
> -    Error parsing expression `xyzzy' encountered as prerequisite or
> predicate of initial expression: Syntax error at `xyzzy' expecting field
> name.
> -self_recurse = 123;
> -    Error parsing expression `self_recurse != 0' encountered as
> prerequisite or predicate of initial expression: Error parsing expression
> `self_recurse != 0' encountered as prerequisite or predicate of initial
> expression: Recursive expansion of symbol `self_recurse'.
> -vlan.present = 0;
> -    Predicate symbol vlan.present used where lvalue required.
> -
> -# Moving one field into another.
> -reg0=reg1;
> -    formats as reg0 = reg1;
> -    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
> -vlan.pcp = reg0[0..2];
> -    encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
> -    has prereqs vlan.tci[12]
> -reg0[10] = vlan.pcp[1];
> -    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
> -    has prereqs vlan.tci[12]
> -outport = inport;
> -    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
> -
> -reg0[0] = vlan.present;
> -    Predicate symbol vlan.present used where lvalue required.
> -reg0 = reg1[0..10];
> -    Can't assign 11-bit value to 32-bit destination.
> -inport = reg0;
> -    Can't assign integer field (reg0) to string field (inport).
> -inport = big_string;
> -    String fields inport and big_string are incompatible for assignment.
> -ip.proto = reg0[0..7];
> -    Field ip.proto is not modifiable.
> -
> -# Exchanging fields.
> -reg0 <-> reg1;
> -    encodes as
> push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127]
> -vlan.pcp <-> reg0[0..2];
> -    encodes as
> push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15]
> -    has prereqs vlan.tci[12]
> -reg0[10] <-> vlan.pcp[1];
> -    encodes as
> push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106]
> -    has prereqs vlan.tci[12]
> -outport <-> inport;
> -    encodes as
> push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[]
> -
> -reg0[0] <-> vlan.present;
> -    Predicate symbol vlan.present used where lvalue required.
> -reg0 <-> reg1[0..10];
> -    Can't exchange 32-bit field with 11-bit field.
> -inport <-> reg0;
> -    Can't exchange string field (inport) with integer field (reg0).
> -inport <-> big_string;
> -    String fields inport and big_string are incompatible for exchange.
> -ip.proto <-> reg0[0..7];
> -    Field ip.proto is not modifiable.
> -reg0[0..7] <-> ip.proto;
> -    Field ip.proto is not modifiable.
> -
> -# TTL decrement.
> -ip.ttl--;
> -    encodes as dec_ttl
> -    has prereqs ip
> -ip.ttl
> -    Syntax error at end of input expecting `--'.
> -
> -# load balancing.
> -ct_lb;
> -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
> -    has prereqs ip
> -ct_lb();
> -    formats as ct_lb;
> -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
> -    has prereqs ip
> -ct_lb(192.168.1.2:80, 192.168.1.3:80);
> -    encodes as group:1
> -    has prereqs ip
> -ct_lb(192.168.1.2, 192.168.1.3, );
> -    formats as ct_lb(192.168.1.2, 192.168.1.3);
> -    encodes as group:2
> -    has prereqs ip
> -ct_lb(fd0f::2, fd0f::3, );
> -    formats as ct_lb(fd0f::2, fd0f::3);
> -    encodes as group:3
> -    has prereqs ip
> -
> -ct_lb(192.168.1.2:);
> -    Syntax error at `)' expecting port number.
> -ct_lb(192.168.1.2:123456);
> -    Syntax error at `123456' expecting port number.
> -ct_lb(foo);
> -    Syntax error at `foo' expecting IP address.
> -ct_lb([192.168.1.2]);
> -    Syntax error at `192.168.1.2' expecting IPv6 address.
> -
> -# ct_next
> -ct_next;
> -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
> -    has prereqs ip
> -
> -# ct_commit
> -ct_commit;
> -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
> -    has prereqs ip
> -ct_commit();
> -    formats as ct_commit;
> -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
> -    has prereqs ip
> -ct_commit(ct_mark=1);
> -    formats as ct_commit(ct_mark=0x1);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
> -    has prereqs ip
> -ct_commit(ct_mark=1/1);
> -    formats as ct_commit(ct_mark=0x1/0x1);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
> -    has prereqs ip
> -ct_commit(ct_label=1);
> -    formats as ct_commit(ct_label=0x1);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
> -    has prereqs ip
> -ct_commit(ct_label=1/1);
> -    formats as ct_commit(ct_label=0x1/0x1);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
> -    has prereqs ip
> -ct_commit(ct_mark=1, ct_label=2);
> -    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label))
> -    has prereqs ip
> -
> -ct_commit(ct_label=0x01020304050607080910111213141516);
> -    formats as ct_commit(ct_label=0x1020304050607080910111213141516);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label))
> -    has prereqs ip
> -ct_commit(ct_label=0x181716151413121110090807060504030201);
> -    formats as ct_commit(ct_label=0x16151413121110090807060504030201);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label))
> -    has prereqs ip
>
> -ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label))
> -    has prereqs ip
> -ct_commit(ct_label=18446744073709551615);
> -    formats as ct_commit(ct_label=0xffffffffffffffff);
> -    encodes as
> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label))
> -    has prereqs ip
> -ct_commit(ct_label=18446744073709551616);
> -    Decimal constants must be less than 2**64.
> -
> -# ct_dnat
> -ct_dnat;
> -    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
> -    has prereqs ip
> -ct_dnat(192.168.1.2);
> -    encodes as
> ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
> -    has prereqs ip
> -
> -ct_dnat(192.168.1.2, 192.168.1.3);
> -    Syntax error at `,' expecting `)'.
> -ct_dnat(foo);
> -    Syntax error at `foo' expecting IPv4 address.
> -ct_dnat(foo, bar);
> -    Syntax error at `foo' expecting IPv4 address.
> -ct_dnat();
> -    Syntax error at `)' expecting IPv4 address.
> -
> -# ct_snat
> -ct_snat;
> -    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
> -    has prereqs ip
> -ct_snat(192.168.1.2);
> -    encodes as
> ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
> -    has prereqs ip
> -
> -ct_snat(192.168.1.2, 192.168.1.3);
> -    Syntax error at `,' expecting `)'.
> -ct_snat(foo);
> -    Syntax error at `foo' expecting IPv4 address.
> -ct_snat(foo, bar);
> -    Syntax error at `foo' expecting IPv4 address.
> -ct_snat();
> -    Syntax error at `)' expecting IPv4 address.
> -
> -# ct_clear
> -ct_clear;
> -    encodes as ct_clear
> -
> -# clone
> -clone { ip4.dst = 255.255.255.255; output; }; next;
> -    encodes as
> clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
> -    has prereqs eth.type == 0x800
> -
> -# arp
> -arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
> -    encodes as
> controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip4
> -arp { };
> -    formats as arp { drop; };
> -    encodes as controller(userdata=00.00.00.00.00.00.00.00)
> -    has prereqs ip4
> -
> -# get_arp
> -get_arp(outport, ip4.dst);
> -    encodes as
> push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[]
> -    has prereqs eth.type == 0x800
> -get_arp(inport, reg0);
> -    encodes as
> push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[]
> -
> -get_arp;
> -    Syntax error at `;' expecting `('.
> -get_arp();
> -    Syntax error at `)' expecting field name.
> -get_arp(inport);
> -    Syntax error at `)' expecting `,'.
> -get_arp(inport ip4.dst);
> -    Syntax error at `ip4.dst' expecting `,'.
> -get_arp(inport, ip4.dst;
> -    Syntax error at `;' expecting `)'.
> -get_arp(inport, eth.dst);
> -    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required.
> -get_arp(inport, outport);
> -    Cannot use string field outport where numeric field is required.
> -get_arp(reg0, ip4.dst);
> -    Cannot use numeric field reg0 where string field is required.
> -
> -# put_arp
> -put_arp(inport, arp.spa, arp.sha);
> -    encodes as
> push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[]
> -    has prereqs eth.type == 0x806 && eth.type == 0x806
> -
> -# put_dhcp_opts
> -reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
> -    encodes as
> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
> -reg2[5] =
> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="
> ovn.org",wpad="https://example.org",bootfile_name="
> https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot");
> -    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router =
> 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name = "ovn.org",
> wpad = "https://example.org", bootfile_name = "https://127.0.0.1/boot.ipxe",
> path_prefix = "/tftpboot");
> -    encodes as
> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause)
> -reg0[15] =
> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={
> 30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1
> },ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5});
> -    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router =
> 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1,
> default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route
> = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1},
> ethernet_encap = 1, router_discovery = 0, tftp_server_address = {10.0.0.4,
> 10.0.0.5});
> -    encodes as
> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause)
> -
> -reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
> -    Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
> -reg1[0] = put_dhcp_opts();
> -    put_dhcp_opts requires offerip to be specified.
> -reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
> -    Syntax error at `x' expecting DHCPv4 option name.
> -reg1[0] = put_dhcp_opts(router = 10.0.0.1);
> -    put_dhcp_opts requires offerip to be specified.
> -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
> -    Syntax error at `"hi"'.
> -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
> -    Syntax error at `xyzzy' expecting DHCPv4 option name.
> -reg1[0] = put_dhcp_opts(offerip="xyzzy");
> -    DHCPv4 option offerip requires numeric value.
> -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
> -    DHCPv4 option domain_name requires string value.
> -
> -# nd_ns
> -nd_ns { nd.target = xxreg0; output; };
> -    encodes as
> controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
> -    has prereqs ip6
> -
> -nd_ns { };
> -    formats as nd_ns { drop; };
> -    encodes as controller(userdata=00.00.00.09.00.00.00.00)
> -    has prereqs ip6
> -
> -# nd_na
> -nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport
> = inport; inport = ""; /* Allow sending out inport. */ output; };
> -    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll =
> 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
> -    encodes as
> controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
> -    has prereqs nd_ns
> -# nd_na_router
> -nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc;
> outport = inport; inport = ""; /* Allow sending out inport. */ output; };
> -    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll =
> 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
> -    encodes as
> controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
> -    has prereqs nd_ns
> -
> -# get_nd
> -get_nd(outport, ip6.dst);
> -    encodes as
> push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[]
> -    has prereqs eth.type == 0x86dd
> -get_nd(inport, xxreg0);
> -    encodes as
> push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[]
> -get_nd;
> -    Syntax error at `;' expecting `('.
> -get_nd();
> -    Syntax error at `)' expecting field name.
> -get_nd(inport);
> -    Syntax error at `)' expecting `,'.
> -get_nd(inport ip6.dst);
> -    Syntax error at `ip6.dst' expecting `,'.
> -get_nd(inport, ip6.dst;
> -    Syntax error at `;' expecting `)'.
> -get_nd(inport, eth.dst);
> -    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is
> required.
> -get_nd(inport, outport);
> -    Cannot use string field outport where numeric field is required.
> -get_nd(xxreg0, ip6.dst);
> -    Cannot use numeric field xxreg0 where string field is required.
> -
> -# put_nd
> -put_nd(inport, nd.target, nd.sll);
> -    encodes as
> push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[]
> -    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type ==
> 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) &&
> icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type ==
> 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 ||
> eth.type == 0x86dd) && icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto
> == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 &&
> eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type ==
> 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd)
> -
> -# put_dhcpv6_opts
> -reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
> 00:00:00:00:10:02);
> -    encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
> -reg1[0] = put_dhcpv6_opts();
> -    encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
> -reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
> -    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1, ae70::2});
> -    encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
> -reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc,
> dns_server={ae70::1,ae89::2});
> -    formats as reg1[0] = put_dhcpv6_opts(server_id = 12:34:56:78:9a:bc,
> dns_server = {ae70::1, ae89::2});
> -    encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
> -reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org");
> -    encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause)
> -reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
> -    Syntax error at `x' expecting DHCPv6 option name.
> -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
> -    Syntax error at `"hi"'.
> -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
> -    Syntax error at `xyzzy' expecting DHCPv6 option name.
> -reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
> -    DHCPv6 option ia_addr requires numeric value.
> -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
> -    DHCPv6 option domain_search requires string value.
> -
> -# set_queue
> -set_queue(0);
> -    encodes as set_queue:0
> -set_queue(61440);
> -    encodes as set_queue:61440
> -set_queue(65535);
> -    Queue ID 65535 for set_queue is not in valid range 0 to 61440.
> -
> -# dns_lookup
> -reg1[0] = dns_lookup();
> -    encodes as
> controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause)
> -    has prereqs udp
> -reg1[0] = dns_lookup("foo");
> -    dns_lookup doesn't take any parameters
> -
> -# set_meter
> -set_meter(0);
> -    Rate 0 for set_meter is not in valid.
> -set_meter(1);
> -    encodes as meter:1
> -set_meter(100, 1000);
> -    encodes as meter:2
> -set_meter(100, 1000, );
> -    Syntax error at `,' expecting `)'.
> -set_meter(4294967295, 4294967295);
> -    encodes as meter:3
> -
> -# log
> -log(verdict=allow, severity=warning);
> -    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
> -log(name="test1", verdict=drop, severity=info);
> -    encodes as
> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
> -log(verdict=drop, severity=info, meter="meter1");
> -    encodes as
> controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
> -log(name="test1", verdict=drop, severity=info, meter="meter1");
> -    encodes as
> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4)
> -log(verdict=drop);
> -    formats as log(verdict=drop, severity=info);
> -    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
> -log(verdict=bad_verdict, severity=info);
> -    Syntax error at `bad_verdict' unknown verdict.
> -log(verdict=drop, severity=bad_severity);
> -    Syntax error at `bad_severity' unknown severity.
> -log(severity=notice);
> -    Syntax error at `;' expecting verdict.
> -
> -# put_nd_ra_opts
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix =
> aef0::/64, slla = ae:01:02:03:04:05);
> -    encodes as
> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
> -    has prereqs ip6
> -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla =
> ae:01:02:03:04:10, mtu = 1450);
> -    encodes as
> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause)
> -    has prereqs ip6
> -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
> ae:01:02:03:04:06, prefix = aef0::/64);
> -    encodes as
> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
> -    has prereqs ip6
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix =
> aef0::/64);
> -    slla option not present
> -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450,
> prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
> -    encodes as
> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
> -    has prereqs ip6
> -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450,
> prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
> -    encodes as
> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
> -    has prereqs ip6
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla = ae:01:02:03:04:10);
> -    prefix option needs to be set when address mode is
> slaac/dhcpv6_stateless.
> -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
> ae:01:02:03:04:10);
> -    prefix option needs to be set when address mode is
> slaac/dhcpv6_stateless.
> -reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix =
> aef0::/64, slla = ae:01:02:03:04:10);
> -    Syntax error at `dhcpv6_stateless' expecting constant.
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix =
> aef0::, slla = ae:01:02:03:04:10);
> -    Invalid value for "prefix" option
> -reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla =
> ae:01:02:03:04:10);
> -    Invalid value for "addr_mode" option
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla =
> ae:01:02:03:04:10);
> -    IPv6 ND RA option mtu requires numeric value.
> -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4, slla =
> ae:01:02:03:04:10);
> -    Invalid value for "mtu" option
> -
> -# icmp4
> -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
> -    encodes as
> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip4
> -
> -icmp4 { };
> -    formats as icmp4 { drop; };
> -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
> -    has prereqs ip4
> -
> -# icmp4 with icmp4.frag_mtu
> -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output; };
> output;
> -    encodes as
> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip4
> -
> -# icmp4_error
> -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
> -    encodes as
> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip4
> -
> -icmp4_error { };
> -    formats as icmp4_error { drop; };
> -    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
> -    has prereqs ip4
> -
> -# icmp4_error with icmp4.frag_mtu
> -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output;
> }; output;
> -    encodes as
> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip4
> -
> -icmp4.frag_mtu = 1500;
> -    encodes as controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
> -
> -# icmp6
> -icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
> -    encodes as
> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs ip6
> -
> -icmp6 { };
> -    formats as icmp6 { drop; };
> -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
> -    has prereqs ip6
> -
> -# tcp_reset
> -tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
> -    encodes as
> controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
> -    has prereqs tcp
> -
> -tcp_reset { };
> -    formats as tcp_reset { drop; };
> -    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
> -    has prereqs tcp
> -
> -# trigger_event
> -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol
> = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
> -    encodes as
> controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
> -
> -# Testing invalid vip results in extra error messages from socket-util.c
> -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol
> = "sctp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
> -    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
> -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol
> = "tcp", load_balancer = "bacon");
> -    Load balancer 'bacon' is not a UUID
> -
> -# IGMP
> -igmp;
> -    encodes as controller(userdata=00.00.00.10.00.00.00.00)
> -
> -# Contradictionary prerequisites (allowed but not useful):
> -ip4.src = ip6.src[0..31];
> -    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
> -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
> -ip4.src <-> ip6.src[0..31];
> -    encodes as
> push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
> -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
> -
> -# check_pkt_larger
> -reg0[0] = check_pkt_larger(1500);
> -    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
> -
> -reg0 = check_pkt_larger(1500);
> -    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
> -
> -reg0 = check_pkt_larger(foo);
> -    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
> -
> -reg0[0] = check_pkt_larger(foo);
> -    Syntax error at `foo' expecting `;'.
> -
> -# Miscellaneous negative tests.
> -;
> -    Syntax error at `;'.
> -xyzzy;
> -    Syntax error at `xyzzy' expecting action.
> -next; 123;
> -    Syntax error at `123'.
> -next; xyzzy;
> -    Syntax error at `xyzzy' expecting action.
> -next
> -    Syntax error at end of input expecting `;'.
> -]])
> -sed '/^[[      ]]/d' test-cases.txt > input.txt
> -cp test-cases.txt expout
> -AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout])
> -AT_CLEANUP
> -
> -AT_BANNER([OVN end-to-end tests])
> -
> -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
> -AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
> -AT_KEYWORDS([ovnarp])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Create hypervisors hv[123].
> -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
> -# Add all of the vifs to a single logical switch lsw0.
> -# Turn on port security on all the vifs except vif[123]1.
> -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
> -# Add some ACLs for Ethertypes 1234, 1235, 1236.
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2 3; do
> -        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j
> external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap
> options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
> -        ovn-nbctl lsp-add lsw0 lp$i$j
> -        if test $j = 1; then
> -            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
> 192.168.0.$i$j" unknown
> -        else
> -            if test $j = 3; then
> -                ip_addrs="192.168.0.$i$j fe80::ea2a:eaff:fe28:$i$j/64
> 192.169.0.$i$j"
> -            else
> -                ip_addrs="192.168.0.$i$j"
> -            fi
> -            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
> $ip_addrs"
> -            ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
> -        fi
> -    done
> -done
> -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
> -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport ==
> "lp11"' drop
> -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport ==
> "lp33"' drop
> -ovn-nbctl create Address_Set name=set1
> addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
> -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src ==
> $set1 && outport == "lp33"' drop
> -
> -get_lsp_uuid () {
> -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
> -}
> -
> -ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid
> lp22`,`get_lsp_uuid lp33`
> -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 && outport ==
> @pg1' drop
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Make sure there is no attempt to adding duplicated flows by
> ovn-controller
> -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
> -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
> -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv${1%?}
> -}
> -
> -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 11 for
> vif11.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        : > $i$j.expected
> -    done
> -done
> -test_packet() {
> -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -# test_arp INPORT SHA SPA TPA [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
> -    local
> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -    hv=`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
> -
> -    if test X$reply_ha = X; then
> -        # Expect to receive the broadcast ARP on the other logical switch
> ports
> -        # if no reply is expected.
> -        local i j
> -        for i in 1 2 3; do
> -            for j in 1 2 3; do
> -                if test $i$j != $inport; then
> -                    echo $request >> $i$j.expected
> -                fi
> -            done
> -        done
> -    else
> -        # Expect to receive the reply, if any.
> -        local
> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
> -        echo $reply >> $inport.expected
> -    fi
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast packets are delivered to exactly one logical switch port
> -#    (except that packets destined to their input ports are dropped).
> -#
> -# 2. Broadcast and multicast are delivered to all logical switch ports
> -#    except the input port.
> -#
> -# 3. When port security is turned on, the switch drops packets from the
> wrong
> -#    MAC address.
> -#
> -# 4. The switch drops all packets with a VLAN tag.
> -#
> -# 5. The switch drops all packets with a multicast source address.  (This
> only
> -#    affects behavior when port security is turned off, since otherwise
> port
> -#    security would drop the packet anyway.)
> -#
> -# 6. The switch delivers packets with an unknown destination to logical
> -#    switch ports with "unknown" among their MAC addresses (and port
> -#    security disabled).
> -#
> -# 7. The switch drops unicast packets that violate an ACL.
> -#
> -# 8. The switch drops multicast and broadcast packets that violate an ACL.
> -#
> -# 9. OVN generates responses to ARP requests for known IPs, except for
> -#    requests from a port for the port's own IP.
> -#
> -# 10. No response to ARP requests for unknown IPs.
> -
> -for is in 1 2 3; do
> -    for js in 1 2 3; do
> -        s=$is$js
> -        bcast=
> -        unknown=
> -        bacl2=
> -        bacl3=
> -        for id in 1 2 3; do
> -            for jd in 1 2 3; do
> -                d=$id$jd
> -
> -                if test $d != $s; then unicast=$d; else unicast=; fi
> -                test_packet $s f000000000$d f000000000$s $s$d $unicast
>  #1
> -
> -                if test $d != $s && test $js = 1; then
> -                    impersonate=$d
> -                else
> -                    impersonate=
> -                fi
> -                test_packet $s f000000000$d f00000000055 55$d
> $impersonate #3
> -
> -                if test $d != $s && test $s != 11; then acl2=$d; else
> acl2=; fi
> -                if test $d != $s && test $d != 33; then acl3=$d; else
> acl3=; fi
> -                if test $d = $s || (test $js = 1 && test $d = 33); then
> -                    # Source of 11, 21, or 31 and dest of 33 should be
> dropped
> -                    # due to the 4th ACL that uses address_set(set1).
> -                    acl4=
> -                else
> -                    acl4=$d
> -                fi
> -                if test $d = $s || test $d = 22 || test $d = 33; then
> -                    # dest of 22 and 33 should be dropped
> -                    # due to the 5th ACL that uses port_group(pg1).
> -                    acl5=
> -                else
> -                    acl5=$d
> -                fi
> -                test_packet $s f000000000$d f000000000$s 1234        #7,
> acl1
> -                test_packet $s f000000000$d f000000000$s 1235 $acl2  #7,
> acl2
> -                test_packet $s f000000000$d f000000000$s 1236 $acl3  #7,
> acl3
> -                test_packet $s f000000000$d f000000000$s 1237 $acl4  #7,
> acl4
> -                test_packet $s f000000000$d f000000000$s 1238 $acl5  #7,
> acl5
> -
> -                test_packet $s f000000000$d f00000000055 810000091234
>   #4
> -                test_packet $s f000000000$d 0100000000$s $s$d
>   #5
> -
> -                if test $d != $s && test $jd = 1; then
> -                    unknown="$unknown $d"
> -                fi
> -                bcast="$bcast $unicast"
> -                bacl2="$bacl2 $acl2"
> -                bacl3="$bacl3 $acl3"
> -
> -                sip=`ip_to_hex 192 168 0 $is$js`
> -                tip=`ip_to_hex 192 168 0 $id$jd`
> -                tip_unknown=`ip_to_hex 11 11 11 11`
> -                if test $d != $s; then
> -                    reply_ha=f000000000$d
> -                else
> -                    reply_ha=
> -                fi
> -                test_arp $s f000000000$s $sip $tip $reply_ha
>  #9
> -                test_arp $s f000000000$s $sip $tip_unknown
>  #10
> -
> -                if test $jd = 3; then
> -                    # lsp[123]3 has an additional ip 192.169.0.[123]3.
> -                    tip=`ip_to_hex 192 169 0 $id$jd`
> -                    test_arp $s f000000000$s $sip $tip $reply_ha
>  #9
> -                fi
> -            done
> -        done
> -
> -        # Broadcast and multicast.
> -        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast
>  #2
> -        test_packet $s 010000000000 f000000000$s ${s}ff $bcast
>  #2
> -        if test $js = 1; then
> -            bcast_impersonate=$bcast
> -        else
> -            bcast_impersonate=
> -        fi
> -        test_packet $s 010000000000 f00000000044 44ff $bcast_impersonate
>  #3
> -
> -        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown
>  #6
> -
> -        test_packet $s ffffffffffff f000000000$s 1234                #8,
> acl1
> -        test_packet $s ffffffffffff f000000000$s 1235 $bacl2         #8,
> acl2
> -        test_packet $s ffffffffffff f000000000$s 1236 $bacl3         #8,
> acl3
> -        test_packet $s 010000000000 f000000000$s 1234                #8,
> acl1
> -        test_packet $s 010000000000 f000000000$s 1235 $bacl2         #8,
> acl2
> -        test_packet $s 010000000000 f000000000$s 1236 $bacl3         #8,
> acl3
> -    done
> -done
> -
> -# set address for lp13 with invalid characters.
> -# lp13 should be configured with only 192.168.0.13.
> -ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13 invalid
> 192.169.0.13"
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -sip=`ip_to_hex 192 168 0 11`
> -tip=`ip_to_hex 192 168 0 13`
> -test_arp 11 f00000000011  $sip $tip f00000000013
> -
> -tip=`ip_to_hex 192 169 0 13`
> -#arp request for 192.169.0.13 should be flooded
> -test_arp 11 f00000000011  $sip $tip
> -
> -# dump information and flows with counters
> -ovn-sbctl dump-flows -- list multicast_group
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv3 dump ------"
> -as hv3 ovs-vsctl show
> -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
> -    done
> -done
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -# 2 hypervisors, one logical switch, 2 logical ports per hypervisor
> -# logical ports bound to chassis encap-ip.
> -AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
> -AT_KEYWORDS([ovnarp])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Create hypervisors hv[12].
> -# Add vif1[12] to hv1, vif2[12] to hv2
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2; do
> -        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j
> external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap
> options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
> -        ovn-nbctl lsp-add lsw0 lp$i$j
> -        ip_addrs="192.168.0.$i$j"
> -        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j $ip_addrs"
> -        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j
> f0:00:00:00:00:$i$j
> -    done
> -done
> -
> -get_lsp_uuid () {
> -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
> -}
> -
> -# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just do it
> -# explictly
> -
> -# For Chassis hv1
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp11],
> [0], [dnl
> -encap               : [[]]
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp12],
> [0], [dnl
> -encap               : [[]]
> -])
> -
> -# For Chassis hv2
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp21],
> [0], [dnl
> -encap               : [[]]
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp22],
> [0], [dnl
> -encap               : [[]]
> -])
> -
> -# Bind the ports to the encap-ip
> -for i in 1 2; do
> -    for j in 1 2; do
> -        as hv$i
> -        ovs-vsctl set Interface vif$i$j external-ids:encap-ip=192.168.0.$i
> -    done
> -done
> -
> -sleep 1
> -
> -# dump port bindings; since we have vxlan and geneve tunnels, we expect
> the
> -# ports to be bound to geneve tunnels.
> -
> -# For Chassis 1
> -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap
> chassis_name=hv1 type=geneve ip=192.168.0.1`
> -
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp11],
> [0], [dnl
> -encap               : ${encap_rec}
> -])
> -
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp12],
> [0], [dnl
> -encap               : ${encap_rec}
> -])
> -
> -# For Chassis 2
> -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap
> chassis_name=hv2 type=geneve ip=192.168.0.2`
> -
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp21],
> [0], [dnl
> -encap               : ${encap_rec}
> -])
> -
> -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp22],
> [0], [dnl
> -encap               : ${encap_rec}
> -])
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Make sure there is no attempt to adding duplicated flows by
> ovn-controller
> -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
> -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
> -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv${1%?}
> -}
> -
> -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 11 for
> vif11.
> -for i in 1 2; do
> -    for j in 1 2; do
> -        : > $i$j.expected
> -    done
> -done
> -test_packet() {
> -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast packets are delivered to exactly one logical switch port
> -#    (except that packets destined to their input ports are dropped).
> -
> -for is in 1 2; do
> -    for js in 1 2; do
> -        s=$is$js
> -        bcast=
> -        unknown=
> -        bacl2=
> -        bacl3=
> -        for id in 1 2 3; do
> -            for jd in 1 2 3; do
> -                d=$id$jd
> -
> -                if test $d != $s; then unicast=$d; else unicast=; fi
> -                test_packet $s f000000000$d f000000000$s $s$d $unicast
>  #1
> -            done
> -        done
> -
> -    done
> -done
> -
> -# dump information and flows with counters
> -ovn-sbctl dump-flows -- list multicast_group
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv3 dump ------"
> -as hv3 ovs-vsctl show
> -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2; do
> -    for j in 1 2; do
> -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
> -    done
> -done
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Create a logical switch and some logical ports.
> -# Turn on port security on all lports except ls1.
> -# Make ls1 a destination for unknown MACs.
> -# Add some ACLs for Ethertypes 1234, 1235, 1236.
> -ovn-nbctl ls-add lsw0
> -ovn-sbctl chassis-add hv0 geneve 127.0.0.1
> -for i in 1 2 3; do
> -    ovn-nbctl lsp-add lsw0 lp$i
> -done
> -ovn-nbctl --wait=sb sync
> -for i in 1 2 3; do
> -    ovn-sbctl lsp-bind lp$i hv0
> -    if test $i = 1; then
> -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
> 192.168.0.$i" unknown
> -    else
> -        if test $i = 3; then
> -           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64 192.169.0.$i"
> -        else
> -           ip_addrs="192.168.0.$i"
> -        fi
> -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i $ip_addrs"
> -        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
> -    fi
> -done
> -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
> -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport ==
> "lp1"' drop
> -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport ==
> "lp3"' drop
> -ovn-nbctl create Address_Set name=set1
> addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
> -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src ==
> $set1 && outport == "lp3"' drop
> -
> -ovn-nbctl --wait=sb sync
> -on_exit 'kill `cat ovn-trace.pid`'
> -ovn-trace --detach --pidfile --no-chdir
> -
> -# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 11 for
> vif11.
> -test_packet() {
> -    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
> -    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst &&
> eth.src==$eth_src"
> -    while :; do
> -        case $1 in # (
> -            -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; # (
> -            -eth) uflow="$uflow && eth.type == 0x$2"; shift; shift ;; # (
> -            *) break ;;
> -        esac
> -    done
> -    for outport; do
> -        echo "output(\"lp$outport\");"
> -    done > expout
> -
> -    AT_CAPTURE_FILE([trace])
> -    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" | tee
> trace | sed '1,/Minimal trace/d'], [0], [expout])
> -}
> -
> -# test_arp INPORT SHA SPA TPA [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
> -
> -    local request="inport == \"lp$inport\"
> -                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src == $sha
> -                   && arp.op == 1 && arp.sha == $sha && arp.spa == $spa
> -                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa == $tpa"
> -
> -    if test -z "$reply_ha"; then
> -        reply=
> -        local i
> -        for i in 1 2 3; do
> -            if test $i != $inport; then
> -                reply="${reply}output(\"lp$i\");
> -"
> -            fi
> -        done
> -    else
> -        reply="\
> -eth.dst = $sha;
> -eth.src = $reply_ha;
> -arp.op = 2;
> -arp.tha = $sha;
> -arp.sha = $reply_ha;
> -arp.tpa = $spa;
> -arp.spa = $tpa;
> -output(\"lp$inport\");
> -"
> -    fi
> -
> -    AT_CAPTURE_FILE([trace])
> -    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0
> "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
> -}
> -
> -# Send packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast packets are delivered to exactly one logical switch port
> -#    (except that packets destined to their input ports are dropped).
> -#
> -# 2. Broadcast and multicast are delivered to all logical switch ports
> -#    except the input port.
> -#
> -# 3. When port security is turned on, the switch drops packets from the
> wrong
> -#    MAC address.
> -#
> -# 4. The switch drops all packets with a VLAN tag.
> -#
> -# 5. The switch drops all packets with a multicast source address.  (This
> only
> -#    affects behavior when port security is turned off, since otherwise
> port
> -#    security would drop the packet anyway.)
> -#
> -# 6. The switch delivers packets with an unknown destination to logical
> -#    switch ports with "unknown" among their MAC addresses (and port
> -#    security disabled).
> -#
> -# 7. The switch drops unicast packets that violate an ACL.
> -#
> -# 8. The switch drops multicast and broadcast packets that violate an ACL.
> -#
> -# 9. OVN generates responses to ARP requests for known IPs, except for
> -#    requests from a port for the port's own IP.
> -#
> -# 10. No response to ARP requests for unknown IPs.
> -
> -for s in 1 2 3; do
> -    bcast=
> -    unknown=
> -    bacl2=
> -    bacl3=
> -    for d in 1 2 3; do
> -        echo
> -        echo "lp$s -> lp$d"
> -        if test $d != $s; then unicast=$d; else unicast=; fi
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s $unicast
>   #1
> -
> -        if test $d != $s && test $s = 1; then
> -            impersonate=$d
> -        else
> -            impersonate=
> -        fi
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 $impersonate
>  #3
> -
> -        if test $d != $s && test $s != 1; then acl2=$d; else acl2=; fi
> -        if test $d != $s && test $d != 3; then acl3=$d; else acl3=; fi
> -        if test $d = $s || ( (test $s = 1 || test $s = 2) && test $d =
> 3); then
> -            # Source of 1 or 2 and dest of 3 should be dropped
> -            # due to the 4th ACL that uses address_set(set1).
> -            acl4=
> -        else
> -            acl4=$d
> -        fi
> -
> -        #7, acl1 to acl4:
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1234
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1235
> $acl2
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1236
> $acl3
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1237
> $acl4
> -
> -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 -vlan
>   #4
> -        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s
>  #5
> -
> -        if test $d != $s && test $d = 1; then
> -            unknown="$unknown $d"
> -        fi
> -        bcast="$bcast $unicast"
> -        bacl2="$bacl2 $acl2"
> -        bacl3="$bacl3 $acl3"
> -
> -        sip=192.168.0.$s
> -        tip=192.168.0.$d
> -        tip_unknown=11.11.11.11
> -        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else
> reply_ha=; fi
> -        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>  #9
> -        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown
>  #10
> -
> -        if test $d = 3; then
> -            # lp3 has an additional ip 192.169.0.[123]3.
> -            tip=192.169.0.$d
> -            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>  #9
> -        fi
> -    done
> -
> -    # Broadcast and multicast.
> -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast
>  #2
> -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast
>  #2
> -    if test $s = 1; then
> -       bcast_impersonate=$bcast
> -    else
> -       bcast_impersonate=
> -    fi
> -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44
> $bcast_impersonate  #3
> -
> -    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown
>  #6
> -
> -    #8, acl1 to acl3:
> -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
> -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235 $bacl2
> -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236 $bacl3
> -
> -    #8, acl1 to acl3:
> -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
> -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235 $bacl2
> -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236 $bacl3
> -done
> -
> -AT_CLEANUP
> -
> -# 2 hypervisors, 4 logical ports per HV
> -# 2 locally attached networks (one flat, one vlan tagged over same device)
> -# 2 ports per HV on each network
> -AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# In this test cases we create 3 switches, all connected to same
> -# physical network (through br-phys on each HV). Each switch has
> -# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
> -# of VIF port name indicates the hypervisor it is bound to, e.g.
> -# lp23 means VIF 3 on hv2.
> -#
> -# Each switch's VLAN tag and their logical switch ports are:
> -#   - ls1:
> -#       - untagged
> -#       - ports: lp11, lp12, lp21, lp22
> -#
> -#   - ls2:
> -#       - tagged with VLAN 101
> -#       - ports: lp13, lp14, lp23, lp24
> -#   - ls3:
> -#       - untagged
> -#       - ports: lp15, lp25
> -#
> -# Note: a localnet port is created for each switch to connect to
> -# physical network.
> -
> -for i in 1 2 3; do
> -    ls_name=ls$i
> -    ovn-nbctl ls-add $ls_name
> -    ln_port_name=ln$i
> -    if test $i -eq 2; then
> -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
> -    else
> -        ovn-nbctl lsp-add $ls_name $ln_port_name
> -    fi
> -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
> -    ovn-nbctl lsp-set-type $ln_port_name localnet
> -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
> -done
> -
> -# lsp_to_ls LSP
> -#
> -# Prints the name of the logical switch that contains LSP.
> -lsp_to_ls () {
> -    case $1 in dnl (
> -        lp?[[12]]) echo ls1 ;; dnl (
> -        lp?[[34]]) echo ls2 ;; dnl (
> -        lp?5) echo ls3 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2 3 4 5; do
> -        ovs-vsctl add-port br-int vif$i$j -- \
> -            set Interface vif$i$j external-ids:iface-id=lp$i$j \
> -                                  options:tx_pcap=hv$i/vif$i$j-tx.pcap \
> -                                  options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
> -                                  ofport-request=$i$j
> -
> -        lsp_name=lp$i$j
> -        ls_name=$(lsp_to_ls $lsp_name)
> -
> -        ovn-nbctl lsp-add $ls_name $lsp_name
> -        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
> -        ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$j
> -
> -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
> -    done
> -done
> -ovn-nbctl --wait=sb sync
> -ovn-sbctl dump-flows
> -
> -OVN_POPULATE_ARP
> -
> -# XXX This is now the 3rd copy of these functions in this file ...
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv${1%?}
> -}
> -#
> -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is specified
> as
> -# logical switch port numbers, e.g. 11 for vif11.
> -#
> -# EOUT is the end-to-end output port, that is, where the packet will end
> up
> -# after possibly bouncing through one or more localnet ports.  LOUT is the
> -# logical output port, which might be a localnet port, as seen by
> ovn-trace
> -# (which doesn't know what localnet ports are connected to and therefore
> can't
> -# figure out the end-to-end answer).
> -for i in 1 2; do
> -    for j in 1 2 3 4 5; do
> -        : > $i$j.expected
> -    done
> -done
> -test_packet() {
> -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
> -    echo "$@"
> -
> -    # First try tracing the packet.
> -    uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src &&
> eth.type==0x$eth"
> -    if test $lout != drop; then
> -        echo "output(\"$lout\");"
> -    fi > expout
> -    AT_CAPTURE_FILE([trace])
> -    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" | tee trace
> | sed '1,/Minimal trace/d'], [0], [expout])
> -
> -    # Then actually send a packet, for an end-to-end test.
> -    local packet=$(echo $dst$src | sed 's/://g')${eth}
> -    hv=`vif_to_hv $inport`
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    if test $eout != drop; then
> -        echo $packet >> ${eout#lp}.expected
> -    fi
> -}
> -
> -# lp11 and lp21 are on the same network (phys, untagged)
> -# and on different hypervisors
> -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
> -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
> -
> -# lp11 and lp12 are on the same network (phys, untagged)
> -# and on the same hypervisor
> -test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
> -test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
> -
> -# lp13 and lp23 are on the same network (phys, VLAN 101)
> -# and on different hypervisors
> -test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
> -test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
> -
> -# lp13 and lp14 are on the same network (phys, VLAN 101)
> -# and on the same hypervisor
> -test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
> -test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
> -
> -# lp11 and lp15 are on the same network (phys, untagged),
> -# same hypervisor, and on different switches
> -test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
> -test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
> -
> -# lp11 and lp25 are on the same network (phys, untagged),
> -# different hypervisors, and on different switches
> -test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
> -test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
> -
> -# Ports that should not be able to communicate
> -test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
> -test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
> -test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
> -test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
> -test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
> -test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
> -test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
> -test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
> -
> -# Dump a bunch of info helpful for debugging if there's a failure.
> -
> -echo "------ OVN dump ------"
> -ovn-nbctl show
> -ovn-sbctl show
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2; do
> -    for j in 1 2 3 4 5; do
> -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
> -    done
> -done
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
> -AT_KEYWORDS([vtep])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Configure the Northbound database
> -ovn-nbctl ls-add lsw0
> -
> -ovn-nbctl lsp-add lsw0 lp1
> -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
> -
> -ovn-nbctl lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
> -
> -ovn-nbctl lsp-add lsw0 lp-vtep
> -ovn-nbctl lsp-set-type lp-vtep vtep
> -ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep
> vtep-logical-switch=lsw0
> -ovn-nbctl lsp-set-addresses lp-vtep unknown
> -
> -# lpr, lr and lrp1 are used for the ARP request handling test only.
> -ovn-nbctl lsp-add lsw0 lpr
> -ovn-nbctl lr-add lr
> -ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
> -ovn-nbctl set Logical_Switch_Port lpr type=router \
> -                             options:router-port=lrp1 \
> -    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
> -
> -
> -net_add n1               # Network to connect hv1, hv2, and vtep
> -net_add n2               # Network to connect vtep and hv3
> -
> -# Create hypervisor hv1 connected to n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
> options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
> -
> -# Create hypervisor hv2 connected to n1
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl add-port br-int vif2 -- set Interface vif2
> external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
> options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
> -
> -
> -# Start the vtep emulator with a leg in both networks
> -sim_add vtep
> -as vtep
> -
> -ovsdb-tool create "$ovs_base"/vtep/vtep.db
> "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
> -ovs-appctl -t ovsdb-server ovsdb-server/add-db "$ovs_base"/vtep/vtep.db
> -
> -ovs-vsctl add-br br-phys
> -net_attach n1 br-phys
> -
> -mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
> -arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
> -ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24 >/dev/null ||
> return 1
> -ovs-appctl ovs/route/add 192.168.0.3/24 br-phys >/dev/null || return 1
> -
> -ovs-vsctl add-br br-vtep
> -net_attach n2 br-vtep
> -
> -vtep-ctl add-ps br-vtep
> -vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
> -vtep-ctl add-ls lsw0
> -
> -start_daemon ovs-vtep br-vtep
> -start_daemon ovn-controller-vtep --vtep-db=unix:"$ovs_base"/vtep/db.sock
> --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -
> -OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
> -
> -OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode lsw0 |
> -               grep -- source`"])
> -# It takes more time for the update to be processed by ovs-vtep.
> -sleep 1
> -
> -# Add hv3 on the other side of the vtep
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -net_attach n2 br-phys
> -
> -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
> options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
> ofport-request=1
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 1 for vif1.
> -for i in 1 2 3; do
> -    : > $i.expected
> -done
> -test_packet() {
> -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
> -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
> -    hv=hv$inport
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -# Send packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast packets are delivered to exactly one logical switch port
> -#    (except that packets destined to their input ports are dropped).
> -#
> -# 2. Broadcast and multicast are delivered to all logical switch ports
> -#    except the input port.
> -#
> -# 3. The switch delivers packets with an unknown destination to logical
> -#    switch ports with "unknown" among their MAC addresses (and port
> -#    security disabled).
> -for s in 1 2 3; do
> -    bcast=
> -    unknown=
> -    for d in 1 2 3; do
> -        if test $d != $s; then unicast=$d; else unicast=; fi
> -        test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast
>  #1
> -
> -        # The vtep (vif3) is the only one configured for "unknown"
> -        if test $d != $s && test $d = 3; then
> -            unknown="$unknown $d"
> -        fi
> -        bcast="$bcast $unicast"
> -    done
> -
> -    # Broadcast and multicast.
> -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>  #2
> -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>  #2
> -
> -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>  #3
> -done
> -
> -# ARP request should not be responded to by logical switch router
> -# type arp responder on HV1 and HV2 and should reach directly to
> -# vif1 and vif2
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -sha=f00000000003
> -spa=`ip_to_hex 192 168 1 2`
> -tpa=`ip_to_hex 192 168 1 1`
>
> -request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -as hv3 ovs-appctl netdev-dummy/receive vif3 $request
> -echo $request >> 1.expected
> -echo $request >> 2.expected
> -
> -# dump information with counters
> -echo "------ OVN dump ------"
> -ovn-nbctl show
> -ovn-sbctl show
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 show br-int
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-ofctl -O OpenFlow13 show br-int
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv3 dump ------"
> -as hv3 ovs-vsctl show
> -# note: hv3 has no logical port bind, thus it should not have br-int
> -AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
> -[ovs-ofctl: br-int is not a bridge or a socket
> -])
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
> -done
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1],[hv2],[vtep])
> -OVN_CLEANUP_VSWITCH([hv3])
> -
> -AT_CLEANUP
> -
> -# Similar test to "hardware GW"
> -AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Configure the Northbound database
> -ovn-nbctl ls-add lsw0
> -
> -ovn-nbctl lsp-add lsw0 lp1
> -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
> -
> -ovn-nbctl lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
> -
> -ovn-nbctl lsp-add lsw0 lp-gw
> -ovn-nbctl lsp-set-type lp-gw l2gateway
> -ovn-nbctl lsp-set-options lp-gw network_name=physnet1
> l2gateway-chassis=hv_gw
> -ovn-nbctl lsp-set-addresses lp-gw unknown
> -
> -net_add n1               # Network to connect hv1, hv2, and gw
> -net_add n2               # Network to connect gw and hv3
> -
> -# Create hypervisor hv1 connected to n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
> options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
> -
> -# Create hypervisor hv2 connected to n1
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl add-port br-int vif2 -- set Interface vif2
> external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
> options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
> -
> -# Create hypervisor hv_gw connected to n1 and n2
> -# connect br-phys bridge to n1; connect hv-gw bridge to n2
> -sim_add hv_gw
> -as hv_gw
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl add-br br-phys2
> -net_attach n2 br-phys2
> -ovs-vsctl set open . external_ids:ovn-bridge-mappings="physnet1:br-phys2"
> -
> -# Add hv3 on the other side of the GW
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -net_attach n2 br-phys
> -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
> options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
> ofport-request=1
> -
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
> -for i in 1 2 3; do
> -    : > $i.expected
> -done
> -test_packet() {
> -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
> -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
> -    hv=hv$inport
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -# Send packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast packets are delivered to exactly one lport (except that
> packets
> -#    destined to their input ports are dropped).
> -#
> -# 2. Broadcast and multicast are delivered to all lports except the input
> port.
> -#
> -# 3. The lswitch delivers packets with an unknown destination to lports
> with
> -#    "unknown" among their MAC addresses (and port security disabled).
> -for s in 1 2 3 ; do
> -    bcast=
> -    unknown=
> -    for d in 1 2 3 ; do
> -        if test $d != $s; then unicast=$d; else unicast=; fi
> -        test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast
>  #1
> -
> -        # The vtep (vif3) is the only one configured for "unknown"
> -        if test $d != $s && test $d = 3; then
> -            unknown="$unknown $d"
> -        fi
> -        bcast="$bcast $unicast"
> -    done
> -
> -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>  #2
> -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>  #3
> -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>  #4
> -done
> -
> -echo "------ ovn-nbctl show ------"
> -ovn-nbctl show
> -echo "------ ovn-sbctl show ------"
> -ovn-sbctl show
> -
> -echo "------ hv1 ------"
> -as hv1 ovs-vsctl show
> -echo "------ hv1 br-int ------"
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -echo "------ hv1 br-phys ------"
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
> -
> -echo "------ hv2 ------"
> -as hv2 ovs-vsctl show
> -echo "------ hv2 br-int ------"
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -echo "------ hv2 br-phys ------"
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
> -
> -echo "------ hv_gw ------"
> -as hv_gw ovs-vsctl show
> -echo "------ hv_gw br-phys ------"
> -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
> -echo "------ hv_gw br-phys2 ------"
> -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
> -
> -echo "------ hv3 ------"
> -as hv3 ovs-vsctl show
> -echo "------ hv3 br-phys ------"
> -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
> -done
> -AT_CLEANUP
> -
> -# 3 hypervisors, 3 logical switches with 3 logical ports each, 1 logical
> router
> -AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -#
> -# Three logical switches ls1, ls2, ls3.
> -# One logical router lr0 connected to ls[123],
> -# with nine subnets, three per logical switch:
> -#
> -#    lrp11 on ls1 for subnet 192.168.11.0/24
> -#    lrp12 on ls1 for subnet 192.168.12.0/24
> -#    lrp13 on ls1 for subnet 192.168.13.0/24
> -#    ...
> -#    lrp33 on ls3 for subnet 192.168.33.0/24
> -#
> -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
> -# digits are the subnet and the last digit distinguishes the VIF.
> -for i in 1 2 3; do
> -    ovn-nbctl ls-add ls$i
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            # Add "unknown" to MAC addresses for lp?11, so packets for
> -            # MAC-IP bindings discovered via ARP later have somewhere to
> go.
> -            if test $j$k = 11; then unknown=unknown; else unknown=; fi
> -
> -            ovn-nbctl \
> -                -- lsp-add ls$i lp$i$j$k \
> -                -- lsp-set-addresses lp$i$j$k \
> -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
> -        done
> -    done
> -done
> -
> -ovn-nbctl lr-add lr0
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
> 192.168.$i$j.254/24
> -        ovn-nbctl \
> -            -- lsp-add ls$i lrp$i$j-attachment \
> -            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
> -                             options:router-port=lrp$i$j \
> -                             addresses='"00:00:00:00:ff:'$i$j'"'
> -    done
> -done
> -
> -ovn-nbctl set Logical_Switch_Port lrp33-attachment \
> -    addresses='"00:00:00:00:ff:33 192.168.33.254"'
> -
> -# Physical network:
> -#
> -# Three hypervisors hv[123].
> -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on
> hv3.
> -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
> -# lp?3[123] all on hv3.
> -
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    case $1 in dnl (
> -        ?11) echo 1 ;; dnl (
> -        ?12 | ?21 | ?22) echo 2 ;; dnl (
> -        ?13 | ?23 | ?3?) echo 3 ;;
> -    esac
> -}
> -
> -# Given the name of a logical port, prints the name of its logical router
> -# port, e.g. "vif_to_lrp 123" yields 12.
> -vif_to_lrp() {
> -    echo ${1%?}
> -}
> -
> -# Given the name of a logical port, prints the name of its logical
> -# switch, e.g. "vif_to_ls 123" yields 1.
> -vif_to_ls() {
> -    echo ${1%??}
> -}
> -
> -net_add n1
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -done
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            hv=`vif_to_hv $i$j$k`
> -                as hv$hv ovs-vsctl \
> -                -- add-port br-int vif$i$j$k \
> -                -- set Interface vif$i$j$k \
> -                    external-ids:iface-id=lp$i$j$k \
> -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
> -                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
> -                    ofport-request=$i$j$k
> -        done
> -    done
> -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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 123 for
> vif123.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            : > $i$j$k.expected
> -        done
> -    done
> -done
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    in_ls=`vif_to_ls $inport`
> -    in_lrp=`vif_to_lrp $inport`
> -    for outport; do
> -        out_ls=`vif_to_ls $outport`
> -        if test $in_ls = $out_ls; then
> -            # Ports on the same logical switch receive exactly the same
> packet.
> -            echo $packet
> -        else
> -            # Routing decrements TTL and updates source and dest MAC
> -            # (and checksum).
> -            out_lrp=`vif_to_lrp $outport`
> -            echo
> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
> -        fi >> $outport.expected
> -    done
> -}
> -
> -# test_arp INPORT SHA SPA TPA [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
> -    local
> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
> -    as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
> -
> -    # Expect to receive the broadcast ARP on the other logical switch
> ports if
> -    # IP address is not configured to the switch patch port.
> -    local i=`vif_to_ls $inport`
> -    local j k
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            # 192.168.33.254 is configured to the switch patch port for
> lrp33,
> -            # so no ARP flooding expected for it.
> -            if test $i$j$k != $inport && test $tpa != `ip_to_hex 192 168
> 33 254`; then
> -                echo $request >> $i$j$k.expected
> -            fi
> -        done
> -    done
> -
> -    # Expect to receive the reply, if any.
> -    if test X$reply_ha != X; then
> -        lrp=`vif_to_lrp $inport`
> -        local
> reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
> -        echo $reply >> $inport.expected
> -    fi
> -}
> -
> -as hv1 ovs-vsctl --columns=name,ofport list interface
> -as hv1 ovn-sbctl list port_binding
> -as hv1 ovn-sbctl list datapath_binding
> -as hv1 ovn-sbctl dump-flows
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Send IP packets between all pairs of source and destination ports:
> -#
> -# 1. Unicast IP packets are delivered to exactly one logical switch port
> -#    (except that packets destined to their input ports are dropped).
> -#
> -# 2. Broadcast IP packets are delivered to all logical switch ports
> -#    except the input port.
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -for is in 1 2 3; do
> -  for js in 1 2 3; do
> -    for ks in 1 2 3; do
> -      bcast=
> -      s=$is$js$ks
> -      smac=f00000000$s
> -      sip=`ip_to_hex 192 168 $is$js $ks`
> -      for id in 1 2 3; do
> -          for jd in 1 2 3; do
> -              for kd in 1 2 3; do
> -                d=$id$jd$kd
> -                dip=`ip_to_hex 192 168 $id$jd $kd`
> -                if test $is = $id; then dmac=f00000000$d; else
> dmac=00000000ff$is$js; fi
> -                if test $d != $s; then unicast=$d; else unicast=; fi
> -
> -                test_ip $s $smac $dmac $sip $dip $unicast #1
> -
> -                if test $id = $is && test $d != $s; then bcast="$bcast
> $d"; fi
> -              done
> -          done
> -        done
> -      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
> -      done
> -  done
> -done
> -
> -: > mac_bindings.expected
> -
> -# 3. Send an IP packet from every logical port to every other subnet,
> -#    to an IP address that does not have a static IP-MAC binding.
> -#    This should generate a broadcast ARP request for the destination
> -#    IP address in the destination subnet.
> -#    Moreover generate an ARP reply for each of the IP addresses ARPed
> -for is in 1 2 3; do
> -  for js in 1 2 3; do
> -    for ks in 1 2 3; do
> -      s=$is$js$ks
> -      smac=f00000000$s
> -      sip=`ip_to_hex 192 168 $is$js $ks`
> -      for id in 1 2 3; do
> -        for jd in 1 2 3; do
> -          if test $is$js = $id$jd; then
> -            continue
> -          fi
> -
> -          # Send the packet.
> -          dmac=00000000ff$is$js
> -          # Calculate a 4th octet for the destination that is
> -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
> -          # that have static MAC bindings, and fits in the range
> -          # 0-255.
> -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
> -          dip=`ip_to_hex 192 168 $id$jd $o4`
> -          test_ip $s $smac $dmac $sip $dip
> -
> -          # Every LP on the destination subnet's lswitch should
> -          # receive the ARP request.
> -          lrmac=00000000ff$id$jd
> -          lrip=`ip_to_hex 192 168 $id$jd 254`
> -
> arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip}
> -          for jd2 in 1 2 3; do
> -            for kd in 1 2 3; do
> -              echo $arp >> $id$jd2$kd.expected
> -            done
> -          done
> -
> -          hmac=8000000000$o4
> -          rmac=00000000ff$id$jd
> -          echo
> ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 >>
> ${id}11.expected
> -
> -          host_mac=8000000000$o4
> -          lrmac=00000000ff$id$jd
> -
> -
> arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip}
> -
> -          hv=hv`vif_to_hv ${id}${jd}1`
> -          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1 $arp_reply
> -
> -          host_ip_pretty=192.168.$id$jd.$o4
> -          host_mac_pretty=80:00:00:00:00:$o4
> -          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >>
> mac_bindings.expected
> -        done
> -      done
> -    done
> -  done
> -done
> -
> -# Test router replies to ARP requests from all source ports:
> -#
> -# 4. Router replies to query for its MAC address from port's own IP
> address.
> -#
> -# 5. Router replies to query for its MAC address from any random IP
> address
> -#    in its subnet.
> -#
> -# 6. No reply to query for IP address other than router IP.
> -#
> -# 7. No reply to query from another subnet.
> -for i in 1 2 3; do
> -  for j in 1 2 3; do
> -    for k in 1 2 3; do
> -      smac=f00000000$i$j$k               # Source MAC
> -      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
> -      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
> -      rmac=00000000ff$i$j                # Router MAC
> -      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in subnet
> -      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in subnet
> -
> -      test_arp $i$j$k $smac $sip        $rip        $rmac      #4
> -      test_arp $i$j$k $smac $otherip    $rip        $rmac      #5
> -      test_arp $i$j$k $smac $sip        $otherip               #6
> -
> -      # When rip is 192.168.33.254, ARP request from externalip won't be
> -      # filtered, because 192.168.33.254 is configured to switch peer port
> -      # for lrp33.
> -      lrp33_rsp=
> -      if test $i = 3 && test $j = 3; then
> -        lrp33_rsp=$rmac
> -      fi
> -      test_arp $i$j$k $smac $externalip $rip        $lrp33_rsp #7
> -
> -      # MAC binding should be learned from ARP request.
> -      host_mac_pretty=f0:00:00:00:0$i:$j$k
> -
> -      host_ip_pretty=192.168.$i$j.$k
> -      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
> mac_bindings.expected
> -
> -      # mac_binding is learned and overwritten so only the last one
> remains.
> -      if test $k = 3; then
> -          # lrp33 will not learn from ARP request, because 192.168.33.254
> is
> -          # configured to switch peer port for lrp33.
> -          if test $i != 3 || test $j != 3; then
> -              host_ip_pretty=192.168.$i$j.55
> -              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
> mac_bindings.expected
> -          fi
> -      fi
> -
> -    done
> -  done
> -done
> -
> -
> -# Allow some time for packet forwarding.
> -# XXX This can be improved.
> -sleep 1
> -
> -# 8. Send an IP packet from every logical port to every other subnet.
> These
> -#    are the same packets already sent as #3, but now the destinations'
> IP-MAC
> -#    bindings have been discovered via ARP, so instead of provoking an ARP
> -#    request, these packets now get routed to their destinations (which
> don't
> -#    have static MAC bindings, so they go to the port we've designated as
> -#    accepting "unknown" MACs.)
> -for is in 1 2 3; do
> -  for js in 1 2 3; do
> -    for ks in 1 2 3; do
> -      s=$is$js$ks
> -      smac=f00000000$s
> -      sip=`ip_to_hex 192 168 $is$js $ks`
> -      for id in 1 2 3; do
> -        for jd in 1 2 3; do
> -          if test $is$js = $id$jd; then
> -            continue
> -          fi
> -
> -          # Send the packet.
> -          dmac=00000000ff$is$js
> -          # Calculate a 4th octet for the destination that is
> -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
> -          # that have static MAC bindings, and fits in the range
> -          # 0-255.
> -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
> -          dip=`ip_to_hex 192 168 $id$jd $o4`
> -          test_ip $s $smac $dmac $sip $dip
> -
> -          # Expect the packet egress.
> -          host_mac=8000000000$o4
> -          outport=${id}11
> -          out_lrp=$id$jd
> -          echo
> ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000
> >> $outport.expected
> -        done
> -      done
> -    done
> -  done
> -done
> -
> -ovn-sbctl -f csv -d bare --no-heading \
> -    -- --columns=logical_port,ip,mac list mac_binding > mac_bindings
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
> -                              [$i$j$k.expected])
> -        done
> -    done
> -done
> -
> -# Check the MAC bindings against those expected.
> -AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort <
> mac_bindings.expected`
> -])
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1], [hv2], [hv3])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IP relocation using GARP request])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -#
> -# Two logical switches ls1, ls2.
> -# One logical router lr0 connected to ls[12],
> -# with 2 subnets, 1 per logical switch:
> -#
> -#    lrp1 on ls1 for subnet 192.168.1.1/24
> -#    lrp2 on ls2 for subnet 192.168.2.1/24
> -#
> -# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
> -# VIFs' fixed IP addresses are 192.168.[12].1[12].
> -#
> -# There is a secondary IP 192.168.1.100 that is unknown in NB and learned
> -# through ARP only, and it can move between lp11 and lp12.
> -#
> -ovn-nbctl lr-add lr0
> -for i in 1 2 ; do
> -    ovn-nbctl ls-add ls$i
> -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
> -    ovn-nbctl \
> -        -- lsp-add ls$i lrp$i-attachment \
> -        -- set Logical_Switch_Port lrp$i-attachment type=router \
> -                         options:router-port=lrp$i \
> -                         addresses=router
> -    for j in 1 2; do
> -        ovn-nbctl \
> -            -- lsp-add ls$i lp$i$j \
> -            -- lsp-set-addresses lp$i$j \
> -               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
> -    done
> -done
> -
> -# Physical network:
> -# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located, e.g. "vif_to_hv 12" yields 2.
> -vif_to_hv() {
> -    echo ${1#?}
> -}
> -
> -# Given the name of a logical port, prints the name of its logical router
> -# port, e.g. "vif_to_lrp 12" yields 1.
> -vif_to_lrp() {
> -    echo ${1%?}
> -}
> -
> -# Given the name of a logical port, prints the name of its logical
> -# switch, e.g. "vif_to_ls 12" yields 1.
> -vif_to_ls() {
> -    echo ${1%?}
> -}
> -
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -done
> -for i in 1 2; do
> -    for j in 1 2; do
> -        hv=`vif_to_hv $i$j`
> -            as hv$hv ovs-vsctl \
> -                -- add-port br-int vif$i$j \
> -                -- set Interface vif$i$j \
> -                    external-ids:iface-id=lp$i$j \
> -                    options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
> -                    options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
> -                    ofport-request=$i$j
> -    done
> -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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 12 for
> vif12.
> -for i in 1 2; do
> -    for j in 1 2; do
> -        : > $i$j.expected
> -    done
> -done
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    in_ls=`vif_to_ls $inport`
> -    in_lrp=`vif_to_lrp $inport`
> -    for outport; do
> -        out_ls=`vif_to_ls $outport`
> -        if test $in_ls = $out_ls; then
> -            # Ports on the same logical switch receive exactly the same
> packet.
> -            echo $packet
> -        else
> -            # Routing decrements TTL and updates source and dest MAC
> -            # (and checksum).
> -            out_lrp=`vif_to_lrp $outport`
> -            echo
> f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
> -        fi >> $outport.expected
> -    done
> -}
> -
> -# test_arp INPORT SHA SPA TPA [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
> -    local
> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
> -
> -    # Expect to receive the broadcast ARP on the other logical switch
> ports if
> -    # IP address is not configured to the switch patch port.
> -    local i=`vif_to_ls $inport`
> -    local j
> -    for j in 1 2; do
> -        if test $i$j != $inport; then
> -            echo $request >> $i$j$k.expected
> -        fi
> -    done
> -
> -    # Expect to receive the reply, if any.
> -    if test X$reply_ha != X; then
> -        lrp=`vif_to_lrp $inport`
> -        local
> reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
> -        echo $reply >> $inport.expected
> -    fi
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# lp11 send GARP request to announce ownership of 192.168.1.100.
> -
> -sha=f00000000011
> -spa=`ip_to_hex 192 168 1 100`
> -tpa=$spa
> -test_arp 11 $sha $spa $tpa
> -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="192.168.1.100" | wc
> -l` -gt 0])
> -ovn-nbctl --wait=hv sync
> -
> -# Send an IP packet from lp21 to 192.168.1.100, which should go to lp11.
> -
> -smac=f00000000021
> -dmac=00000000ff02
> -sip=`ip_to_hex 192 168 2 11`
> -dip=`ip_to_hex 192 168 1 100`
> -test_ip 21 $smac $dmac $sip $dip 11
> -
> -# lp12 send GARP request to announce ownership of 192.168.1.100.
> -
> -sha=f00000000012
> -test_arp 12 $sha $spa $tpa
> -OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" | grep
> f0:00:00:00:00:12])
> -ovn-nbctl --wait=hv sync
> -# give to the hv the time to send queued ip packets
> -sleep 1
> -
> -# Send an IP packet from lp21 to 192.168.1.100, which should go to lp12.
> -
> -test_ip 21 $smac $dmac $sip $dip 12
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2; do
> -    for j in 1 2; do
> -        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
> -                          [$i$j.expected])
> -    done
> -done
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1], [hv2])
> -
> -AT_CLEANUP
> -
> -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
> -AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Create hypervisors hv[123].
> -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
> -# Add all of the vifs to a single logical switch lsw0.
> -# Turn off port security on vifs vif[123]1
> -# Turn on l2 port security on vifs vif[123]2
> -# Turn of l2 and l3 port security on vifs vif[123]3
> -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2 3; do
> -        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j
> external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap
> options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
> -        ovn-nbctl lsp-add lsw0 lp$i$j
> -        if test $j = 1; then
> -            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
> 192.168.0.$i$j" unknown
> -        elif test $j = 2; then
> -            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
> 192.168.0.$i$j"
> -            ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
> -        else
> -            extra_addr="f0:00:00:00:0$i:$i$j fe80::ea2a:eaff:fe28:$i$j"
> -            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
> 192.168.0.$i$j" "$extra_addr"
> -            ovn-nbctl lsp-set-port-security lp$i$j "f0:00:00:00:00:$i$j
> 192.168.0.$i$j" "$extra_addr"
> -        fi
> -    done
> -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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv${1%?}
> -}
> -
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        : > $i$j.expected
> -    done
> -done
> -
> -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -#
> -# This shell function causes an ip packet to be received on INPORT.
> -# The packet's content has Ethernet destination DST and source SRC
> -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
> -# The OUTPORTs (zero or more) list the VIFs on which the packet should
> -# be received.  INPORT and the OUTPORTs are specified as logical switch
> -# port numbers, e.g. 11 for vif11.
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 reply_ha=$7
> -    local
> request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -    hv=`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
> -    if test $drop != 1; then
> -        if test X$reply_ha = X; then
> -            # Expect to receive the broadcast ARP on the other logical
> switch ports
> -            # if no reply is expected.
> -            local i j
> -            for i in 1 2 3; do
> -                for j in 1 2 3; do
> -                    if test $i$j != $inport; then
> -                        echo $request >> $i$j.expected
> -                    fi
> -                done
> -            done
> -        else
> -            # Expect to receive the reply, if any.
> -            local
> reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
> -            echo $reply >> $inport.expected
> -        fi
> -    fi
> -}
> -
> -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -# This function is similar to test_ip() except that it sends
> -# ipv6 packet
> -test_ipv6() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000
> -    shift; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
> -# This function is similar to test_ipv6() except it specifies the ICMPv6
> type
> -# of the test packet
> -test_icmpv6() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
> -    local
> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000
> -    shift; shift; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# no port security
> -sip=`ip_to_hex 192 168 0 12`
> -tip=`ip_to_hex 192 168 0 13`
> -# the arp packet should be allowed even if lp[123]1 is
> -# not configured with mac f00000000023 and ip 192.168.0.12
> -for i in 1 2 3; do
> -    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 f00000000013
> -    for j in 1 2 3; do
> -        if test $i != $j; then
> -            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip $tip ${j}1
> -        fi
> -    done
> -done
> -
> -# l2 port security
> -sip=`ip_to_hex 192 168 0 12`
> -tip=`ip_to_hex 192 168 0 13`
> -
> -# arp packet should be allowed since lp22 is configured with
> -# mac f00000000022
> -test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
> -
> -# arp packet should not be allowed since lp32 is not configured with
> -# mac f00000000021
> -test_arp 32 f00000000021 f00000000021 $sip $tip 1
> -
> -# arp packet with sha set to f00000000021 should not be allowed
> -# for lp12
> -test_arp 12 f00000000012 f00000000021 $sip $tip 1
> -
> -# ip packets should be allowed and received since lp[123]2 do not
> -# have l3 port security
> -sip=`ip_to_hex 192 168 0 55`
> -tip=`ip_to_hex 192 168 0 66`
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        if test $i != $j; then
> -            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip $tip ${j}2
> -        fi
> -    done
> -done
> -
> -# ipv6 packets should be received by lp[123]2
> -# lp[123]1 can send ipv6 traffic as there is no port security
> -sip=fe800000000000000000000000000000
> -tip=ff020000000000000000000000000000
> -
> -for i in 1 2 3; do
> -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip ${i}2
> -done
> -
> -
> -# l2 and l3 port security
> -sip=`ip_to_hex 192 168 0 13`
> -tip=`ip_to_hex 192 168 0 22`
> -# arp packet should be allowed since lp13 is configured with
> -# f00000000013 and 192.168.0.13
> -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
> -
> -# the arp packet should be dropped because lp23 is not configured
> -# with mac f00000000022
> -sip=`ip_to_hex 192 168 0 13`
> -tip=`ip_to_hex 192 168 0 22`
> -test_arp 23 f00000000022 f00000000022 $sip $tip 1
> -
> -# the arp packet should be dropped because lp33 is not configured
> -# with ip 192.168.0.55
> -spa=`ip_to_hex 192 168 0 55`
> -tpa=`ip_to_hex 192 168 0 22`
> -test_arp 33 f00000000031 f00000000031 $spa $tpa 1
> -
> -# ip packets should not be received by lp[123]3 since
> -# l3 port security is enabled
> -sip=`ip_to_hex 192 168 0 55`
> -tip=`ip_to_hex 192 168 0 66`
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
> -    done
> -done
> -
> -# ipv6 packets should be dropped for lp[123]3 since
> -# it is configured with only ipv4 address
> -sip=fe800000000000000000000000000000
> -tip=ff020000000000000000000000000000
> -
> -for i in 1 2 3; do
> -    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
> -done
> -
> -# ipv6 packets should not be received by lp[123]3 with mac
> f000000000$[123]3
> -# lp[123]1 can send ipv6 traffic as there is no port security
> -for i in 1 2 3; do
> -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
> -done
> -
> -# lp13 has extra port security with mac f0000000113 and ipv6 addr
> -# fe80::ea2a:eaff:fe28:0012
> -
> -# ipv4 packet should be dropped for lp13 with mac f0000000113
> -sip=`ip_to_hex 192 168 0 13`
> -tip=`ip_to_hex 192 168 0 23`
> -test_ip 13 f00000000113 f00000000023 $sip $tip
> -
> -# ipv6 packet should be received by lp[123]3 with mac f00000000${i}${i}3
> -# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
> -# lp11 can send ipv6 traffic as there is no port security
> -sip=ee800000000000000000000000000000
> -for i in 1 2 3; do
> -    tip=fe80000000000000ea2aeafffe2800${i}3
> -    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
> -done
> -
> -
> -# ipv6 packet should not be received by lp33 with mac f0000000333
> -# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
> -# configured with fe80::ea2a:eaff:fe28:0033
> -# lp11 can send ipv6 traffic as there is no port security
> -
> -sip=ee800000000000000000000000000000
> -tip=fe80000000000000ea2aeafffe280023
> -test_ipv6 11 f00000000011 f00000000333 $sip $tip
> -
> -# ipv6 packet should be allowed for lp[123]3 with mac f0000000${i}${i}3
> -# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
> -# and should be dropped for any other ip6.src
> -# lp21 can receive ipv6 traffic as there is no port security
> -
> -tip=ee800000000000000000000000000000
> -for i in 1 2 3; do
> -    sip=fe80000000000000ea2aeafffe2800${i}3
> -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
> -
> -    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
> -    sip=00000000000000000000000000000000
> -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
> ff020000000000000000000000160000 83 21
> -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
> ff020000000000000000000000160000 8f 21
> -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
> ff0200000000000000ea2aeafffe2800 87 21
> -    # Traffic to non-multicast traffic should be dropped
> -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
> -    # Traffic of other ICMPv6 types should be dropped
> -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
> ff020000000000000000000000160000 80
> -
> -    # should be dropped
> -    sip=ae80000000000000ea2aeafffe2800aa
> -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
> -done
> -
> -# configure lsp13 to send and received IPv4 packets with an address range
> -ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13 192.168.0.13
> 20.0.0.4/24 10.0.0.0/24"
> -
> -sleep 2
> -
> -sip=`ip_to_hex 10 0 0 13`
> -tip=`ip_to_hex 192 168 0 22`
> -# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
> -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
> -
> -sip=`ip_to_hex 10 0 0 14`
> -tip=`ip_to_hex 192 168 0 23`
> -# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
> -# with dst ip 192.168.0.23 should be allowed
> -test_ip 13 f00000000013 f00000000023 $sip $tip 23
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 10 0 0 15`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 10.0.0.15 should be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip 13
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 20 0 0 4`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 20.0.0.4 should be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip 13
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 20 0 0 5`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 20.0.0.5 should not be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 20 0 0 255`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 20.0.0.255 should be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip 13
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 192 168 0 255`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 192.168.0.255 should not be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip
> -
> -sip=`ip_to_hex 192 168 0 33`
> -tip=`ip_to_hex 224 0 0 4`
> -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
> -# with dst ip 224.0.0.4  should be received by lsp13
> -test_ip 33 f00000000033 f00000000013 $sip $tip 13
> -
> -#dump information including flow counters
> -ovn-nbctl show
> -ovn-sbctl dump-flows -- list multicast_group
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 show br-int
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-ofctl -O OpenFlow13 show br-int
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -echo "------ hv3 dump ------"
> -as hv3 ovs-vsctl show
> -as hv3 ovs-ofctl -O OpenFlow13 show br-int
> -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
> -    done
> -done
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other as peers in
> 20.0.0.0/24
> -# network. R1 has a switchs ls1 (191.168.1.0/24) connected to it.
> -# R2 has ls2 (172.16.1.0/24) connected to it.
> -
> -ls1_lp1_mac="f0:00:00:01:02:03"
> -rp_ls1_mac="00:00:00:01:02:03"
> -rp_ls2_mac="00:00:00:01:02:04"
> -ls2_lp1_mac="f0:00:00:01:02:04"
> -
> -ls1_lp1_ip="192.168.1.2"
> -ls2_lp1_ip="172.16.1.2"
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lr-add R2
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
> -
> -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
> type=router \
> -  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
> -
> -# Connect ls2 to R2
> -ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
> -
> -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
> type=router \
> -  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
> -
> -# Connect R1 to R2
> -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
> -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
> -
> -ovn-nbctl lr-route-add R1 "0.0.0.0/0" 20.0.0.2
> -ovn-nbctl lr-route-add R2 "0.0.0.0/0" 20.0.0.1
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
> -
> -# Create logical port ls2-lp1 in ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Packet to send.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
> eth.dst==$rp_ls1_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip
> &&
> -        udp && udp.src==53 && udp.dst==4369"
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -
> -# Packet to Expect
> -# The TTL should be decremented by 2.
> -packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
> -        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip
> &&
> -        udp && udp.src==53 && udp.dst==4369"
> -echo $packet | ovstest test-ovn expr-to-packets > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
> -grep "reg0 == 172.16.1.2" | wc -l], [0], [1
> -])
> -
> -# Disable the ls2-lp1 port.
> -ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
> -
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
> -grep "reg0 == 172.16.1.2" | wc -l], [0], [0
> -])
> -
> -# Generate the packet destined for ls2-lp1 and it should not be delivered.
> -# Packet to send.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
> eth.dst==$rp_ls1_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip
> &&
> -        udp && udp.src==53 && udp.dst==4369"
> -
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -# The 2nd packet sent shound not be received.
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -
> -AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
> -AT_KEYWORDS([router-admin-state])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR - R1 has switch ls1 with two subnets attached to it (
> 191.168.1.0/24
> -# and 172.16.1.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add ls1
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24 172.16.1.1/24
> -ovn-nbctl <http://172.16.1.1/24-ovn-nbctl> lsp-add ls1 rp-ls1 -- set
> Logical_Switch_Port rp-ls1 type=router \
> -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> -          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port ls1-lp2 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp2 \
> -          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Create one hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int vif1 -- \
> -    set interface vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif2 -- \
> -    set interface vif2 external-ids:iface-id=ls1-lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=1
> -
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Send ip packets between the two ports.
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Packet to send.
> -src_mac="f00000010203"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
> -
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -
> -#Disable router R1
> -ovn-nbctl set Logical_Router R1 enabled=false
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
> -
> -# Packet to Expect
> -expect_src_mac="000000010203"
> -expect_dst_mac="f00000010204"
> -echo
> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -
> -AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
> -AT_KEYWORDS([router-admin-state])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
> -# and has switch ls2 (172.16.1.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
> type=router \
> -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
> -
> -# Connect ls2 to R1
> -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
> -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
> type=router \
> -          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port ls2-lp1 in ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Create one hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int vif1 -- \
> -    set interface vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif2 -- \
> -    set interface vif2 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=1
> -
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Send ip packets between the two ports.
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Packet to send.
> -src_mac="f00000010203"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
> -
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -#Disable router R1
> -ovn-nbctl set Logical_Router R1 enabled=false
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Allow some time for the disabling of logical router R1 to propagate.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
> -
> -# Packet to Expect
> -expect_src_mac="000000010204"
> -expect_dst_mac="f00000010204"
> -echo
> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static routes])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other as peers in
> 20.0.0.0/24
> -# network. R1 has switchess foo (192.168.1.0/24)
> -# connected to it.
> -# R2 has alice (172.16.1.0/24) and bob (172.16.2.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lr-add R2
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add bob
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -          type=router options:router-port=alice
> addresses=\"00:00:00:01:02:04\"
> -
> -# Connect bob to R2
> -ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
> -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob
> type=router \
> -          options:router-port=bob addresses=\"00:00:00:01:02:05\"
> -
> -# Connect R1 to R2
> -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
> -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
> -
> -#install static routes
> -ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> -ovn-nbctl lr-route-add R2 172.16.2.0/24 20.0.0.2 R1_R2
> -ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Create logical port bob1 in bob
> -ovn-nbctl lsp-add bob bob1 \
> --- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=bob1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="f00000010203"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -# Send ip packets between foo1 and bob1
> -src_mac="f00000010203"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 2 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump ----------"
> -as hv2 ovs-ofctl dump-flows br-int
> -
> -# Packet to Expect at bob1
> -src_mac="000000010205"
> -dst_mac="f00000010205"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 2 2`
> -echo
> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Packet to Expect at alice1
> -src_mac="000000010204"
> -dst_mac="f00000010204"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
> -echo
> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send gratuitous arp on localnet])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0
> -
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-eth0])
> -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif
> options:tx_pcap=hv/snoopvif-tx.pcap options:rxq_pcap=hv/snoopvif-rx.pcap])
> -
> -# Create a vif.
> -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01
> 192.168.1.2"])
> -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
> -
> -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1
> external_ids:iface-id=localvif1])
> -
> -# Wait for packet to be received.
> -echo
> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102"
> > expected
> -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
> -
> -# Check GARP packet when restart openflow connection.
> -as hv
> -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> -
> -OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect"
> hv/ovn-controller.log])
> -
> -as hv
> -start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif
> -vunixctl
> -
> -# Wait for packet to be received.
> -echo
> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102"
> > expected
> -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
> -
> -# Delete the localnet ports.
> -AT_CHECK([ovs-vsctl del-port localvif1])
> -AT_CHECK([ovn-nbctl lsp-del ln_port])
> -
> -OVN_CLEANUP([hv])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
> -# connected to it. R2 has alice (172.16.1.0/24) and R3 has bob (
> 10.32.1.0/24)
> -# connected to it.
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lr-add R2
> -ovn-nbctl lr-add R3
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add bob
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect bob to R3
> -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
> -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
> -    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Connect R3 to join
> -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
> -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
> -    type=router options:router-port=R3_join
> addresses='"00:00:04:01:02:05"'
> -
> -#install static routes
> -ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> -ovn-nbctl lr-route-add R1 10.32.1.0/24 20.0.0.3
> -
> -ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
> -ovn-nbctl lr-route-add R2 10.32.1.0/24 20.0.0.3
> -
> -ovn-nbctl lr-route-add R3 192.168.1.0/24 20.0.0.1
> -ovn-nbctl lr-route-add R3 172.16.1.0/24 20.0.0.2
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Create logical port bob1 in bob
> -ovn-nbctl lsp-add bob bob1 \
> --- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=bob1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
> -
> -# Send ip packets between foo1 and bob1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 10 32 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -echo "----------------------------"
> -
> -# Packet to Expect at bob1
> -src_mac="000003010203"
> -dst_mac="f00000010205"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 10 32 1 2`
> -echo
> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Packet to Expect at alice1
> -src_mac="000002010203"
> -dst_mac="f00000010204"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
> -echo
> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -ovn-nbctl lsp-add ls1 ls1-lp2 \
> --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6
> 20.0.0.4"
> -
> -ovn-nbctl ls-add ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
> -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 30.0.0.6
> 40.0.0.4"
> -ovn-nbctl lsp-add ls2 ls2-lp2 \
> --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
> -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
> -
> -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
> -options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
> -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
> -
> -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
> -ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
> -
> -d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24 \
> -options="\"server_id\"=\"30.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:02\" \
> -\"lease_time\"=\"3600\"")"
> -
> -ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
> -
> -net_add n1
> -sim_add hv1
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -ovs-vsctl -- add-port br-int hv1-vif3 -- \
> -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=hv1/vif3-tx.pcap \
> -    options:rxq_pcap=hv1/vif3-rx.pcap \
> -    ofport-request=3
> -
> -ovs-vsctl -- add-port br-int hv1-vif4 -- \
> -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
> -    options:tx_pcap=hv1/vif4-tx.pcap \
> -    options:rxq_pcap=hv1/vif4-rx.pcap \
> -    ofport-request=4
> -
> -OVN_POPULATE_ARP
> -
> -sleep 2
> -
> -as hv1 ovs-vsctl show
> -
> -# This shell function sends a DHCP request packet
> -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
> -test_dhcp() {
> -    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5
> request_ip=$6 use_ip=$7
> -    shift; shift; shift; shift; shift; shift; shift;
> -    if test $use_ip != 0; then
> -        src_ip=$1
> -        dst_ip=$2
> -        shift; shift;
> -    else
> -        src_ip=`ip_to_hex 0 0 0 0`
> -        dst_ip=`ip_to_hex 255 255 255 255`
> -    fi
> -    if test $request_ip != 0; then
> -        ip_len=0120
> -        udp_len=010b
> -    else
> -        ip_len=011a
> -        udp_len=0106
> -    fi
> -    local
> request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip}
> -    # udp header and dhcp header
> -    request=${request}00440043${udp_len}0000
> -
> request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac}
> -    # client hardware padding
> -    request=${request}00000000000000000000
> -    # server hostname
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -    # boot file name
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -    # dhcp magic cookie
> -    request=${request}63825363
> -    # dhcp message type
> -    request=${request}3501${dhcp_type}
> -    # dhcp unknown option
> -    request=${request}d70701020304050607
> -    # dhcp pad option
> -    request=${request}00
> -    if test $request_ip != 0; then
> -        # dhcp requested ip
> -        request=${request}3204${request_ip}
> -    fi
> -    # dhcp end option
> -    request=${request}ff
> -
> -    for port in $inport "$@"; do
> -        : >> $port.expected
> -    done
> -    if test $offer_ip != 0; then
> -        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3
> expected_dhcp_opts=$4
> -        # total IP length will be the IP length of the request packet
> -        # (which is 272 in our case) + 8 (padding bytes) +
> (expected_dhcp_opts / 2)
> -        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
> -        udp_len=`expr $ip_len - 20`
> -        ip_len=$(printf "%x" $ip_len)
> -        udp_len=$(printf "%x" $udp_len)
> -        # $ip_len var will be in 3 digits i.e 134. So adding a '0' before
> $ip_len
> -        local
> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
> -        # udp header and dhcp header.
> -        # $udp_len var will be in 3 digits. So adding a '0' before
> $udp_len
> -
> reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
> -        # your ip address; 0 for NAK
> -        if test $dhcp_reply_type = 06; then
> -            reply=${reply}00000000
> -        else
> -            reply=${reply}${offer_ip}
> -        fi
> -        # next server ip address, relay agent ip address, client mac
> address
> -        reply=${reply}0000000000000000${src_mac}
> -        # client hardware padding
> -        reply=${reply}00000000000000000000
> -        # server hostname
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -        # boot file name
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -        # dhcp magic cookie
> -        reply=${reply}63825363
> -
> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
> -        echo $reply >> $inport.expected
> -    else
> -        for outport; do
> -            echo $request >> $outport.expected
> -        done
> -    fi
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -AT_CAPTURE_FILE([ofctl_monitor0.log])
> -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Send DHCPDISCOVER.
> -offer_ip=`ip_to_hex 10 0 0 4`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=`ip_to_hex 0 0 0 0`
> -request_ip=0
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0 ff1000000001
> $server_ip 02 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 1.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
> -cat 1.expected | cut -c -48 > expout
> -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 1.expected | cut -c 53- > expout
> -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
> -
> -# ovs-ofctl also resumes the packets and this causes other ports to
> receive
> -# the DHCP request packet. So reset the pcap files so that its easier to
> test.
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
> -# address in the Requested IP Address option.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=`ip_to_hex 0 0 0 0`
> -request_ip=$offer_ip
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001
> $server_ip 05 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a mismatched
> IP in
> -# the Requested IP Address option, expect a DHCPNAK.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=`ip_to_hex 0 0 0 0`
> -request_ip=`ip_to_hex 10 0 0 7`
> -expected_dhcp_opts=""
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001
> $server_ip 06 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 3.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by
> ovn-controller
> -# but should be resumed without the reply.
> -# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet twice,
> -# one from ovn-controller and the other from "ovs-ofctl resume."
> -ciaddr=`ip_to_hex 0 0 0 0`
> -offer_ip=0
> -request_ip=0
> -test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
> -
> -# NXT_RESUMEs should be 4.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -# vif1-tx.pcap should have received the DHCPv4 (invalid) request packet
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4 options
> defined.
> -# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet once.
> -
> -ciaddr=`ip_to_hex 0 0 0 0`
> -test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
> -
> -# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not defined for
> -# this lport.
> -ciaddr=`ip_to_hex 0 0 0 0`
> -test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
> -
> -# NXT_RESUMEs should be 4.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
> -#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
> -
> -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to
> 10.0.0.6
> -# and ip4.dst set to 10.0.0.1.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=$offer_ip
> -request_ip=0
> -src_ip=$offer_ip
> -dst_ip=$server_ip
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip
> $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 5.
> -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to
> 10.0.0.6
> -# and ip4.dst set to 255.255.255.255.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=$offer_ip
> -request_ip=0
> -src_ip=$offer_ip
> -dst_ip=`ip_to_hex 255 255 255 255`
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip
> $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 6.
> -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST in the RENEWING/REBINDING state with a mismatched IP
> in the
> -# ciaddr, expect a DHCPNAK.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=`ip_to_hex 10 0 0 7`
> -request_ip=0
> -src_ip=$offer_ip
> -dst_ip=`ip_to_hex 255 255 255 255`
> -expected_dhcp_opts=""
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip
> $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 7.
> -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST in the RENEWING/REBINDING state without a specifyied
> ciaddr,
> -# expect a DHCPNAK.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -ciaddr=`ip_to_hex 0 0 0 0`
> -request_ip=0
> -src_ip=$offer_ip
> -dst_ip=`ip_to_hex 255 255 255 255`
> -expected_dhcp_opts=""
> -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip
> $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 8.
> -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set to
> 10.0.0.4.
> -# The packet should not be received by ovn-controller.
> -ciaddr=`ip_to_hex 0 0 0 0`
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 4`
> -test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
> -
> -# NXT_RESUMEs should be 8.
> -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -# vif1-tx.pcap should have received the DHCPv4 request packet
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4
> ae70::4"
> -
> -ovn-nbctl lsp-add ls1 ls1-lp2 \
> --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
> -
> -ovn-nbctl lsp-add ls1 ls1-lp3 \
> --- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
> -
> -d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
> -options="\"server_id\"=\"00:00:00:10:00:01\"")"
> -
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
> -
> -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
> -options="\"dhcpv6_stateless\"=\"true\"
> \"server_id\"=\"00:00:00:10:00:01\"")"
> -
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
> -
> -ovn-nbctl ls-add ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
> -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 be70::3"
> -ovn-nbctl lsp-add ls2 ls2-lp2 \
> --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
> -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 be70::4"
> -
> -net_add n1
> -sim_add hv1
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -ovs-vsctl -- add-port br-int hv1-vif3 -- \
> -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=hv1/vif3-tx.pcap \
> -    options:rxq_pcap=hv1/vif3-rx.pcap \
> -    ofport-request=3
> -
> -ovs-vsctl -- add-port br-int hv1-vif4 -- \
> -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
> -    options:tx_pcap=hv1/vif4-tx.pcap \
> -    options:rxq_pcap=hv1/vif4-rx.pcap \
> -    ofport-request=4
> -
> -ovs-vsctl -- add-port br-int hv1-vif5 -- \
> -    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
> -    options:tx_pcap=hv1/vif5-tx.pcap \
> -    options:rxq_pcap=hv1/vif5-rx.pcap \
> -    ofport-request=5
> -
> -OVN_POPULATE_ARP
> -
> -sleep 2
> -
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -# This shell function sends a DHCPv6 request packet
> -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
> -# The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
> -# packet should be received twice (one from ovn-controller and the other
> -# from the "ovs-ofctl monitor br-int resume"
> -test_dhcpv6() {
> -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
> -    if test $msg_code != 0b; then
> -        req_len=2a
> -    else
> -        req_len=1a
> -    fi
> -    local
> request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
> -    # dst ip ff02::1:2
> -    request=${request}ff020000000000000000000000010002
> -    # udp header and dhcpv6 header
> -    request=${request}0222022300${req_len}ffff${msg_code}010203
> -    # Client identifier
> -    request=${request}0001000a00030001${src_mac}
> -    # Add IA-NA (Identity Association for Non Temporary Address) if
> msg_code
> -    # is not 11 (information request packet)
> -    if test $msg_code != 0b; then
> -        request=${request}0003000c0102030400000e1000001518
> -    fi
> -    shift; shift; shift; shift; shift;
> -    if test $offer_ip != 0; then
> -        local server_mac=000000100001
> -        local server_lla=fe80000000000000020000fffe100001
> -        local reply_code=07
> -        if test $msg_code = 01; then
> -            reply_code=02
> -        fi
> -        local msg_len=54
> -        if test $offer_ip = 1; then
> -            msg_len=28
> -        fi
> -        local
> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla}
> -        # udp header and dhcpv6 header
> -        reply=${reply}0223022200${msg_len}ffff${reply_code}010203
> -        # Client identifier
> -        reply=${reply}0001000a00030001${src_mac}
> -        # IA-NA
> -        if test $offer_ip != 1; then
> -
> reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
> -        fi
> -        # Server identifier
> -        reply=${reply}0002000a00030001${server_mac}
> -        echo $reply | trim_zeros >> $inport.expected
> -    else
> -        for outport; do
> -            echo $request | trim_zeros >> $outport.expected
> -        done
> -    fi
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -AT_CAPTURE_FILE([ofctl_monitor0.log])
> -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -src_mac=f00000000001
> -src_lla=fe80000000000000f20000fffe000001
> -offer_ip=ae700000000000000000000000000004
> -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
> -
> -# NXT_RESUMEs should be 1.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap |
> trim_zeros > 1.packets
> -# cat 1.expected | trim_zeros > expout
> -cat 1.expected | cut -c -120 > expout
> -AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
> -# Skipping the UDP checksum
> -cat 1.expected | cut -c 125- > expout
> -AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
> -
> -rm  1.expected
> -
> -# Send invalid packet on ls1-lp2. ovn-controller should resume the packet
> -# without any modifications and the packet should be received by ls1-lp1.
> -# ls1-lp1 will receive the packet twice, one from the ovn-controller
> after the
> -# resume and the other from ovs-ofctl monitor resume.
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -
> -src_mac=f00000000002
> -src_lla=fe80000000000000f20000fffe000002
> -offer_ip=ae700000000000000000000000000005
> -# Set invalid msg_type
> -
> -test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
> -
> -# NXT_RESUMEs should be 2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -# vif2-tx.pcap should not have received the DHCPv6 reply packet
> -rm 2.packets
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap |
> trim_zeros > 2.packets
> -AT_CHECK([cat 2.packets], [0], [])
> -
> -# vif1-tx.pcap should have received the DHCPv6 (invalid) request packet
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap |
> trim_zeros > 1.packets
> -cat 1.expected > expout
> -AT_CHECK([cat 1.packets], [0], [expout])
> -
> -# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on this port.
> -# There should be no DHCPv6 reply from ovn-controller and the request
> packet
> -# should be received by ls2-lp2.
> -
> -src_mac=f00000000003
> -src_lla=fe80000000000000f20000fffe000003
> -test_dhcpv6 3 $src_mac $src_lla 01 0 4
> -
> -# NXT_RESUMEs should be 2 only.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -# vif3-tx.pcap should not have received the DHCPv6 reply packet
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap |
> trim_zeros > 3.packets
> -AT_CHECK([cat 3.packets], [0], [])
> -
> -# vif4-tx.pcap should have received the DHCPv6 request packet
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif4-tx.pcap |
> trim_zeros > 4.packets
> -cat 4.expected > expout
> -AT_CHECK([cat 4.packets], [0], [expout])
> -
> -# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless mode
> for this port.
> -# The DHCPv6 reply shouldn't contain offer_ip.
> -src_mac=f00000000022
> -src_lla=fe80000000000000f20000fffe000022
> -reset_pcap_file hv1-vif5 hv1/vif5
> -test_dhcpv6 5 $src_mac $src_lla 01 1 5
> -
> -# NXT_RESUMEs should be 3.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap |
> trim_zeros > 5.packets
> -# Skipping the UDP checksum
> -cat 5.expected | cut -c 1-120,125- > expout
> -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
> -
> -# Send DHCPv6 information request (code 11) on ls1-lp3. The DHCPv6 reply
> -# shouldn't contain offer_ip
> -src_mac=f00000000022
> -src_lla=fe80000000000000f20000fffe000022
> -reset_pcap_file hv1-vif5 hv1/vif5
> -rm -f 5.expected
> -test_dhcpv6 5 $src_mac $src_lla 0b 1 5
> -
> -# NXT_RESUMEs should be 4.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap |
> -trim_zeros > 5.packets
> -# Skipping the UDP checksum
> -cat 5.expected | cut -c 1-120,125- > expout
> -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
> -# connected to it. R2 has alice (172.16.1.0/24) connected to it.
> -# R2 is a gateway router.
> -
> -
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -# 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
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -
> -#install static routes
> -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
> -ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \
> -R1 static_routes @lrt
> -
> -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
> -ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
> -R2 static_routes @lrt
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 2
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -ovn-sbctl list chassis
> -ovn-sbctl list encap
> -echo "---------------------"
> -
> -# Packet to Expect at alice1
> -src_mac="000002010203"
> -dst_mac="f00000010204"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
> -
> -
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
> -
> -echo "------ hv1 dump after packet 1 ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump after packet 1 ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -echo "----------------------------"
> -
> -echo $expected > expected
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Delete the router and re-create it. Things should work as before.
> -ovn-nbctl  lr-del R2
> -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -
> -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
> -ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
> -R2 static_routes @lrt
> -
> -# Wait for ovn-controller to catch up.
> -sleep 1
> -
> -# Send the packet again.
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -echo "------ hv1 dump after packet 2 ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump after packet 2 ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -echo "----------------------------"
> -
> -echo $expected >> expected
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
> -AT_KEYWORDS([router-icmp-reply])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
> -# and has switch ls2 (172.16.1.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
> -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
> -    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
> -
> -# Connect ls2 to R1
> -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
> -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
> -    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port ls2-lp1 in ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
> -
> -# Create one hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int vif1 -- \
> -    set interface vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif2 -- \
> -    set interface vif2 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=1
> -
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -for i in 1 2; do
> -    : > vif$i.expected
> -done
> -# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST
> IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ICMPv4
> -# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
> -# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are
> -# provided, then it should be the ip and icmp checksums of the packet
> -# responded; otherwise, no reply is expected.
> -# In the absence of an ip checksum calculation helpers, this relies
> -# on the caller to provide the checksums for the ip and icmp headers.
> -# XXX This should be more systematic.
> -#
> -# INPORT is an lport number, e.g. 11 for vif11.
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC and IPV4_DST are each 8 hex digits.
> -# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
> -# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
> -test_ipv4_icmp_request() {
> -    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5
> ip_chksum=$6 icmp_chksum=$7
> -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
> -    shift; shift; shift; shift; shift; shift; shift
> -    shift; shift
> -
> -    # Use ttl to exercise section 4.2.2.9 of RFC1812
> -    local ip_ttl=01
> -    local icmp_id=5fbf
> -    local icmp_seq=0001
> -    local icmp_data=$(seq 1 56 | xargs printf "%02x")
> -    local icmp_type_code_request=0800
> -    local
> icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
> -    local
> packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload}
> -
> -    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
> -    if test X$exp_icmp_chksum != X; then
> -        # Expect to receive the reply, if any. In same port where packet
> was sent.
> -        # Note: src and dst fields are expected to be reversed.
> -        local icmp_type_code_response=0000
> -        local reply_icmp_ttl=fe
> -        local
> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
> -        local
> reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
> -        echo $reply >> vif$inport.expected
> -    fi
> -}
> -
> -# Send ping packet to router's ip addresses, from each of the 2 logical
> ports.
> -rtr_l1_ip=$(ip_to_hex 192 168 1 1)
> -rtr_l2_ip=$(ip_to_hex 172 16 1 1)
> -l1_ip=$(ip_to_hex 192 168 1 2)
> -l2_ip=$(ip_to_hex 172 16 1 2)
> -
> -# Ping router ip address that is on same subnet as the logical port
> -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l1_ip 0000
> 8510 02ff 8d10
> -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l2_ip 0000
> 8510 02ff 8d10
> -
> -# Ping router ip address that is on the other side of the logical ports
> -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l2_ip 0000
> 8510 02ff 8d10
> -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l1_ip 0000
> 8510 02ff 8d10
> -
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list logical_flow
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Now check the packets actually received against the ones expected.
> -for inport in 1 2; do
> -    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap], [vif$inport.expected])
> -done
> -
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
> -AT_KEYWORDS([policy-based-routing])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
> -# and has switch ls2 (172.16.1.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -ovn-nbctl ls-add ls3
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
> -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
> -    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
> -
> -# Connect ls2 to R1
> -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
> -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
> -    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
> -
> -# Connect ls3 to R1
> -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
> -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
> -    type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port ls2-lp1 in ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
> -
> -# Create logical port ls3-lp1 in ls3
> -ovn-nbctl lsp-add ls3 ls3-lp1 \
> --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
> -
> -# Create one hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add pbr-hv
> -as pbr-hv
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -ovs-vsctl -- add-port br-int vif1 -- \
> -    set interface vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif2 -- \
> -    set interface vif2 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif3 -- \
> -    set interface vif3 external-ids:iface-id=ls3-lp1 \
> -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
> -    ofport-request=1
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ls1_ro_mac=00:00:00:01:02:f1
> -ls1_ro_ip=192.168.1.1
> -
> -ls2_ro_mac=00:00:00:01:02:f2
> -ls2_ro_ip=172.16.1.1
> -
> -ls3_ro_mac=00:00:00:01:02:f3
> -
> -ls1_p1_mac=00:00:00:01:02:03
> -ls1_p1_ip=192.168.1.2
> -
> -ls2_p1_mac=00:00:00:01:02:04
> -ls2_p1_ip=172.16.1.2
> -
> -ls3_p1_mac=00:00:00:01:02:05
> -
> -# Create a drop policy
> -ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24 && ip4.dst==
> 172.16.1.0/24" drop
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" |
> wc -l], [0], [dnl
> -1
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Check if packet hit the drop policy
> -AT_CHECK([ovs-ofctl dump-flows br-int | \
> -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24 actions=drop" | \
> -    grep "priority=10" | \
> -    grep "n_packets=1" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Expected to drop the packet.
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap >
> vif2.packets
> -rcvd_packet=`cat vif2.packets`
> -AT_FAIL_IF([rcvd_packet = ""])
> -
> -# Override drop policy with allow
> -ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24 && ip4.dst==
> 172.16.1.0/24" allow
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" |
> wc -l], [0], [dnl
> -2
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Check if packet hit the allow policy
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
> -    grep "192.168.1.0" | \
> -    grep "priority=20" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
> -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > expected
> -
> -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
> -
> -# Override allow policy with reroute
> -ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.dst==
> 172.16.1.0/24" reroute 20.20.1.2
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
> -    grep "192.168.1.0" | \
> -    grep "priority=30" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -echo "southbound flows"
> -
> -ovn-sbctl dump-flows | grep lr_in_policy
> -echo "ovs flows"
> -ovs-ofctl dump-flows br-int
> -# Check if packet hit the allow policy
> -AT_CHECK([ovs-ofctl dump-flows br-int | \
> -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" | \
> -    grep "priority=30" | \
> -    grep "n_packets=1" | wc -l], [0], [dnl
> -1
> -])
> -echo "packet hit reroute policy"
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
> -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
> -
> -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
> -
> -OVN_CLEANUP([pbr-hv])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1 lport/LS, 1
> LR])
> -AT_KEYWORDS([policy-based-routing])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
> -# and has switch ls2 (172.16.1.0/24) connected to it.
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -ovn-nbctl ls-add ls3
> -
> -# Connect ls1 to R1
> -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
> -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
> -    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
> -
> -# Connect ls2 to R1
> -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
> -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
> -    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
> -
> -# Connect ls3 to R1
> -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
> -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
> -    type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
> -
> -# Create logical port ls1-lp1 in ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
> -
> -# Create logical port ls2-lp1 in ls2
> -ovn-nbctl lsp-add ls2 ls2-lp1 \
> --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
> -
> -# Create logical port ls3-lp1 in ls3
> -ovn-nbctl lsp-add ls3 ls3-lp1 \
> --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
> -
> -# Create one hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add pbr-hv
> -as pbr-hv
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -ovs-vsctl -- add-port br-int vif1 -- \
> -    set interface vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif2 -- \
> -    set interface vif2 external-ids:iface-id=ls2-lp1 \
> -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int vif3 -- \
> -    set interface vif3 external-ids:iface-id=ls3-lp1 \
> -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
> -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
> -    ofport-request=1
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ls1_ro_mac=00:00:00:01:02:f1
> -ls1_ro_ip=2001::1
> -
> -ls2_ro_mac=00:00:00:01:02:f2
> -ls2_ro_ip=2002::1
> -
> -ls3_ro_mac=00:00:00:01:02:f3
> -
> -ls1_p1_mac=00:00:00:01:02:03
> -ls1_p1_ip=2001::2
> -
> -ls2_p1_mac=00:00:00:01:02:04
> -ls2_p1_ip=2002::2
> -
> -ls3_p1_mac=00:00:00:01:02:05
> -
> -# Create a drop policy
> -ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 && ip6.dst==2002::/64"
> drop
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc
> -l], [0], [dnl
> -1
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Check if packet hit the drop policy
> -AT_CHECK([ovs-ofctl dump-flows br-int | \
> -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
> -    grep "priority=10" | \
> -    grep "n_packets=1" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Expected to drop the packet.
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap >
> vif2.packets
> -rcvd_packet=`cat vif2.packets`
> -AT_FAIL_IF([rcvd_packet = ""])
> -
> -# Override drop policy with allow
> -ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 && ip6.dst==2002::/64"
> allow
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc
> -l], [0], [dnl
> -2
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Check if packet hit the allow policy
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
> -    grep "2001" | \
> -    grep "priority=20" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
> -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > expected
> -
> -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
> -
> -# Override allow policy with reroute
> -ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 && ip6.dst==2002::/64"
> reroute 2003::2
> -
> -# Check logical flow
> -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
> -    grep "2001" | \
> -    grep "priority=30" | wc -l], [0], [dnl
> -1
> -])
> -
> -# Send packet.
> -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
> eth.dst==$ls1_ro_mac &&
> -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -echo "southbound flows"
> -
> -ovn-sbctl dump-flows | grep lr_in_policy
> -echo "ovs flows"
> -ovs-ofctl dump-flows br-int
> -# Check if packet hit the allow policy
> -AT_CHECK([ovs-ofctl dump-flows br-int | \
> -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
> -    grep "priority=30" | \
> -    grep "n_packets=1" | wc -l], [0], [dnl
> -1
> -])
> -echo "packet hit reroute policy"
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
> -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
> -
> -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
> -
> -OVN_CLEANUP([pbr-hv])
> -AT_CLEANUP
> -
> -# 1 hypervisor, 1 port
> -# make sure that the port state is properly set to up and back down
> -# when created and deleted.
> -AT_SETUP([ovn -- port state up and down])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl lsp-add ls1 lp1
> -ovn-nbctl lsp-set-addresses lp1 unknown
> -
> -net_add n1
> -sim_add hv1
> -as hv1 ovs-vsctl add-br br-phys
> -as hv1 ovn_attach n1 br-phys 192.168.0.1
> -
> -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
> -
> -as hv1 ovs-vsctl del-port br-int vif1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -# 1 hypervisor, 1 port
> -# make sure that the OF rules created to support a datapath are
> added/cleared
> -# when logical switch is created and removed.
> -AT_SETUP([ovn -- datapath rules added/removed])
> -AT_KEYWORDS([cleanup])
> -ovn_start
> -
> -net_add n1
> -sim_add hv1
> -as hv1 ovs-vsctl add-br br-phys
> -as hv1 ovn_attach n1 br-phys 192.168.0.1
> -
> -# This shell function checks if OF rules in br-int have clauses
> -# related to OVN datapaths. The caller determines if it should find
> -# a match in the output, or not.
> -#
> -# EXPECT_DATAPATH param determines whether flows that refer to
> -#                 datapath to should be present or not. 0 means
> -#                 they should not be.
> -# STAGE_INFO param is a simple string to help identify the stage
> -#            in the test when this function was invoked.
> -test_datapath_in_of_rules() {
> -    local expect_datapath=$1 stage_info=$2
> -    echo "------ ovn-nbctl show ${stage_info} ------"
> -    ovn-nbctl show
> -    echo "------ ovn-sbctl show ${stage_info} ------"
> -    ovn-sbctl show
> -    echo "------ OF rules ${stage_info} ------"
> -    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
> -    # if there is a datapath mentioned in the output, check for the
> -    # magic keyword that represents one, based on the exit status of
> -    # a quiet grep
> -    if test $expect_datapath != 0; then
> -       AT_CHECK([grep -q -i 'metadata=' stdout], [0], [ignore-nolog])
> -    else
> -       AT_CHECK([grep -q -i 'metadata=' stdout], [1], [ignore-nolog])
> -    fi
> -}
> -
> -test_datapath_in_of_rules 0 "before ls+port create"
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl lsp-add ls1 lp1
> -ovn-nbctl lsp-set-addresses lp1 unknown
> -
> -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
> -
> -test_datapath_in_of_rules 1 "after port is bound"
> -
> -as hv1 ovs-vsctl del-port br-int vif1
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
> -
> -ovn-nbctl lsp-set-addresses lp1
> -ovn-nbctl lsp-del lp1
> -ovn-nbctl ls-del ls1
> -
> -# wait for earlier changes to take effect
> -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
> -
> -# ensure OF rules are no longer present. There used to be a bug here.
> -test_datapath_in_of_rules 0 "after lport+ls removal"
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- nd_na ])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -#TODO: since patch port for IPv6 logical router port is not ready not,
> -#  so we are not going to test vifs on different lswitches cases. Try
> -#  to update for that once relevant stuff implemented.
> -
> -# In this test cases we create 1 lswitch, it has 2 VIF ports attached
> -# with. NS packet we test, from one VIF for another VIF, will be replied
> -# by local ovn-controller, but not by target VIF.
> -
> -# Create hypervisors and logical switch lsw0.
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
> options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
> -ovn-nbctl lsp-add lsw0 lp1
> -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3
> fd81:ce49:a948:0:f816:3eff:fe94:598"
> -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98 192.168.0.3
> fd81:ce49:a948:0:f816:3eff:fe94:598"
> -
> -# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
> -ovs-vsctl add-port br-int vif2 -- set Interface vif2
> external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap
> options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
> -ovn-nbctl lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
> fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
> -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
> fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
> -
> -# Add ACL rule for ICMPv6 on lsw0
> -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
> -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'
> allow-related
> -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'
> allow-related
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv1${1%?}
> -}
> -for i in 1 2; do
> -    : > $i.expected
> -done
> -
> -# Complete Neighbor Solicitation packet and Neighbor Advertisement packet
> -# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
> -# vif2 will not receive NS packet, since ovn-controller will reply for it.
>
> -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598
>
> -na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae
> -
> -as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
> -echo $na_packet >> 1.expected
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-ofctl -O OpenFlow13 show br-int
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -
> -for i in 1 2; do
> -    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
> -done
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- address sets modification/removal smoke test])
> -ovn_start
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
> -ovn-nbctl set Address_Set $row name=set1 addresses=\"1.1.1.1,1.1.1.2\"
> -ovn-nbctl destroy Address_Set $row
> -
> -sleep 1
> -
> -# A bug previously existed in the address set support code
> -# that caused ovn-controller to crash after an address set
> -# was updated and then removed.  This test case ensures
> -# that ovn-controller is at least still running after
> -# creating, updating, and deleting an address set.
> -AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ipam])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Add a port to a switch that does not have a subnet set, then set the
> -# subnet which should result in an address being allocated for the port.
> -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
> -ovn-nbctl ls-add sw0
> -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
> -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=
> 192.168.1.0/24
> -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl> get
> Logical-Switch-Port p0 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:03 192.168.1.2"
> -])
> -
> -# Add 9 more ports to sw0, addresses should all be unique.
> -for n in `seq 1 9`; do
> -    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses "p$n"
> dynamic
> -done
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p1 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:04 192.168.1.3"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p2 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:05 192.168.1.4"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p3 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:06 192.168.1.5"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p4 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:07 192.168.1.6"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p5 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:08 192.168.1.7"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p6 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:09 192.168.1.8"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p7 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:0a 192.168.1.9"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p8 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:0b 192.168.1.10"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p9 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:0c 192.168.1.11"
> -])
> -
> -# Trying similar tests with a second switch. MAC addresses should be
> unique
> -# across both switches but IP's only need to be unique within the same
> switch.
> -ovn-nbctl ls-add sw1
> -ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
> -ovn-nbctl --wait=sb add Logical-Switch sw1 other_config subnet=
> 192.168.1.0/24
> -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl> get
> Logical-Switch-Port p10 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:0d 192.168.1.2"
> -])
> -
> -for n in `seq 11 19`; do
> -    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses "p$n"
> dynamic
> -done
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p11 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:0e 192.168.1.3"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p12 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:0f 192.168.1.4"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p13 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:10 192.168.1.5"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p14 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:11 192.168.1.6"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p15 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:12 192.168.1.7"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p16 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:13 192.168.1.8"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p17 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:14 192.168.1.9"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p18 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:15 192.168.1.10"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p19 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:16 192.168.1.11"
> -])
> -
> -# Change a port's address to test for multiple ip's for a single address
> entry
> -# and addresses set by the user.
> -ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2
> 192.168.1.12 192.168.1.14"
> -ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p20 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:18 192.168.1.13"
> -])
> -
> -# Test for logical router port address management.
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
> -network="192.168.1.1/24" mac=\"0a:00:00:a8:01:19\" \
> --- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
> --- set Logical_Switch_Port rp-sw0 type=router options:router-port=sw0
> -ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p21 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:1a 192.168.1.15"
> -])
> -
> -# Test for address reuse after logical port is deleted.
> -ovn-nbctl lsp-del p0
> -ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p23 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:03 192.168.1.2"
> -])
> -
> -# Test for multiple addresses to one logical port.
> -ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
> -"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
> -ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p26 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:17 192.168.1.16"
> -])
> -
> -# Test for exhausting subnet address space.
> -ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config subnet=
> 172.16.1.0/30
> -ovn-nbctl <http://172.16.1.0/30-ovn-nbctl> --wait=sb lsp-add sw2 p27 --
> lsp-set-addresses p27 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p27 dynamic_addresses], [0],
> -     ["0a:00:00:10:01:03 172.16.1.2"
> -])
> -
> -ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p28 dynamic_addresses], [0],
> -     ["0a:00:00:00:00:01"
> -])
> -
> -# Test that address management does not add duplicate MAC for lsp/lrp
> peers.
> -ovn-nbctl create Logical_Router name=R2
> -ovn-nbctl ls-add sw3
> -ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
> -"0a:00:00:a8:01:18"
> -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
> -network="192.168.2.1/24" mac=\"0a:00:00:a8:01:18\" \
> --- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
> --- set Logical_Switch_Port rp-sw3 type=router options:router-port=sw3
> -ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 dynamic
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p30 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:1d 192.168.1.17"
> -])
> -
> -# Test static MAC address with dynamically allocated IP
> -ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
> -"fe:dc:ba:98:76:54 dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
> -     ["fe:dc:ba:98:76:54 192.168.1.18"
> -])
> -
> -# Update the static MAC address with dynamically allocated IP and check
> -# if the MAC address is updated in
> 'Logical_Switch_Port.dynamic_adddresses'
> -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 dynamic"
> -
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
> -     ["fe:dc:ba:98:76:55 192.168.1.18"
> -])
> -
> -ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:1e 192.168.1.18"
> -])
> -
> -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
> -     ["fe:dc:ba:98:76:56 192.168.1.18"
> -])
> -
> -
> -# Test the exclude_ips from the IPAM list
> -ovn-nbctl --wait=sb set logical_switch sw0 \
> -other_config:exclude_ips="192.168.1.19 192.168.1.21
> 192.168.1.23..192.168.1.50"
> -
> -ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
> -"dynamic"
> -# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p32 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:1e 192.168.1.20"
> -])
> -
> -ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
> -"dynamic"
> -# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p33 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:1f 192.168.1.22"
> -])
> -
> -ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
> -"dynamic"
> -# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is
> excluded.
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p34 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:34 192.168.1.51"
> -])
> -
> -# Now clear the exclude_ips list. 192.168.1.19 should be assigned.
> -ovn-nbctl --wait=sb set Logical-switch sw0
> other_config:exclude_ips="invalid"
> -ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
> -"dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p35 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:20 192.168.1.19"
> -])
> -
> -# Set invalid data in exclude_ips list. It should be ignored.
> -ovn-nbctl --wait=sb set Logical-switch sw0
> other_config:exclude_ips="182.168.1.30"
> -ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
> -"dynamic"
> -# 192.168.1.21 should be assigned as that's the next free one.
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:21 192.168.1.21"
> -])
> -
> -# Clear the dynamic addresses assignment request.
> -ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
> -         [[[]]
> -])
> -
> -# Set IPv6 prefix
> -ovn-nbctl --wait=sb set Logical-switch sw0
> other_config:ipv6_prefix="aef0::"
> -ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
> -"dynamic"
> -
> -# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6 should be
> -# - aef0::800:ff:fe00:26 (EUI64)
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p37 dynamic_addresses], [0],
> -     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
> -])
> -
> -ovn-nbctl --wait=sb ls-add sw4
> -ovn-nbctl --wait=sb set Logical-switch sw4
> other_config:ipv6_prefix="bef0::" \
> --- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
> -ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
> -"dynamic"
> -
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p38 dynamic_addresses], [0],
> -     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
> -])
> -
> -ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
> -"f0:00:00:00:10:12 dynamic"
> -
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p39 dynamic_addresses], [0],
> -     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
> -])
> -
> -# Test the case where IPv4 addresses are exhausted and IPv6 prefix is set
> -# p40 should not have an IPv4 address since the pool is exhausted
> -ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
> -"dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p40 dynamic_addresses], [0],
> -         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
> -])
> -
> -# Test dynamic changes on switch ports.
> -#
> -ovn-nbctl --wait=sb ls-add sw5
> -ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
> -"dynamic"
> -# p41 will start with nothing
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         [[[]]
> -])
> -
> -# Set a subnet. Now p41 should have an ipv4 address, too
> -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=
> 192.168.1.0/24
> -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl> get
> Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["0a:00:00:a8:01:22 192.168.1.2"
> -])
> -
> -# Clear the other_config. The IPv4 address should be gone
> -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         [[[]]
> -])
> -
> -# Set an IPv6 prefix. Now p41 should have an IPv6 address.
> -ovn-nbctl --wait=sb set Logical-Switch sw5
> other_config:ipv6_prefix="aef0::"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
> -])
> -
> -# Change the MAC address to a static one. The IPv6 address should update.
> -ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b dynamic"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
> -])
> -
> -# Change the IPv6 prefix. The IPv6 address should update.
> -ovn-nbctl --wait=sb set Logical-Switch sw5
> other_config:ipv6_prefix="bef0::"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
> -])
> -
> -# Clear the other_config. The IPv6 address should be gone
> -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         [[[]]
> -])
> -
> -# Set the subnet again. Now p41 should get the IPv4 address again.
> -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=
> 192.168.1.0/24
> -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl> get
> Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["f0:00:00:00:10:2b 192.168.1.2"
> -])
> -
> -# Add an excluded IP address that conflicts with p41. p41 should update.
> -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
> -exclude_ips="192.168.1.2"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["f0:00:00:00:10:2b 192.168.1.3"
> -])
> -
> -# Add static ip address
> -ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
> -ovn-nbctl list Logical-Switch-Port p41
> -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
> -"dynamic 192.168.1.101"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
> -         ["0a:00:00:a8:01:65 192.168.1.100"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p42 dynamic_addresses], [0],
> -         ["0a:00:00:a8:01:66 192.168.1.101"
> -])
> -
> -# define a mac address prefix
> -ovn-nbctl ls-add sw6
> -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22:33:44:55"
> -ovn-nbctl --wait=sb set Logical-Switch sw6 other_config:subnet=
> 192.168.100.0/24
> -for <http://192.168.100.0/24-for> n in $(seq 1 3); do
> -    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses "p5$n"
> dynamic
> -done
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p51 dynamic_addresses], [0],
> -    ["00:11:22:a8:64:03 192.168.100.2"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p52 dynamic_addresses], [0],
> -    ["00:11:22:a8:64:04 192.168.100.3"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p53 dynamic_addresses], [0],
> -    ["00:11:22:a8:64:05 192.168.100.4"
> -])
> -
> -# verify configuration order does not break IPAM/MACAM
> -ovn-nbctl ls-add sw7
> -for n in $(seq 1 3); do
> -    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses "p7$n"
> dynamic
> -done
> -ovn-nbctl --wait=sb set Logical-Switch sw7
> other_config:ipv6_prefix="bef0::"
> -p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 dynamic_addresses)
> -p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 dynamic_addresses)
> -p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 dynamic_addresses)
> -AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
> -AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
> -AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
> -
> -# request to assign mac only
> -#
> -ovn-nbctl ls-add sw8
> -ovn-nbctl --wait=sb set Logical-Switch sw8 other_config:mac_only=true
> -for n in $(seq 1 3); do
> -    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses "p8$n"
> dynamic
> -done
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p81 dynamic_addresses], [0],
> -    ["00:11:22:00:00:06"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p82 dynamic_addresses], [0],
> -    ["00:11:22:00:00:07"
> -])
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p83 dynamic_addresses], [0],
> -    ["00:11:22:00:00:08"
> -])
> -
> -# clear mac_prefix and check it is allocated in a random manner
> -ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
> -ovn-nbctl ls-add sw9
> -ovn-nbctl --wait=sb set Logical-Switch sw9 other_config:mac_only=true
> -ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 dynamic
> -
> -mac_prefix=$(ovn-nbctl --wait=sb get NB_Global . options:mac_prefix | tr
> -d \")
> -port_addr=$(ovn-nbctl get Logical-Switch-Port p91 dynamic_addresses | tr
> -d \")
> -AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
> -
> -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
> -ovn-nbctl ls-add sw10
> -ovn-nbctl --wait=sb set Logical-Switch sw10
> other_config:ipv6_prefix="ae01::"
> -ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101 "dynamic
> ae01::1"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p101 dynamic_addresses], [0],
> -    ["00:11:22:00:00:0a ae01::1"
> -])
> -
> -ovn-nbctl --wait=sb set Logical-Switch sw10 other_config:subnet=
> 192.168.110.0/24
> -ovn-nbctl <http://192.168.110.0/24-ovn-nbctl> --wait=sb lsp-add sw10
> p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 ae01::2"
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p102 dynamic_addresses], [0],
> -    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
> -])
> -
> -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 northd-backup
> -OVS_APP_EXIT_AND_WAIT([ovn-northd])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ipam connectivity])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl lr-add R1
> -
> -# Test for a ping using dynamically allocated addresses.
> -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
> -ovn-nbctl ls-add foo -- add Logical_Switch foo other_config subnet=
> 192.168.1.0/24
> -ovn-nbctl <http://192.168.1.0/24-ovn-nbctl> ls-add alice -- add
> Logical_Switch alice other_config subnet=192.168.2.0/24
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -          options:router-port=foo \
> -          -- lsp-set-addresses rp-foo router
> -
> -# Connect alice to R1
> -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice
> type=router \
> -          options:router-port=alice addresses=\"00:00:00:01:02:04\"
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl --wait=sb lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "dynamic"
> -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo1
> dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl --wait=sb lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "dynamic"
> -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port alice1
> dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
> -
> -# Create logical port foo2 in foo
> -ovn-nbctl --wait=sb lsp-add foo foo2 \
> --- lsp-set-addresses foo2 "dynamic"
> -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo2
> dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
> -
> -# Create a hypervisor and create OVS ports corresponding to logical ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=foo2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -ovs-vsctl -- add-port br-int hv1-vif3 -- \
> -    set interface hv1-vif3 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv1/vif3-tx.pcap \
> -    options:rxq_pcap=hv1/vif3-rx.pcap \
> -    ofport-request=3
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and foo2
> -src_mac="0a0000a80103"
> -dst_mac="0a0000a80104"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 1 3`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="0a0000a80103"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Packet to Expect at foo2
> -src_mac="0a0000a80103"
> -dst_mac="0a0000a80104"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 1 3`
>
> -expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap >
> received1.packets
> -echo $expected > expout
> -AT_CHECK([cat received1.packets], [0], [expout])
> -
> -# Packet to Expect at alice1
> -src_mac="000000010204"
> -dst_mac="0a0000a80203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap >
> received2.packets
> -echo $expected > expout
> -AT_CHECK([cat received2.packets], [0], [expout])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ovs-vswitchd restart])
> -AT_KEYWORDS([vswitchd])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -net_add n1
> -sim_add hv1
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -OVN_POPULATE_ARP
> -sleep 2
> -
> -as hv1 ovs-vsctl show
> -
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl dump-flows br-int
> -total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
> -
> -echo "Total flows before vswitchd restart = " $total_flows
> -
> -# Code taken from ovs-save utility
> -save_flows () {
> -    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
> -    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
> -            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
> -    echo "EOF" >> restore_flows.sh
> -}
> -
> -restart_vswitchd () {
> -    restore_flows=$1
> -
> -    if test $restore_flows = true; then
> -        save_flows
> -    fi
> -
> -    as hv1
> -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> -
> -    if test $restore_flows = true; then
> -        as hv1
> -        ovs-vsctl --no-wait set open_vswitch .
> other_config:flow-restore-wait="true"
> -    fi
> -
> -    as hv1
> -    start_daemon ovs-vswitchd --enable-dummy=system -vvconn
> -vofproto_dpif -vunixctl
> -    ovs-ofctl dump-flows br-int
> -
> -    if test $restore_flows = true; then
> -        sh ./restore_flows.sh
> -        echo "Flows after restore"
> -        as hv1
> -        ovs-ofctl dump-flows br-int
> -        ovs-vsctl --no-wait --if-exists remove open_vswitch .
> other_config \
> -            flow-restore-wait="true"
> -    fi
> -}
> -
> -# Save the flows, restart vswitchd and restore the flows
> -restart_vswitchd true
> -OVS_WAIT_UNTIL([
> -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
> -    echo "Total flows after vswitchd restart = "
> $total_flows_after_restart
> -    test "${total_flows}" = "${total_flows_after_restart}"
> -])
> -
> -# Restart vswitchd without restoring
> -restart_vswitchd false
> -OVS_WAIT_UNTIL([
> -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
> -    echo "Total flows after vswitchd restart = "
> $total_flows_after_restart
> -    test "${total_flows}" = "${total_flows_after_restart}"
> -])
> -
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send arp for nexthop])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Topology: Two LSs - ls1 and ls2 are connected via router r0
> -
> -# Create logical switches
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -
> -# Create  router
> -ovn-nbctl create Logical_Router name=lr0
> -
> -# Add router ls1p1 port to gateway router
> -ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
> -ovn-nbctl <http://192.168.0.1/24-ovn-nbctl> lsp-add ls1 ls1lp1 -- set
> Logical_Switch_Port ls1lp1  \
> -    type=router options:router-port=lrp-ls1lp1 \
> -    addresses='"f0:00:00:00:00:01 192.168.0.1"'
> -
> -# Add router ls2p2 port to gateway router
> -ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
> -ovn-nbctl <http://192.168.1.1/24-ovn-nbctl> lsp-add ls2 ls2lp1 -- set
> Logical_Switch_Port ls2lp1 \
> -    type=router options:router-port=lrp-ls2lp1 \
> -    addresses='"f0:00:00:00:00:02 192.168.1.1"'
> -
> -# Set default gateway (nexthop) to 192.168.1.254
> -ovn-nbctl lr-route-add lr0 "0.0.0.0/0" 192.168.1.254 lrp-ls2lp1
> -
> -# Create logical port ls1lp2 in ls1
> -ovn-nbctl lsp-add ls1 ls1lp2 \
> --- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
> -
> -# Create logical port ls2lp2 in ls2
> -ovn-nbctl lsp-add ls2 ls2lp2 \
> --- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
> -    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
> -    options:tx_pcap=hv1/ls1lp2-tx.pcap \
> -    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
> -    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
> -    options:tx_pcap=hv1/ls2lp2-tx.pcap \
> -    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
> -    ofport-request=2
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -ovn-sbctl list chassis
> -ovn-sbctl list encap
> -echo "---------------------"
> -
> -echo "------Flows dump-----"
> -as hv1
> -ovs-ofctl dump-flows
> -echo "---------------------"
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -src_mac="f00000000003"
> -dst_mac="f00000000001"
> -src_ip=`ip_to_hex 192 168 0 2`
> -dst_ip=`ip_to_hex 8 8 8 8`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -# Send IP packet destined to 8.8.8.8 from lsp1lp2
> -as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
> -
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -# ARP packet should be received with Target IP Address set to
> 192.168.1.254 and
> -# not 8.8.8.8
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ls2lp2-tx.pcap |
> trim_zeros > packets
>
> -expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe"
> -echo $expected > expout
> -AT_CHECK([cat packets], [0], [expout])
> -cat packets
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -# Create logical switch
> -ovn-nbctl ls-add ls0
> -# Create gateway router
> -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
> -# Add router port to gateway router
> -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
> -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
> -    type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
> -# Add nat-address option
> -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
> nat-addresses="f0:00:00:00:00:01 192.168.0.2"
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0
> -
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-eth0])
> -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif
> options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
> -
> -# Wait until the patch ports are created in hv1 to connect br-int to
> br-eth0
> -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
> -grep "Port patch-br-int-to-ln_port" | wc -l`])
> -
> -# Wait for packet to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros > packets
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
> -echo $expected > expout
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
> -echo $expected >> expout
> -AT_CHECK([sort packets], [0], [expout])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in
> localnet])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -# Create logical switch
> -ovn-nbctl ls-add ls0
> -# Create gateway router
> -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
> -# Add router port to gateway router
> -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
> -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
> -    type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
> -# Add nat-address option
> -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
> -# Add NAT rules
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
> -# Add load balancers
> -AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80 10.0.0.2:80,10.0.0.3:80])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
> -AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080 10.0.0.2:8080,
> 10.0.0.3:8080])
> -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl \
> -    -- add-br br-phys \
> -    -- add-br br-eth0
> -
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-eth0])
> -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif
> options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
> -
> -# Wait until the patch ports are created to connect br-int to br-eth0
> -OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
> -grep "Port patch-br-int-to-ln_port" | wc -l`])
> -
> -ovn-sbctl list port_binding lrp0-rp
> -echo "*****"
> -ovn-nbctl list logical_switch_port lrp0-rp
> -ovn-nbctl list logical_router_port lrp0
> -ovn-nbctl show
> -# Wait for packet to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros > packets
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
> -echo $expected > expout
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
> -echo $expected >> expout
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003"
> -echo $expected >> expout
> -AT_CHECK([sort packets], [0], [expout])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- delete mac bindings])
> -ovn_start
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl -- add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -# Create logical switch ls0
> -ovn-nbctl ls-add ls0
> -# Create ports lp0, lp1 in ls0
> -ovn-nbctl lsp-add ls0 lp0
> -ovn-nbctl lsp-add ls0 lp1
> -ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
> -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
> -dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" | cut -f2
> -d " "`
> -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
> logical_port=lp0 mac="mac1"
> -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
> logical_port=lp1 mac="mac2"
> -ovn-sbctl find MAC_Binding
> -# Delete port lp0 and check that its MAC_Binding is deleted.
> -ovn-nbctl lsp-del lp0
> -ovn-sbctl find MAC_Binding
> -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0 | wc
> -l` = 0])
> -# Delete logical switch ls0 and check that its MAC_Binding is deleted.
> -ovn-nbctl ls-del ls0
> -ovn-sbctl find MAC_Binding
> -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- conntrack zone allocation])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# 2 logical switches "foo" (192.168.1.0/24) and "bar" (172.16.1.0/24)
> -# connected to a router R1.
> -# foo has foo1 to act as a client.
> -# bar has bar1, bar2, bar3 to act as servers.
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -for i in foo1 bar1 bar2 bar3; do
> -    ovs-vsctl -- add-port br-int $i -- \
> -        set interface $i external-ids:iface-id=$i \
> -        options:tx_pcap=hv1/$i-tx.pcap \
> -        options:rxq_pcap=hv1/$i-rx.pcap
> -done
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port bar1, bar2 and bar3 in bar
> -for i in `seq 1 3`; do
> -    ip=`expr $i + 1`
> -    ovn-nbctl lsp-add bar bar$i \
> -    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
> -done
> -
> -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep REG13 |
> wc -l` -eq 4])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- tag allocation])
> -ovn_start
> -
> -AT_CHECK([ovn-nbctl ls-add ls0])
> -AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
> -AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
> -AT_CHECK([ovn-nbctl ls-add ls1])
> -
> -dnl When a tag is provided, no allocation is done
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
> -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
> -])
> -dnl The same 'tag' gets created in southbound database.
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c0"], [0], [3
> -])
> -
> -dnl Allocate tags and see it getting created in both NB and SB
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c1"], [0], [1
> -])
> -
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c2"], [0], [2
> -])
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c3"], [0], [4
> -])
> -
> -dnl A different parent.
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c4"], [0], [1
> -])
> -
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c5"], [0], [2
> -])
> -
> -dnl Delete a logical port and create a new one.
> -AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c6"], [0], [1
> -])
> -
> -dnl Restart northd to see that the same allocation remains.
> -as northd
> -OVS_APP_EXIT_AND_WAIT([ovn-northd])
> -start_daemon ovn-northd \
> -    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
> -    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
> -
> -dnl Create a switch to make sure that ovn-northd has run through the main
> loop.
> -AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
> -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
> -])
> -
> -dnl Create a switch port with a tag that has already been allocated.
> -dnl It should go through fine with a duplicate tag.
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
> -AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
> -])
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="c7"], [0], [2
> -])
> -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
> -])
> -
> -AT_CHECK([ovn-nbctl ls-add ls2])
> -dnl When there is no parent_name provided (for say, 'localnet'),
> 'tag_request'
> -dnl gets copied to 'tag'
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
> -AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
> -])
> -dnl The same 'tag' gets created in southbound database.
> -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
> port_binding \
> -logical_port="local0"], [0], [25
> -])
> -dnl If 'tag_request' is 0 for localnet, nothing gets written to 'tag'
> -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
> -AT_CHECK([ovn-nbctl lsp-get-tag local1])
> -dnl change the tag_request.
> -AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1
> tag_request=50])
> -AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on localnet])
> -ovn_start
> -ovn-nbctl ls-add lsw0
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -    ovs-vsctl add-br br-eth0
> -    AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-eth0])
> -done
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
> -
> -
> -# Create 3 vifs.
> -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
> -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01
> 192.168.1.1"])
> -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
> -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
> -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2 "f0:00:00:00:00:02
> 192.168.1.2"])
> -AT_CHECK([ovn-nbctl lsp-set-port-security localvif2 "f0:00:00:00:00:02"])
> -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
> -AT_CHECK([ovn-nbctl lsp-set-addresses localvif3 "f0:00:00:00:00:03
> 192.168.1.3"])
> -AT_CHECK([ovn-nbctl lsp-set-port-security localvif3 "f0:00:00:00:00:03"])
> -
> -# Bind the localvif1 to hv1.
> -as hv1
> -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1
> external_ids:iface-id=localvif1])
> -
> -# On hv1, check that there are no flows outputting bcast to tunnel
> -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip
> | grep output | wc -l` -eq 0])
> -
> -# On hv2, check that no flow outputs bcast to tunnel to hv1.
> -as hv2
> -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip
> | grep output | wc -l` -eq 0])
> -
> -# Now bind vif2 on hv2.
> -AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
> external_ids:iface-id=localvif2])
> -
> -# At this point, the broadcast flow on vif2 should be deleted.
> -# because, there is now a localnet vif bound (table=32 programming logic)
> -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip
> | grep output | wc -l` -eq 0])
> -
> -# Verify that the local net patch port exists on hv2.
> -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
> patch-br-int-to-ln_port" | wc -l` -eq 1])
> -
> -# Now bind vif3 on hv2.
> -AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface localvif3
> external_ids:iface-id=localvif3])
> -
> -# Verify that the local net patch port still exists on hv2
> -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
> patch-br-int-to-ln_port" | wc -l` -eq 1])
> -
> -# Delete localvif2
> -AT_CHECK([ovn-nbctl lsp-del localvif2])
> -
> -# Verify that the local net patch port still exists on hv2,
> -# because, localvif3 is still bound.
> -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
> patch-br-int-to-ln_port" | wc -l` -eq 1])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -
> -AT_SETUP([ovn -- ACL logging])
> -AT_KEYWORDS([ovn])
> -ovn_start
> -
> -net_add n1
> -
> -sim_add hv
> -as hv
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -for i in lp1 lp2; do
> -    ovs-vsctl -- add-port br-int $i -- \
> -        set interface $i external-ids:iface-id=$i \
> -        options:tx_pcap=hv/$i-tx.pcap \
> -        options:rxq_pcap=hv/$i-rx.pcap
> -done
> -
> -lp1_mac="f0:00:00:00:00:01"
> -lp1_ip="192.168.1.2"
> -
> -lp2_mac="f0:00:00:00:00:02"
> -lp2_ip="192.168.1.3"
> -
> -ovn-nbctl ls-add lsw0
> -ovn-nbctl --wait=sb lsp-add lsw0 lp1
> -ovn-nbctl --wait=sb lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
> -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
> -ovn-nbctl --wait=sb sync
> -
> -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
> -ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport
> 1000 'tcp.dst==81' drop
> -
> -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
> -ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 to-lport
> 1000 'tcp.dst==83' allow
> -
> -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
> -ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85' allow-related
> -
> -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
> -ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow acl-add
> lsw0 to-lport 1000 'tcp.dst==87' reject
> -
> -ovn-sbctl dump-flows
> -
> -
> -# Send packet that should be dropped without logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should be dropped with logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should be allowed without logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should be allowed with logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should allow related flows without logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should allow related flows with logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should be rejected without logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Send packet that should be rejected with logging.
> -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
> -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
> -        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
> -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log' hv/ovn-controller.log) ])
> -
> -AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed 's/.*name=/name=/'],
> [0], [dnl
> -name="drop-flow", verdict=drop, severity=alert:
> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn
> -name="allow-flow", verdict=allow, severity=info:
> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn
> -name="<unnamed>", verdict=allow, severity=info:
> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn
> -name="reject-flow", verdict=reject, severity=alert:
> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn
> -])
> -
> -OVN_CLEANUP([hv])
> -AT_CLEANUP
> -
> -
> -AT_SETUP([ovn -- ACL rate-limited logging])
> -AT_KEYWORDS([ovn])
> -ovn_start
> -
> -net_add n1
> -
> -sim_add hv
> -as hv
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -for i in lp1 lp2; do
> -    ovs-vsctl -- add-port br-int $i -- \
> -        set interface $i external-ids:iface-id=$i \
> -        options:tx_pcap=hv/$i-tx.pcap \
> -        options:rxq_pcap=hv/$i-rx.pcap
> -done
> -
> -lp1_mac="f0:00:00:00:00:01"
> -lp1_ip="192.168.1.2"
> -
> -lp2_mac="f0:00:00:00:00:02"
> -lp2_ip="192.168.1.3"
> -
> -ovn-nbctl ls-add lsw0
> -ovn-nbctl --wait=sb lsp-add lsw0 lp1
> -ovn-nbctl --wait=sb lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
> -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
> -ovn-nbctl --wait=sb sync
> -
> -
> -# Add an ACL that rate-limits logs at 10 per second.
> -ovn-nbctl meter-add http-rl1 drop 10 pktps
> -ovn-nbctl --log --severity=alert --meter=http-rl1 --name=http-acl1
> acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
> -
> -# Add an ACL that rate-limits logs at 5 per second.
> -ovn-nbctl meter-add http-rl2 drop 5 pktps
> -ovn-nbctl --log --severity=alert --meter=http-rl2 --name=http-acl2
> acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
> -
> -# Add an ACL that doesn't rate-limit logs.
> -ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0 to-lport
> 1000 'tcp.dst==82' drop
> -ovn-nbctl --wait=hv sync
> -
> -# For each ACL, send 100 packets.
> -for i in `seq 1 100`; do
> -    ovs-appctl netdev-dummy/receive lp1
> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)'
> -
> -    ovs-appctl netdev-dummy/receive lp1
> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)'
> -
> -    ovs-appctl netdev-dummy/receive lp1
> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)'
> -done
> -
> -# The rate at which packets are sent is highly system-dependent, so we
> -# can't count on precise drop counts.  To work around that, we just
> -# check that exactly 100 "http-acl3" actions were logged and that there
> -# were more "http-acl1" actions than "http-acl2" ones.
> -OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3' hv/ovn-controller.log)
> ])
> -
> -# On particularly slow or overloaded systems, the transmission rate may
> -# be lower than the configured meter rate.  To prevent false test
> -# failures, we check the duration count of the meter, and if it's
> -# greater than nine seconds, just skip the test.
> -d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep
> "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
> -
> -echo "Meter duration: $d_secs"
> -AT_SKIP_IF([test $d_secs -gt 9])
> -
> -# Print some information that may help debugging.
> -as hv ovs-appctl -t ovn-controller meter-table-list
> -as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
> -
> -n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
> -n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
> -n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
> -
> -AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
> -AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
> -
> -OVN_CLEANUP([hv])
> -AT_CLEANUP
> -
> -
> -AT_SETUP([ovn -- DSCP marking and meter check])
> -AT_KEYWORDS([ovn])
> -ovn_start
> -
> -ovn-nbctl ls-add lsw0
> -ovn-nbctl --wait=sb lsp-add lsw0 lp1
> -ovn-nbctl --wait=sb lsp-add lsw0 lp2
> -ovn-nbctl --wait=sb lsp-add lsw0 lp3
> -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
> -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
> -ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
> -ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
> -ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
> -ovn-nbctl --wait=sb sync
> -net_add n1
> -sim_add hv
> -as hv
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap
> options:rxq_pcap=vif1-rx.pcap ofport-request=1
> -ovs-vsctl add-port br-int vif2 -- set Interface vif2
> external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap
> options:rxq_pcap=vif2-rx.pcap ofport-request=2
> -
> -AT_CAPTURE_FILE([trace])
> -ovn_trace () {
> -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
> -}
> -
> -# Extracts nw_tos from the final flow from ofproto/trace output and prints
> -# it on stdout.  Prints "none" if no nw_tos was included.
> -get_final_nw_tos() {
> -    if flow=$(grep '^Final flow:' stdout); then :; else
> -       # The output didn't have a final flow.
> -       return 99
> -    fi
> -
> -    tos=$(echo "$flow" | sed -n 's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
> -    case $tos in
> -        '') echo none ;;
> -        *) echo $tos ;;
> -    esac
> -}
> -
> -# check_tos TOS
> -#
> -# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set to TOS.
> -check_tos() {
> -    # First check with ovn-trace for logical flows.
> -    echo "checking for tos $1"
> -    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
> -     echo 'output("lp2");') > expout
> -    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src ==
> f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src == 1.1.1.1 &&
> ip4.dst == 1.1.1.2'], [0], [expout])
> -
> -    # Then re-check with ofproto/trace for a physical packet.
> -    AT_CHECK([ovs-appctl ofproto/trace br-int
> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'],
> [0], [stdout-nolog])
> -    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
> -])
> -}
> -
> -# check at L2
> -AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src == f0:00:00:00:00:01
> && eth.dst == f0:00:00:00:00:02'], [0], [output("lp2");
> -])
> -AT_CHECK([ovs-appctl ofproto/trace br-int
> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'], [0],
> [stdout-nolog])
> -AT_CHECK([get_final_nw_tos], [0], [none
> -])
> -
> -# check at L3 without dscp marking
> -check_tos 0
> -
> -# Mark DSCP with a valid value
> -qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS priority=100
> action=dscp=48 match="inport\=\=\"lp1\"\ &&\ is_chassis_resident(\"lp1\")"
> direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp1-qos)
> -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
> -])
> -check_tos 48
> -
> -# check at hv without qos meter
> -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter |
> wc -l], [0], [0
> -])
> -
> -# Update the meter rate
> -ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
> -
> -# check at hv with a qos meter table
> -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
> rate=100 | wc -l], [0], [1
> -])
> -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter |
> wc -l], [0], [1
> -])
> -
> -# Update the DSCP marking
> -ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
> -check_tos 63
> -
> -# Update the meter rate
> -ovn-nbctl --wait=hv set QoS $qos_id
> bandwidth=rate=4294967295,burst=4294967295
> -
> -# check at hv with a qos meter table
> -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
> burst_size=4294967295 | wc -l], [0], [1
> -])
> -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter |
> wc -l], [0], [1
> -])
> -
> -ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\""
> direction="to-lport"
> -check_tos 63
> -
> -# Disable DSCP marking
> -ovn-nbctl --wait=hv qos-del lsw0
> -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
> -])
> -check_tos 0
> -
> -# check at hv without qos meter
> -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter |
> wc -l], [0], [0
> -])
> -
> -# check meter with chassis not resident
> -ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" &&
> is_chassis_resident("lp3")' rate=11123 burst=111230
> -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
> -])
> -
> -# check no meter table
> -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter |
> wc -l], [0], [0
> -])
> -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
> rate=11123 | wc -l], [0], [0
> -])
> -
> -OVN_CLEANUP([hv])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- read-only sb db:ptcp access])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -
> -: > .$1.db.~lock~
> -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
> -
> -# Add read-only remote to sb ovsdb-server
> -AT_CHECK(
> -  [ovsdb-tool transact ovn-sb.db \
> -     ['["OVN_Southbound",
> -       {"op": "insert",
> -        "table": "SB_Global",
> -        "row": {
> -          "connections": ["set", [["named-uuid", "xyz"]]]}},
> -       {"op": "insert",
> -        "table": "Connection",
> -        "uuid-name": "xyz",
> -        "row": {"target": "ptcp:0:127.0.0.1",
> -               "read_only": true}}]']], [0], [ignore], [ignore])
> -
> -start_daemon ovsdb-server --remote=punix:ovn-sb.sock
> --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
> -
> -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> -
> -# read-only accesses should succeed
> -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global], [0],
> [stdout], [ignore])
> -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list Connection], [0],
> [stdout], [ignore])
> -
> -# write access should fail
> -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch vxlan
> 1.2.4.8], [1], [ignore],
> -[ovn-sbctl: transaction error: {"details":"insert operation not allowed
> when database server is in read only mode","error":"not allowed"}
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- read-only sb db:pssl access])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
> -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
> -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
> -\\]"])
> -
> -: > .$1.db.~lock~
> -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
> -
> -# Add read-only remote to sb ovsdb-server
> -AT_CHECK(
> -  [ovsdb-tool transact ovn-sb.db \
> -     ['["OVN_Southbound",
> -       {"op": "insert",
> -        "table": "SB_Global",
> -        "row": {
> -          "connections": ["set", [["named-uuid", "xyz"]]]}},
> -       {"op": "insert",
> -        "table": "Connection",
> -        "uuid-name": "xyz",
> -        "row": {"target": "pssl:0:127.0.0.1",
> -               "read_only": true}}]']], [0], [ignore], [ignore])
> -
> -start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
> -
> --remote=db:OVN_Southbound,SB_Global,connections \
> -                          --private-key="$PKIDIR/testpki-privkey2.pem" \
> -                          --certificate="$PKIDIR/testpki-cert2.pem" \
> -                          --ca-cert="$PKIDIR/testpki-cacert.pem" \
> -                          ovn-sb.db
> -
> -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> -
> -# read-only accesses should succeed
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -                    list SB_Global], [0], [stdout], [ignore])
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -                    list Connection], [0], [stdout], [ignore])
> -
> -# write access should fail
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
> -[ovn-sbctl: transaction error: {"details":"insert operation not allowed
> when database server is in read only mode","error":"not allowed"}
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- nb connection/ssl commands])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
> -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
> -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
> -\\]"])
> -
> -: > .$1.db.~lock~
> -ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
> -
> -# Start nb db server using db connection/ssl entries (unpopulated
> initially)
> -start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
> -
> --remote=db:OVN_Northbound,NB_Global,connections \
> -                          --private-key=db:OVN_Northbound,SSL,private_key
> \
> -                          --certificate=db:OVN_Northbound,SSL,certificate
> \
> -                          --ca-cert=db:OVN_Northbound,SSL,ca_cert \
> -                          ovn-nb.db
> -
> -# Populate SSL configuration entries in nb db
> -AT_CHECK(
> -    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
> -                       $PKIDIR/testpki-cert.pem \
> -                       $PKIDIR/testpki-cacert.pem], [0], [stdout],
> [ignore])
> -
> -# Populate a passive SSL connection in nb db
> -AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0], [stdout],
> [ignore])
> -
> -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> -
> -# Verify SSL connetivity to nb db server
> -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          list NB_Global],
> -         [0], [stdout], [ignore])
> -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          list Connection],
> -         [0], [stdout], [ignore])
> -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          get-connection],
> -         [0], [stdout], [ignore])
> -
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- sb connection/ssl commands])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
> -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
> -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
> -\\]"])
> -
> -: > .$1.db.~lock~
> -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
> -
> -# Start sb db server using db connection/ssl entries (unpopulated
> initially)
> -start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
> -
> --remote=db:OVN_Southbound,SB_Global,connections \
> -                          --private-key=db:OVN_Southbound,SSL,private_key
> \
> -                          --certificate=db:OVN_Southbound,SSL,certificate
> \
> -                          --ca-cert=db:OVN_Southbound,SSL,ca_cert \
> -                          ovn-sb.db
> -
> -# Populate SSL configuration entries in sb db
> -AT_CHECK(
> -    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
> -                       $PKIDIR/testpki-cert.pem \
> -                       $PKIDIR/testpki-cacert.pem], [0], [stdout],
> [ignore])
> -
> -# Populate a passive SSL connection in sb db
> -AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0], [stdout],
> [ignore])
> -
> -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> -
> -# Verify SSL connetivity to sb db server
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          list SB_Global],
> -         [0], [stdout], [ignore])
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          list Connection],
> -         [0], [stdout], [ignore])
> -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
> -                    --private-key=$PKIDIR/testpki-privkey.pem \
> -                    --certificate=$PKIDIR/testpki-cert.pem \
> -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
> -          get-connection],
> -         [0], [stdout], [ignore])
> -
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- nested containers])
> -ovn_start
> -
> -# Physical network:
> -# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
> -
> -# Logical network:
> -# 3 Logical switches - "mgmt" (172.16.1.0/24), "foo" (192.168.1.0/24)
> -# and "bar" (192.168.2.0/24). They are all connected to router R1.
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl ls-add mgmt
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -
> -# Connect mgmt to R1
> -ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
> -ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt
> type=router \
> -          options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
> type=router \
> -          options:router-port=bar addresses=\"00:00:00:01:02:04\"
> -
> -# "mgmt" has VM1 and VM2 connected
> -ovn-nbctl lsp-add mgmt vm1 \
> --- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
> -
> -ovn-nbctl lsp-add mgmt vm2 \
> --- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# "foo1" and "foo2" are containers belonging to switch "foo"
> -# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as parent_port.
> -ovn-nbctl lsp-add foo foo1 vm1 1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
> -
> -ovn-nbctl lsp-add foo foo2 vm2 2 \
> --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
> -
> -# "bar1" and "bar2" are containers belonging to switch "bar"
> -# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as parent_port.
> -ovn-nbctl lsp-add bar bar1 vm1 2 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
> -
> -ovn-nbctl lsp-add bar bar2 vm2 1 \
> --- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
> -
> -# bar3 is a standalone VM belonging to switch "bar"
> -ovn-nbctl lsp-add bar bar3 \
> --- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int vm1 -- \
> -    set interface vm1 external-ids:iface-id=vm1 \
> -    options:tx_pcap=hv1/vm1-tx.pcap \
> -    options:rxq_pcap=hv1/vm1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int bar3 -- \
> -    set interface bar3 external-ids:iface-id=bar3 \
> -    options:tx_pcap=hv1/bar3-tx.pcap \
> -    options:rxq_pcap=hv1/bar3-rx.pcap \
> -    ofport-request=2
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int vm2 -- \
> -    set interface vm2 external-ids:iface-id=vm2 \
> -    options:tx_pcap=hv2/vm2-tx.pcap \
> -    options:rxq_pcap=hv2/vm2-rx.pcap \
> -    ofport-request=1
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and foo2 (same switch, different HVs and
> -# different VLAN tags).
> -src_mac="f00000010205"
> -dst_mac="f00000010206"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 1 3`
>
> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at foo2
>
> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -echo  $packet > expected
> -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
> -
> -# Send ip packets between foo1 and bar2 (different switch, different HV)
> -src_mac="f00000010205"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 3`
>
> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at bar2
> -src_mac="000000010204"
> -dst_mac="f00000010208"
>
> -packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -echo  $packet >> expected
> -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
> -
> -# Send ip packets between foo1 and bar1
> -# (different switch, loopback to same vm but different tag)
> -src_mac="f00000010205"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at bar1
> -src_mac="000000010204"
> -dst_mac="f00000010207"
>
> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -echo  $packet > expected1
> -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
> -
> -# Send ip packets between bar1 and bar3
> -# (same switch. But one is container and another is a standalone VM)
> -src_mac="f00000010207"
> -dst_mac="f00000010209"
> -src_ip=`ip_to_hex 192 168 2 2`
> -dst_ip=`ip_to_hex 192 168 2 3`
>
> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at bar3
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -echo  $packet > expected
> -OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
> -
> -# Send ip packets between foo1 and vm1.
> -(different switch, container to the VM hosting it.)
> -src_mac="f00000010205"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 2`
>
> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at vm1
> -src_mac="000000010202"
> -dst_mac="f00000010203"
>
> -packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -echo  $packet >> expected1
> -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
> -
> -# Send packets from vm1 to bar1.
> -(different switch, A hosting VM to a container inside it)
> -src_mac="f00000010203"
> -dst_mac="000000010202"
> -src_ip=`ip_to_hex 172 16 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at vm1
> -src_mac="000000010204"
> -dst_mac="f00000010207"
>
> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -echo  $packet >> expected1
> -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
> -
> -# Send broadcast packet from foo1. foo1 should not receive the same
> packet.
> -src_mac="f00000010205"
> -dst_mac="ffffffffffff"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 255 255 255 255`
>
> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
> -
> -# expected packet at VM1
> -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based routes])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and bar
> -# (192.168.2.0/24) connected to it.
> -#
> -# R2 and R3 are gateway routers.
> -# R2 has alice (172.16.1.0/24) and R3 has bob (172.16.1.0/24)
> -# connected to it. Note how both alice and bob have the same subnet
> behind it.
> -# We are trying to simulate external network via those 2 switches. In real
> -# world the switch ports of these switches will have addresses set as
> "unknown"
> -# to make them learning switches. Or those switches will be "localnet"
> ones.
> -
> -# Create three hypervisors and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=bar1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-int hv3-vif1 -- \
> -    set interface hv3-vif1 external-ids:iface-id=bob1 \
> -    options:tx_pcap=hv3/vif1-tx.pcap \
> -    options:rxq_pcap=hv3/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
> -ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add bob
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
> type=router \
> -    options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect bob to R3
> -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
> -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
> -    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Connect R3 to join
> -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
> -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
> -    type=router options:router-port=R3_join
> addresses='"00:00:04:01:02:05"'
> -
> -# Install static routes with source ip address as the policy for routing.
> -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via
> R3.
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
> -
> -# Install static routes with destination ip address as the policy for
> routing.
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -
> -ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port bar1 in bar
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
> -
> -# Create logical port bob1 in bob
> -ovn-nbctl lsp-add bob bob1 \
> --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -# Send ip packets between foo1 and bar1
> -# (East-west traffic should flow normally)
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 3`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
> -
> -# Send ip packets between bar1 and bob1
> -src_mac="f00000010204"
> -dst_mac="000001010204"
> -src_ip=`ip_to_hex 192 168 2 2`
> -dst_ip=`ip_to_hex 172 16 1 4`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
> -#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
> -
> -# Packet to expect at bar1
> -src_mac="000001010204"
> -dst_mac="f00000010204"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 192 168 2 2`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -echo $expected > expected
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -
> -# Packet to Expect at alice1
> -src_mac="000002010203"
> -dst_mac="f00000010205"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 3`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
> -echo $expected > expected
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Packet to Expect at bob1
> -src_mac="000003010203"
> -dst_mac="f00000010206"
> -src_ip=`ip_to_hex 192 168 2 2`
> -dst_ip=`ip_to_hex 172 16 1 4`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
> -echo $expected > expected
> -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4
> aef0::4"
> -
> -ovn-nbctl lsp-add ls1 ls1-lp2 \
> --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6
> 20.0.0.4"
> -
> -DNS1=`ovn-nbctl create DNS records={}`
> -DNS2=`ovn-nbctl create DNS records={}`
> -
> -ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
> -ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6 20.0.0.4"
> -ovn-nbctl set DNS $DNS2 records:vm3.ovn.org="40.0.0.4"
> -
> -ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
> -
> -net_add n1
> -sim_add hv1
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -OVN_POPULATE_ARP
> -sleep 2
> -as hv1 ovs-vsctl show
> -
> -echo "*************************"
> -ovn-sbctl list DNS
> -echo "*************************"
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -# set_dns_params host_name
> -# Sets the dns_req_data and dns_resp_data
> -set_dns_params() {
> -    local hname=$1
> -    local ttl=00000e10
> -    an_count=0001
> -    type=0001
> -    case $hname in
> -    vm1)
> -        # vm1.ovn.org
> -        query_name=03766d31036f766e036f726700
> -        # IPv4 address - 10.0.0.4
> -        expected_dns_answer=${query_name}00010001${ttl}00040a000004
> -        ;;
> -    vm2)
> -        # vm2.ovn.org
> -        query_name=03766d32036f766e036f726700
> -        # IPv4 address - 10.0.0.6
> -        expected_dns_answer=${query_name}00010001${ttl}00040a000006
> -        # IPv4 address - 20.0.0.4
> -
> expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004
> -        an_count=0002
> -        ;;
> -    vm3)
> -        # vm3.ovn.org
> -        query_name=03766d33036f766e036f726700
> -        # IPv4 address - 40.0.0.4
> -        expected_dns_answer=${query_name}00010001${ttl}000428000004
> -        ;;
> -    vm1_ipv6_only)
> -        # vm1.ovn.org
> -        query_name=03766d31036f766e036f726700
> -        # IPv6 address - aef0::4
> -        type=001c
> -
> expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004
> -        ;;
> -    vm1_ipv4_v6)
> -        # vm1.ovn.org
> -        query_name=03766d31036f766e036f726700
> -        type=00ff
> -        an_count=0002
> -        # IPv4 address - 10.0.0.4
> -        # IPv6 address - aef0::4
> -        expected_dns_answer=${query_name}00010001${ttl}00040a000004
> -
> expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
> -
> expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004
> -        ;;
> -    vm1_invalid_type)
> -        # vm1.ovn.org
> -        query_name=03766d31036f766e036f726700
> -        # IPv6 address - aef0::4
> -        type=0002
> -        ;;
> -    vm1_incomplete)
> -        # set type to none
> -        type=''
> -    esac
> -    # TTL - 3600
> -    local dns_req_header=010201200001000000000000
> -    local dns_resp_header=010281200001${an_count}00000000
> -    dns_req_data=${dns_req_header}${query_name}${type}0001
> -
> dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer}
> -}
> -
> -# This shell function sends a DNS request packet
> -# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
> -test_dns() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
> -    local dns_query_data=$7
> -    shift; shift; shift; shift; shift; shift; shift;
> -    # Packet size => IPv4 header (20) + UDP header (8) +
> -    #                DNS data (header + query)
> -    ip_len=`expr 28 + ${#dns_query_data} / 2`
> -    udp_len=`expr $ip_len - 20`
> -    ip_len=$(printf "%x" $ip_len)
> -    udp_len=$(printf "%x" $udp_len)
> -    local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
> -    request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
> -    # dns data
> -    request=${request}${dns_query_data}
> -
> -    if test $dns_reply != 0; then
> -        local dns_reply=$1
> -        ip_len=`expr 28 + ${#dns_reply} / 2`
> -        udp_len=`expr $ip_len - 20`
> -        ip_len=$(printf "%x" $ip_len)
> -        udp_len=$(printf "%x" $udp_len)
> -        local
> reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
> -
> reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
> -        echo $reply >> $inport.expected
> -    else
> -        for outport; do
> -            echo $request >> $outport.expected
> -        done
> -    fi
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
> -}
> -
> -test_dns6() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
> -    local dns_query_data=$7
> -    shift; shift; shift; shift; shift; shift; shift;
> -    # Packet size => UDP header (8) +
> -    #                DNS data (header + query)
> -    ip_len=`expr 8 + ${#dns_query_data} / 2`
> -    udp_len=$ip_len
> -    ip_len=$(printf "%x" $ip_len)
> -    udp_len=$(printf "%x" $udp_len)
> -    local
> request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
> -    request=${request}9234003500${udp_len}0000
> -    #dns data
> -    request=${request}${dns_query_data}
> -
> -    if test $dns_reply != 0; then
> -        local dns_reply=$1
> -        ip_len=`expr 8 + ${#dns_reply} / 2`
> -        udp_len=$ip_len
> -        ip_len=$(printf "%x" $ip_len)
> -        udp_len=$(printf "%x" $udp_len)
> -        local
> reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
> -        reply=${reply}0035923400${udp_len}0000${dns_reply}
> -        echo $reply >> $inport.expected
> -    else
> -        for outport; do
> -            echo $request >> $outport.expected
> -        done
> -    fi
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
> -}
> -
> -AT_CAPTURE_FILE([ofctl_monitor0.log])
> -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
> -
> -set_dns_params vm2
> -src_ip=`ip_to_hex 10 0 0 4`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=1
> -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 1.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
> -cat 1.expected | cut -c -48 > expout
> -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 1.expected | cut -c 53- > expout
> -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -set_dns_params vm1
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=1
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Clear the query name options for ls1-lp2
> -ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
> -
> -set_dns_params vm2
> -src_ip=`ip_to_hex 10 0 0 4`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=0
> -test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply
> $dns_req_data
> -
> -# NXT_RESUMEs should be 3.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
> -AT_CHECK([cat 1.packets], [0], [])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Clear the query name for ls1-lp1
> -# Since ls1 has no query names configued,
> -# ovn-northd should not add the DNS flows.
> -ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
> -
> -set_dns_params vm1
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=0
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data
> -
> -# NXT_RESUMEs should be 3 only.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -AT_CHECK([cat 2.packets], [0], [])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Test IPv6 (AAAA records) using IPv4 packet.
> -# Add back the DNS options for ls1-lp1.
> -ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
> -
> -set_dns_params vm1_ipv6_only
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=1
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 4.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
> -set_dns_params vm1_ipv4_v6
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=1
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 5.
> -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -cat 2.expected | cut -c -48 > expout
> -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 2.expected | cut -c 53- > expout
> -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Invalid type.
> -set_dns_params vm1_invalid_type
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=0
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data
> -
> -# NXT_RESUMEs should be 6.
> -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -AT_CHECK([cat 2.packets], [0], [])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Incomplete DNS packet.
> -set_dns_params vm1_incomplete
> -src_ip=`ip_to_hex 10 0 0 6`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=0
> -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data
> -
> -# NXT_RESUMEs should be 7.
> -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -AT_CHECK([cat 2.packets], [0], [])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Add one more DNS record to the ls1.
> -ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
> -
> -set_dns_params vm3
> -src_ip=`ip_to_hex 10 0 0 4`
> -dst_ip=`ip_to_hex 10 0 0 1`
> -dns_reply=1
> -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 8.
> -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
> -cat 1.expected | cut -c -48 > expout
> -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat 1.expected | cut -c 53- > expout
> -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -# Try DNS query over IPv6
> -set_dns_params vm1
> -src_ip=aef00000000000000000000000000004
> -dst_ip=aef00000000000000000000000000001
> -dns_reply=1
> -test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
> $dns_req_data $dns_resp_data
> -
> -# NXT_RESUMEs should be 9.
> -OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
> -# Skipping the UDP checksum.
> -cat 1.expected | cut -c 1-120,125- > expout
> -AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
> -
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -rm -f 1.expected
> -rm -f 2.expected
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA distributed router
> gateway port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add gw1
> -as gw1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -sim_add gw2
> -as gw2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.4
> -
> -sim_add ext1
> -as ext1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-int ext1-vif1 -- \
> -    set interface ext1-vif1 external-ids:iface-id=outside1 \
> -    options:tx_pcap=ext1/vif1-tx.pcap \
> -    options:rxq_pcap=ext1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -# 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
> -
> -ovn-nbctl create Logical_Router name=R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add outside
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect alice to R1 as distributed router gateway port on gw1
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
> -
> -ovn-nbctl \
> -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
> -                                     chassis_name=gw1 \
> -                                     priority=20 -- \
> -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
> -                                     chassis_name=gw2 \
> -                                     priority=10 -- \
> -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
> -
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port outside1 in outside
> -ovn-nbctl lsp-add outside outside1 \
> --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# Create localnet port in alice
> -ovn-nbctl lsp-add alice ln-alice
> -ovn-nbctl lsp-set-addresses ln-alice unknown
> -ovn-nbctl lsp-set-type ln-alice localnet
> -ovn-nbctl lsp-set-options ln-alice network_name=phys
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
> -# mapping to the external network, is the one generating packets
> -as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 2
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -test_ip_packet()
> -{
> -    local active_gw=$1
> -    local backup_gw=$2
> -    local backup_vswitchd_dead=$3
> -
> -    # Send ip packet between foo1 and outside1
> -    src_mac="f00000010203" # foo1 mac
> -    dst_mac="000001010203" # rp-foo mac (internal router leg)
> -    src_ip=`ip_to_hex 192 168 1 2`
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -    # ARP request packet to expect at outside1
> -
> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -    # Send ARP reply from outside1 back to the router
> -    # XXX: note, we could avoid this if we plug this port into a netns
> -    # and setup the IP address into the port, so the kernel would simply
> reply
> -    src_mac="000002010203"
> -    reply_mac="f00000010204"
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -    src_ip=`ip_to_hex 172 16 1 1`
> -
> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
> -
> -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
> -
> -    OVS_WAIT_UNTIL([
> -        test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 |
> \
> -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
> -    ])
> -
> -    # Packet to Expect at ext1 chassis, outside1 port
> -    src_mac="000002010203"
> -    dst_mac="f00000010204"
> -    src_ip=`ip_to_hex 192 168 1 2`
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -
> expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -    echo $expected > ext1-vif1.expected
> -
> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
> -    echo $exp_gw_ip_garp >> ext1-vif1.expected
> -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
> -
> -    if test $backup_vswitchd_dead != 1; then
> -        # Reset the file only if vswitchd in backup gw is alive
> -        as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
> -    fi
> -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
> -
> -    # Resend packet from foo1 to outside1
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -    sleep 1
> -
> -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
> -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> $active_gw/br-phys_n1-tx.pcap  > packets
> -    cat packets | grep $expected > exp
> -    # Its possible that $active_gw/br-phys_n1-tx.pcap may have received
> multiple
> -    # garp packets. So consider only the first packet.
> -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
> -    AT_CHECK([cat exp], [0], [expout])
> -    rm -f expout
> -    if test $backup_vswitchd_dead != 1; then
> -        # Check for backup gw only if vswitchd is alive
> -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> $backup_gw/br-phys_n1-tx.pcap  > packets
> -        AT_CHECK([grep $expected packets | sort], [0], [])
> -    fi
> -}
> -
> -test_ip_packet gw1 gw2 0
> -
> -ovn-nbctl --timeout=3 --wait=hv \
> -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
> -                                     chassis_name=gw1 \
> -                                     priority=10 -- \
> -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
> -                                     chassis_name=gw2 \
> -                                     priority=20 -- \
> -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
> -
> -test_ip_packet gw2 gw1 0
> -
> -# Get the claim count of both gw1 and gw2.
> -gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log | wc -l`
> -gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log | wc -l`
> -
> -# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
> -as gw2
> -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
> -
> -# gw1 should claim the cr-alice and the claim count of gw1 should be
> -# incremented by 1.
> -gw1_claim_ct=$((gw1_claim_ct+1))
> -
> -OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
> -| grep -c "cr-alice: Claiming"`])
> -
> -AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
> -grep -c "cr-alice: Claiming"`])
> -
> -test_ip_packet gw1 gw2 1
> -
> -as gw2
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> -
> -OVN_CLEANUP([hv1],[gw1],[ext1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA distributed router
> gateway port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add gw1
> -as gw1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -sim_add gw2
> -as gw2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.4
> -
> -sim_add ext1
> -as ext1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-int ext1-vif1 -- \
> -    set interface ext1-vif1 external-ids:iface-id=outside1 \
> -    options:tx_pcap=ext1/vif1-tx.pcap \
> -    options:rxq_pcap=ext1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -# 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
> -
> -ovn-nbctl create Logical_Router name=R0
> -ovn-nbctl create Logical_Router name=R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add join
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add outside
> -
> -#Connect foo to R0
> -ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
> -    type=router options:router-port=R0-foo \
> -    -- lsp-set-addresses foo-R0 router
> -
> -#Connect R0 to join
> -ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
> -ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port join-R0 \
> -    type=router options:router-port=R0-join \
> -    -- lsp-set-addresses join-R0 router
> -
> -#Connect join to R1
> -ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
> -ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port join-R1 \
> -    type=router options:router-port=R1-join \
> -    -- lsp-set-addresses join-R1 router
> -
> -#add route rules
> -ovn-nbctl lr-route-add R0 0.0.0.0/0 100.60.1.2
> -ovn-nbctl lr-route-add R1 192.168.0.0/16 100.60.1.1
> -
> -# Connect alice to R1 as distributed router gateway port on gw1
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
> -
> -ovn-nbctl \
> -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
> -                                     chassis_name=gw1 \
> -                                     priority=20 -- \
> -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
> -                                     chassis_name=gw2 \
> -                                     priority=10 -- \
> -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
> -
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port outside1 in outside
> -ovn-nbctl lsp-add outside outside1 \
> --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# Create localnet port in alice
> -ovn-nbctl lsp-add alice ln-alice
> -ovn-nbctl lsp-set-addresses ln-alice unknown
> -ovn-nbctl lsp-set-type ln-alice localnet
> -ovn-nbctl lsp-set-options ln-alice network_name=phys
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
> -# mapping to the external network, is the one generating packets
> -as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
> -
> -# hv1 should be in 'ref_chassis' of the ha_chasssi_group as logical
> -# switch 'foo' can reach the router 'R1' (which has gw router port)
> -# via foo1 -> foo -> R0 -> join -> R1
> -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$hv1_ch_uuid" = "$ref_ch_list"])
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 2
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -test_ip_packet()
> -{
> -    local active_gw=$1
> -    local backup_gw=$2
> -
> -    # Send ip packet between foo1 and outside1
> -    src_mac="f00000010203" # foo1 mac
> -    dst_mac="000001010203" # foo-R0 mac (internal router leg)
> -    src_ip=`ip_to_hex 192 168 1 2`
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -    # ARP request packet to expect at outside1
> -
> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -    # Send ARP reply from outside1 back to the router
> -    # XXX: note, we could avoid this if we plug this port into a netns
> -    # and setup the IP address into the port, so the kernel would simply
> reply
> -    src_mac="000002010203"
> -    reply_mac="f00000010204"
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -    src_ip=`ip_to_hex 172 16 1 1`
> -
> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
> -
> -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
> -
> -    OVS_WAIT_UNTIL([
> -        test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 |
> \
> -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
> -    ])
> -
> -    # Packet to Expect at ext1 chassis, outside1 port
> -    src_mac="000002010203"
> -    dst_mac="f00000010204"
> -    src_ip=`ip_to_hex 192 168 1 2`
> -    dst_ip=`ip_to_hex 172 16 1 3`
> -
> expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
> -    echo $expected > ext1-vif1.expected
> -
> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
> -    echo $exp_gw_ip_garp >> ext1-vif1.expected
> -
> -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
> -    as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
> -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
> -
> -    # Resend packet from foo1 to outside1
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
> -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> $active_gw/br-phys_n1-tx.pcap  > packets
> -    cat packets | grep $expected > exp
> -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
> -    AT_CHECK([cat exp], [0], [expout])
> -
> -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> $backup_gw/br-phys_n1-tx.pcap  > packets
> -    AT_CHECK([grep $expected packets | sort], [0], [])
> -}
> -
> -test_ip_packet gw1 gw2
> -
> -ovn-nbctl --timeout=3 --wait=hv \
> -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
> -                                     chassis_name=gw1 \
> -                                     priority=10 -- \
> -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
> -                                     chassis_name=gw2 \
> -                                     priority=20 -- \
> -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
> -
> -test_ip_packet gw2 gw1
> -
> -OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 1 LR with distributed router gateway port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR R1 that has switches foo (192.168.1.0/24) and
> -# alice (172.16.1.0/24) connected to it.  The logical port
> -# between R1 and alice has a "redirect-chassis" specified,
> -# i.e. it is the distributed router gateway port.
> -# Switch alice also has a localnet port defined.
> -# An additional switch outside has a localnet port and the
> -# same subnet as alice (172.16.1.0/24).
> -
> -# Physical network:
> -# Three hypervisors hv[123].
> -# hv1 hosts vif foo1.
> -# hv2 is the "redirect-chassis" that hosts the distributed
> -# router gateway port.
> -# hv3 hosts vif outside1.
> -# In order to show that connectivity works only through hv2,
> -# an initial round of tests is run without any bridge-mapping
> -# defined for the localnet on hv2.  These tests are expected
> -# to fail.
> -# Subsequent tests are run after defining the bridge-mapping
> -# for the localnet on hv2. These tests are expected to succeed.
> -
> -# Create three hypervisors and create OVS ports corresponding
> -# to logical ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-int hv3-vif1 -- \
> -    set interface hv3-vif1 external-ids:iface-id=outside1 \
> -    options:tx_pcap=hv3/vif1-tx.pcap \
> -    options:rxq_pcap=hv3/vif1-rx.pcap \
> -    ofport-request=1
> -
> -# 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
> -
> -ovn-nbctl create Logical_Router name=R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add outside
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect alice to R1 as distributed router gateway port on hv2
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port outside1 in outside
> -ovn-nbctl lsp-add outside outside1 \
> --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# Create localnet port in alice
> -ovn-nbctl lsp-add alice ln-alice
> -ovn-nbctl lsp-set-addresses ln-alice unknown
> -ovn-nbctl lsp-set-type ln-alice localnet
> -ovn-nbctl lsp-set-options ln-alice network_name=phys
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
> -as hv1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -as hv3 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 2
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -ovn-sbctl list chassis
> -ovn-sbctl list encap
> -echo "------ Gateway_Chassis dump (SBDB) -------"
> -ovn-sbctl list Gateway_Chassis
> -echo "------ Port_Binding chassisredirect -------"
> -ovn-sbctl find Port_Binding type=chassisredirect
> -echo "-------------------------------------------"
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -echo "------ hv3 dump ----------"
> -as hv3 ovs-ofctl show br-int
> -as hv3 ovs-ofctl dump-flows br-int
> -echo "--------------------------"
> -
> -
> -# Check that redirect mapping is programmed only on hv2
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep
> =0x3,metadata=0x1 | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep
> =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
> -])
> -# Check that hv1 sends chassisredirect port traffic to hv2
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep
> =0x3,metadata=0x1 | grep output | wc -l], [0], [1
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep
> =0x3,metadata=0x1 | wc -l], [0], [0
> -])
> -# Check that arp reply on distributed gateway port is only programmed on
> hv2
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2-
> | grep =0x2,metadata=0x1 | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2-
> | grep =0x2,metadata=0x1 | wc -l], [0], [1
> -])
> -
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -
> -: > hv2-vif1.expected
> -: > hv3-vif1.expected
> -
> -# test_arp INPORT SHA SPA TPA [REPLY_HA]
> -#
> -# Causes a packet to be received on INPORT.  The packet is an ARP
> -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided,
> then
> -# it should be the hardware address of the target to expect to receive in
> an
> -# ARP reply; otherwise no reply is expected.
> -#
> -# INPORT is an logical switch port number, e.g. 11 for vif11.
> -# SHA and REPLY_HA are each 12 hex digits.
> -# SPA and TPA are each 8 hex digits.
> -test_arp() {
> -    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
> -    local
> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
> -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
> -
> -    if test X$reply_ha != X; then
> -        # Expect to receive the reply, if any.
> -        local
> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
> -        echo $reply >> hv${hv}-vif$inport.expected
> -    fi
> -}
> -
> -rtr_ip=$(ip_to_hex 172 16 1 1)
> -foo_ip=$(ip_to_hex 192 168 1 2)
> -outside_ip=$(ip_to_hex 172 16 1 3)
> -
> -echo $rtr_ip
> -echo $foo_ip
> -echo $outside_ip
> -
> -# ARP for router IP address from outside1, no response expected
> -test_arp 3 1 f00000010204 $outside_ip $rtr_ip
> -
> -# Now check the packets actually received against the ones expected.
> -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
> -
> -# Send ip packet between foo1 and outside1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 3`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -# Now check the packets actually received against the ones expected.
> -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
> -
> -# Now add bridge-mappings on hv2, which should make everything work
> -as hv2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -# Wait until the patch ports are created in hv2 to connect br-int to
> br-phys
> -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
> -grep "Port patch-br-int-to-ln-alice" | wc -l`])
> -
> -# ARP for router IP address from outside1
> -test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
> -
> -# hv3-vif1.expected should also have the gw router port garp packet.
>
> -exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
> -echo $exp_gw_ip_garp >> hv3-vif1.expected
> -
> -# Now check the packets actually received against the ones expected.
> -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
> -
> -# Send ip packet between foo1 and outside1
> -src_mac="f00000010203"
> -dst_mac="000001010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 172 16 1 3`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -# Packet to Expect at outside1
> -src_mac="000002010203"
> -dst_mac="f00000010204"
>
> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -echo "------ hv1 dump ----------"
> -as hv1 ovs-ofctl show br-int
> -as hv1 ovs-ofctl dump-flows br-int
> -echo "------ hv2 dump ----------"
> -as hv2 ovs-ofctl show br-int
> -as hv2 ovs-ofctl dump-flows br-int
> -echo "------ hv3 dump ----------"
> -as hv3 ovs-ofctl show br-int
> -as hv3 ovs-ofctl dump-flows br-int
> -echo "----------------------------"
> -
> -echo $expected >> hv3-vif1.expected
> -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
> -
> -#Check ovn-trace over "chassisredirect" port
> -AT_CAPTURE_FILE([trace])
> -ovn_trace () {
> -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
> -}
> -
> -echo 'ip.ttl--;' > expout
> -echo 'eth.src = 00:00:02:01:02:03;' >> expout
> -echo 'eth.dst = f0:00:00:01:02:04;' >> expout
> -echo 'output("ln-alice");' >> expout
> -AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src ==
> f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src == 192.168.1.2
> && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0], [expout])
> -
> -# Create logical port alice1 in alice on hv1
> -as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=1
> -
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
> -
> -# Create logical port foo2 in foo on hv2
> -as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=foo2 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovn-nbctl lsp-add foo foo2 \
> --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -: > hv1-vif2.expected
> -
> -# Send ip packet between alice1 and foo2
> -src_mac="f00000010205"
> -dst_mac="000002010203"
> -src_ip=`ip_to_hex 172 16 1 4`
> -dst_ip=`ip_to_hex 192 168 1 3`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
> -
> -# Packet to Expect at foo2
> -src_mac="000001010203"
> -dst_mac="f00000010206"
> -src_ip=`ip_to_hex 172 16 1 4`
> -dst_ip=`ip_to_hex 192 168 1 3`
>
> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
> -
> -echo $expected >> hv2-vif1.expected
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
> -
> -AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding
> logical_port=cr-alice | wc -l], [0], [1
> -])
> -
> -ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice options
> redirect-chassis
> -
> -AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc -l],
> [0], [0
> -])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed router])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -# Create logical switches
> -ovn-nbctl ls-add ls0
> -ovn-nbctl ls-add ls1
> -# Create distributed router
> -ovn-nbctl create Logical_Router name=lr0
> -# Add distributed gateway port to distributed router
> -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24 \
> -    -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
> -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
> -    type=router options:router-port=lrp0 addresses="router"
> -# Add router port to ls1
> -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
> -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
> -    type=router options:router-port=lrp1 addresses="router"
> -# Add logical ports for NAT rules
> -ovn-nbctl lsp-add ls1 foo1 \
> --- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
> -ovn-nbctl lsp-add ls1 foo2 \
> --- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
> -# Add nat-addresses option
> -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
> -# Add NAT rules
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3 10.0.0.3
> foo1 f0:00:00:00:00:03])
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4 10.0.0.4
> foo2 f0:00:00:00:00:04])
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif
> options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -# Initially test with no bridge-mapping on hv2, expect to receive no
> packets
> -
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -# Initially test with no bridge-mapping on hv3
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port
> network_name=physnet1])
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 2
> -
> -# Expect no packets when hv2 bridge-mapping is not present
> -: > packets
> -OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
> -
> -# Add bridge-mapping on hv2
> -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -
> -# Wait until the patch ports are created in hv2 to connect br-int to
> br-phys
> -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
> -grep "Port patch-br-int-to-ln_port" | wc -l`])
> -
> -# Wait for packets to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros > packets
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
> -echo $expected > expout
>
> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
> -echo $expected >> expout
> -AT_CHECK([sort packets], [0], [expout])
> -sort packets | cat
> -
> -# Temporarily remove nat-addresses option to avoid race conditions
> -# due to GARP backoff
> -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses=""
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -as hv1 reset_pcap_file snoopvif hv1/snoopvif
> -
> -# Add OVS ports for foo1 and foo2 on hv3
> -ovs-vsctl -- add-port br-int hv3-vif1 -- \
> -    set interface hv3-vif1 external-ids:iface-id=foo1 \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv3-vif2 -- \
> -    set interface hv3-vif2 external-ids:iface-id=foo2 \
> -    ofport-request=2
> -
> -# Add bridge-mapping on hv3
> -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -
> -# Wait until the patch ports are created in hv3 to connect br-int to
> br-phys
> -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
> -grep "Port patch-br-int-to-ln_port" | wc -l`])
> -
> -# Re-add nat-addresses option
> -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
> -
> -# Wait for packets to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros > packets
>
> -garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
> -echo $garp_1 > expout
>
> -garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
> -echo $garp_2 >> expout
> -
> -cat packets | grep $garp_1 | head -1 > exp
> -cat packets | grep $garp_2 | head -1 >> exp
> -AT_CHECK([cat exp], [0], [expout])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -# VLAN traffic for external network redirected through distributed router
> -# gateway port should use vlans(i.e input network vlan tag) across
> hypervisors
> -# instead of tunneling.
> -AT_SETUP([ovn -- vlan traffic for external network with distributed
> router gateway port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# # One LR R1 that has switches foo (192.168.1.0/24) and
> -# # alice (172.16.1.0/24) connected to it.  The logical port
> -# # between R1 and alice has a "redirect-chassis" specified,
> -# # i.e. it is the distributed router gateway port(172.16.1.6).
> -# # Switch alice also has a localnet port defined.
> -# # An additional switch outside has the same subnet as alice
> -# # (172.16.1.0/24), a localnet port and nexthop port(172.16.1.1)
> -# # which will receive the packet destined for external network
> -# # (i.e 8.8.8.8 as destination ip).
> -
> -# Physical network:
> -# # Four hypervisors hv[1234].
> -# # hv1 hosts vif foo1.
> -# # hv2 is the "redirect-chassis" that hosts the distributed router
> gateway port.
> -# # Later to test GARPs for the router port - foo, hv2 and hv4 are added
> to the ha_chassis_group
> -# # hv3 hosts nexthop port vif outside1.
> -# # All other tests connect hypervisors to network n1 through br-phys for
> tunneling.
> -# # But in this test, hv1 won't connect to n1(and no br-phys in hv1), and
> -# # in order to show vlans(instead of tunneling) used between hv1 and hv2,
> -# # a new network n2 created and hv1 and hv2 connected to this network
> through br-ex.
> -# # hv2 and hv3 are still connected to n1 network through br-phys.
> -net_add n1
> -
> -# We are not calling ovn_attach for hv1, to avoid adding br-phys.
> -# Tunneling won't work in hv1 as ovn-encap-ip is not added to any bridge
> in hv1
> -sim_add hv1
> -as hv1
> -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,vxlan \
> -    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
> -    -- add-br br-int \
> -    -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true \
> -    -- set Open_vSwitch . external-ids:ovn-bridge-mappings=public:br-ex
> -
> -start_daemon ovn-controller
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
> -
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-int hv3-vif1 -- \
> -    set interface hv3-vif1 external-ids:iface-id=outside1 \
> -    options:tx_pcap=hv3/vif1-tx.pcap \
> -    options:rxq_pcap=hv3/vif1-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings="phys:br-phys"
> -
> -sim_add hv4
> -as hv4
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.4
> -ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
> -
> -# Create network n2 for vlan connectivity between hv1 and hv2
> -net_add n2
> -
> -as hv1
> -ovs-vsctl add-br br-ex
> -net_attach n2 br-ex
> -
> -as hv2
> -ovs-vsctl add-br br-ex
> -net_attach n2 br-ex
> -
> -as hv4
> -ovs-vsctl add-br br-ex
> -net_attach n2 br-ex
> -
> -OVN_POPULATE_ARP
> -
> -ovn-nbctl create Logical_Router name=R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add outside
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect alice to R1 as distributed router gateway port (172.16.1.6) on
> hv2
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24 \
> -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router \
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port outside1 in outside, which is a nexthop address
> -# for 172.16.1.0/24
> -ovn-nbctl lsp-add outside outside1 \
> --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
> -
> -# Set default gateway (nexthop) to 172.16.1.1
> -ovn-nbctl lr-route-add R1 "0.0.0.0/0" 172.16.1.1 alice
> -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24])
> -ovn-nbctl set Logical_Switch_Port rp-alice options:nat-addresses=router
> -
> -ovn-nbctl lsp-add foo ln-foo
> -ovn-nbctl lsp-set-addresses ln-foo unknown
> -ovn-nbctl lsp-set-options ln-foo network_name=public
> -ovn-nbctl lsp-set-type ln-foo localnet
> -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
> -
> -# Create localnet port in alice
> -ovn-nbctl lsp-add alice ln-alice
> -ovn-nbctl lsp-set-addresses ln-alice unknown
> -ovn-nbctl lsp-set-type ln-alice localnet
> -ovn-nbctl lsp-set-options ln-alice network_name=phys
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -# Check that there is a logical flow in logical switch foo's pipeline
> -# to set the outport to rp-foo (which is expected).
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup |
> \
> -grep rp-foo | grep -v is_chassis_resident | wc -l`])
> -
> -# Set the option 'reside-on-redirect-chassis' for foo
> -ovn-nbctl set logical_router_port foo
> options:reside-on-redirect-chassis=true
> -# Check that there is a logical flow in logical switch foo's pipeline
> -# to set the outport to rp-foo with the condition is_chassis_redirect.
> -ovn-sbctl dump-flows foo
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup |
> \
> -grep rp-foo | grep is_chassis_resident | wc -l`])
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list nat
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -ovn-sbctl list chassis
> -echo "---------------------"
> -
> -for chassis in hv1 hv2 hv3; do
> -    as $chassis
> -    echo "------ $chassis dump ----------"
> -    ovs-vsctl show br-int
> -    ovs-ofctl show br-int
> -    ovs-ofctl dump-flows br-int
> -    echo "--------------------------"
> -done
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -foo1_ip=$(ip_to_hex 192 168 1 2)
> -gw_ip=$(ip_to_hex 172 16 1 6)
> -dst_ip=$(ip_to_hex 8 8 8 8)
> -nexthop_ip=$(ip_to_hex 172 16 1 1)
> -
> -foo1_mac="f00000010203"
> -foo_mac="000001010203"
> -gw_mac="000002010203"
> -nexthop_mac="f00000010204"
> -
> -# Send ip packet from foo1 to 8.8.8.8
> -src_mac="f00000010203"
> -dst_mac="000001010203"
>
> -packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
> -
> -# Wait for GARPs announcing gw IP to arrive
> -OVS_WAIT_UNTIL([
> -    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
> -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
> -    ])
> -
> -# VLAN tagged packet with router port(192.168.1.1) MAC as destination MAC
> -# is expected on bridge connecting hv1 and hv2
>
> -expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
> -echo $expected > hv1-br-ex_n2.expected
> -
> -# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
> -# As connection tracking not enabled for this test, snat can't be done on
> the packet.
> -# We still see foo1 as the source ip address. But source mac(gateway MAC)
> and
> -# dest mac(nexthop mac) are properly configured.
>
> -expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000
> -echo $expected > hv3-vif1.expected
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
> -as hv3 reset_pcap_file hv3-vif1 hv3/vif1
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -sleep 2
> -
> -# On hv1, table 32 check that no packet goes via the tunnel port
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
> -| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
> -]])
> -
> -ip_packet() {
> -    grep "1010203f00000010203"
> -}
> -
> -# Check vlan tagged packet on the bridge connecting hv1 and hv2 with the
> -# foo1's mac.
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-ex_n2-tx.pcap |
> ip_packet | uniq > hv1-br-ex_n2
> -cat hv1-br-ex_n2.expected > expout
> -AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
> -
> -# Check expected packet on nexthop interface
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/vif1-tx.pcap | grep
> ${foo1_ip}${dst_ip} | uniq > hv3-vif1
> -cat hv3-vif1.expected > expout
> -AT_CHECK([sort hv3-vif1], [0], [expout])
> -
> -# Test the GARP for the router port ip - 192.168.1.1
> -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
> -
> -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
> -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
> -
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
> -
> -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group
> name=hagrp1`
> -ovn-nbctl remove logical_router_port alice options redirect-chassis
> -ovn-nbctl --wait=sb set logical_router_port alice
> ha_chassis_group=$hagrp1_uuid
> -
> -# When hv2 claims the gw router port cr-alice, it should send out
> -# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
> -
> -# foo1 (on hv1) should receive GARP without VLAN tag
>
> -exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101"
> -echo $exp_garp_on_foo1 > foo1.expout
> -
> -# ovn-controller on hv2 should send garp with VLAN tag
>
> -sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101"
> -
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
> -# Wait until we receive atleast 1 packet
> -OVS_WAIT_UNTIL([test 1=`$PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> hv2/br-ex_n2-tx.pcap | wc -l`])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-ex_n2-tx.pcap | head
> -1 > packets
> -echo $sent_garp > expout
> -AT_CHECK([cat packets], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv4/br-ex_n2-tx.pcap > empty
> -AT_CHECK([cat empty], [0], [])
> -
> -# Make hv4 master
> -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
> -
> -# Wait till cr-alice is claimed by hv4
> -hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=hv4)
> -# check that the chassis redirect port has been claimed by the gw1 chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
> -]])
> -
> -# Reset the pcap file for hv2/br-ex_n2. From now on ovn-controller in hv2
> -# should not send GARPs for the router ports.
> -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
> -
> -echo $sent_garp > br-ex_n2.expout
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
> -OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
> -
> -sleep 2
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-ex_n2-tx.pcap > empty
> -AT_CHECK([cat empty], [0], [])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
> -AT_KEYWORDS([ovn-nd_ra])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# In this test case we create 1 lswitch with 3 VIF ports attached,
> -# and a lrouter connected to the lswitch.
> -# We generate the Router solicitation packet and verify the Router
> Advertisement
> -# reply packet from the ovn-controller.
> -
> -# Create hypervisor and logical switch lsw0, logical router lr0, attach
> lsw0
> -# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode column to
> -# 'slaac' to allow lrp0 send RA for SLAAC mode.
> -ovn-nbctl ls-add lsw0
> -ovn-nbctl lr-add lr0
> -ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
> -ovn-nbctl set Logical_Router_Port lrp0
> ipv6_ra_configs:address_mode="slaac"
> -ovn-nbctl \
> -    -- lsp-add lsw0 lsp0 \
> -    -- set Logical_Switch_Port lsp0 type=router \
> -                     options:router-port=lrp0 \
> -                     addresses='"fa:16:3e:00:00:01 fdad:1234:5678::1"'
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -ovn-nbctl lsp-add lsw0 lp1
> -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
> fdad:1234:5678:0:f816:3eff:fe:2"
> -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
> fdad:1234:5678:0:f816:3eff:fe:2"
> -
> -ovn-nbctl lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
> fdad:1234:5678:0:f816:3eff:fe:3"
> -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
> fdad:1234:5678:0:f816:3eff:fe:3"
> -
> -ovn-nbctl lsp-add lsw0 lp3
> -ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
> fdad:1234:5678:0:f816:3eff:fe:4"
> -ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
> fdad:1234:5678:0:f816:3eff:fe:4"
> -
> -# Add ACL rule for ICMPv6 on lsw0
> -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
> -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'
> allow-related
> -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'
> allow-related
> -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 && icmp6'
> allow-related
> -
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -ovs-vsctl -- add-port br-int hv1-vif3 -- \
> -    set interface hv1-vif3 external-ids:iface-id=lp3 \
> -    options:tx_pcap=hv1/vif3-tx.pcap \
> -    options:rxq_pcap=hv1/vif3-rx.pcap \
> -    ofport-request=3
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -# Make sure that ovn-controller has installed the corresponding OF Flow.
> -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c
> "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
> -
> -# This shell function sends a Router Solicitation packet.
> -# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
> -test_ipv6_ra() {
> -    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
> prefix_opt=$6
> -    local
> request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac}
> -
> -    local len=24
> -    local mtu_opt=""
> -    if test $mtu != 0; then
> -        len=`expr $len + 8`
> -        mtu_opt=05010000${mtu}
> -    fi
> -
> -    if test ${#prefix_opt} != 0; then
> -        prefix_opt=${prefix_opt}fdad1234567800000000000000000000
> -        len=`expr $len + ${#prefix_opt} / 2`
> -    fi
> -
> -    len=$(printf "%x" $len)
> -    local lrp_mac=fa163e000001
> -    local lrp_lla=fe80000000000000f8163efffe000001
> -    local
> reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt}
> -    echo $reply >> $inport.expected
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
> -}
> -
> -AT_CAPTURE_FILE([ofctl_monitor0.log])
> -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
> -
> -# MTU is not set and the address mode is set to slaac
> -addr_mode=00
> -default_prefix_option_config=030440c0ffffffffffffffff00000000
> -src_mac=fa163e000002
> -src_lla=fe80000000000000f8163efffe000002
> -test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
> $default_prefix_option_config
> -
> -# NXT_RESUME should be 1.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
> -
> -cat 1.expected | cut -c -112 > expout
> -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum.
> -cat 1.expected | cut -c 117- > expout
> -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
> -
> -rm -f *.expected
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -reset_pcap_file hv1-vif3 hv1/vif3
> -
> -# Set the MTU to 1500
> -ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500
> -
> -# Make sure that ovn-controller has installed the corresponding OF Flow.
> -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c
> "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
> -
> -addr_mode=00
> -default_prefix_option_config=030440c0ffffffffffffffff00000000
> -src_mac=fa163e000003
> -src_lla=fe80000000000000f8163efffe000003
> -mtu=000005dc
> -
> -test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
> $default_prefix_option_config
> -
> -# NXT_RESUME should be 2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap  > 2.packets
> -
> -cat 2.expected | cut -c -112 > expout
> -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum.
> -cat 2.expected | cut -c 117- > expout
> -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
> -
> -rm -f *.expected
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -reset_pcap_file hv1-vif3 hv1/vif3
> -
> -# Set the address mode to dhcpv6_stateful
> -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
> ipv6_ra_configs:address_mode=dhcpv6_stateful
> -# Make sure that ovn-controller has installed the corresponding OF Flow.
> -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c
> "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
> -
> -addr_mode=80
> -default_prefix_option_config=03044080ffffffffffffffff00000000
> -src_mac=fa163e000004
> -src_lla=fe80000000000000f8163efffe000004
> -mtu=000005dc
> -
> -test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
> $default_prefix_option_config
> -
> -# NXT_RESUME should be 3.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap  > 3.packets
> -
> -cat 3.expected | cut -c -112 > expout
> -AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum.
> -cat 3.expected | cut -c 117- > expout
> -AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
> -
> -rm -f *.expected
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -reset_pcap_file hv1-vif3 hv1/vif3
> -
> -# Set the address mode to dhcpv6_stateless
> -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
> ipv6_ra_configs:address_mode=dhcpv6_stateless
> -# Make sure that ovn-controller has installed the corresponding OF Flow.
> -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c
> "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
> -
> -addr_mode=40
> -default_prefix_option_config=030440c0ffffffffffffffff00000000
> -src_mac=fa163e000002
> -src_lla=fe80000000000000f8163efffe000002
> -mtu=000005dc
> -
> -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
> $default_prefix_option_config
> -
> -# NXT_RESUME should be 4.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
> -
> -cat 1.expected | cut -c -112 > expout
> -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum.
> -cat 1.expected | cut -c 117- > expout
> -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
> -
> -rm -f *.expected
> -reset_pcap_file hv1-vif1 hv1/vif1
> -reset_pcap_file hv1-vif2 hv1/vif2
> -reset_pcap_file hv1-vif3 hv1/vif3
> -
> -# Set the address mode to invalid.
> -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
> ipv6_ra_configs:address_mode=invalid
> -# Make sure that ovn-controller has not installed any OF Flow for IPv6 ND
> RA.
> -OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | grep -c
> "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
> -
> -addr_mode=40
> -default_prefix_option_config=""
> -src_mac=fa163e000002
> -src_lla=fe80000000000000f8163efffe000002
> -mtu=000005dc
> -
> -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
> $default_prefix_option_config
> -
> -# NXT_RESUME should be 4 only.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
> -AT_CHECK([cat 1.packets], [0], [])
> -
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- /32 router IP address])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# 2 LS 'foo' and 'alice' connected via router R1.
> -# R1 connects to 'alice' with a /32 IP address. We use static routes and
> -# nexthop to push traffic to a logical port in switch 'alice'
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
> type=router \
> -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
> -
> -# Connect alice to R1.
> -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -          type=router options:router-port=alice
> addresses=\"00:00:00:01:02:04\"
> -
> -# Create logical port foo1 in foo
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical port alice1 in alice
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
> -
> -#install default route in R1 to use alice1's IP address as nexthop
> -ovn-nbctl lr-route-add R1 0.0.0.0/0 10.0.0.2 alice
> -
> -# Create two hypervisor and create OVS ports corresponding to logical
> ports.
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=foo1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=alice1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -
> -# 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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -# Send ip packets between foo1 and alice1
> -src_mac="f00000010203"
> -dst_mac="000000010203"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 10 0 0 2`
>
> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -
> -# Send the first packet to trigger a ARP response and population of
> -# mac_bindings table.
> -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" | wc -l`
> -gt 0])
> -ovn-nbctl --wait=hv sync
> -
> -# Packet to Expect at 'alice1'
> -src_mac="000000010204"
> -dst_mac="f00000010204"
> -src_ip=`ip_to_hex 192 168 1 2`
> -dst_ip=`ip_to_hex 10 0 0 2`
> -echo
> "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
> > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -# Add localport to the switch
> -ovn-nbctl lsp-add ls1 lp01
> -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
> -ovn-nbctl lsp-set-type lp01 localport
> -
> -net_add n1
> -
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -    ovs-vsctl add-port br-int vif01 -- \
> -        set Interface vif01 external-ids:iface-id=lp01 \
> -                              options:tx_pcap=hv${i}/vif01-tx.pcap \
> -                              options:rxq_pcap=hv${i}/vif01-rx.pcap \
> -                              ofport-request=${i}0
> -
> -    ovs-vsctl add-port br-int vif${i}1 -- \
> -        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
> -                              options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
> -                              options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
> -                              ofport-request=${i}1
> -
> -    ovn-nbctl lsp-add ls1 lp${i}1
> -    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
> -    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
> -
> -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup])
> -done
> -
> -ovn-nbctl --wait=sb sync
> -ovn-sbctl dump-flows
> -
> -OVN_POPULATE_ARP
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    echo hv${1%?}
> -}
> -#
> -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is specified
> as
> -# logical switch port numbers, e.g. 11 for vif11.
> -#
> -# EOUT is the end-to-end output port, that is, where the packet will end
> up
> -# after possibly bouncing through one or more localnet ports.  LOUT is the
> -# logical output port, which might be a localnet port, as seen by
> ovn-trace
> -# (which doesn't know what localnet ports are connected to and therefore
> can't
> -# figure out the end-to-end answer).
> -#
> -# DEFHV is the default hypervisor from where the packet is going to be
> sent
> -# if the source port is a localport.
> -for i in 1 2; do
> -    for j in 0 1; do
> -        : > $i$j.expected
> -    done
> -done
> -test_packet() {
> -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
> -    echo "$@"
> -
> -    # First try tracing the packet.
> -    uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src &&
> eth.type==0x$eth"
> -    if test $lout != drop; then
> -        echo "output(\"$lout\");"
> -    fi > expout
> -    AT_CAPTURE_FILE([trace])
> -    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed '1,/Minimal
> trace/d'], [0], [expout])
> -
> -    # Then actually send a packet, for an end-to-end test.
> -    local packet=$(echo $dst$src | sed 's/://g')${eth}
> -    hv=`vif_to_hv $inport`
> -    # If hypervisor 0 (localport) use the defhv parameter
> -    if test $hv = hv0; then
> -        hv=$defhv
> -    fi
> -    vif=vif$inport
> -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
> -    if test $eout != drop; then
> -        echo $packet >> ${eout#lp}.expected
> -    fi
> -}
> -
> -
> -# lp11 and lp21 are on different hypervisors
> -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
> -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
> -
> -# Both VIFs should be able to reach the localport on their own HV
> -test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
> -test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
> -
> -# Packet sent from localport on same hv should reach the vif
> -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 lp11 hv1
> -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 lp21 hv2
> -
> -# Packet sent from localport on different hv should be dropped
> -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop lp21 hv1
> -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop lp11 hv2
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2; do
> -    for j in 0 1; do
> -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
> -    done
> -done
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -
> -# create gateways with external network connectivity
> -
> -for i in 1 2; do
> -    sim_add gw$i
> -    as gw$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -done
> -
> -ovn-nbctl ls-add inside
> -ovn-nbctl ls-add outside
> -
> -# create hypervisors with a vif port each to an internal network
> -
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.1$i
> -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
> -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
> -        options:tx_pcap=hv$i/vif1-tx.pcap \
> -        options:rxq_pcap=hv$i/vif1-rx.pcap \
> -        ofport-request=1
> -
> -        ovn-nbctl lsp-add inside inside$i \
> -            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i
> 192.168.1.10$i"
> -
> -done
> -
> -OVN_POPULATE_ARP
> -
> -ovn-nbctl create Logical_Router name=R1
> -
> -# Connect inside to R1
> -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
> -    type=router options:router-port=inside \
> -    -- lsp-set-addresses rp-inside router
> -
> -# Connect outside to R1 as distributed router gateway port on gw1+gw2
> -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
> -
> -ovn-nbctl --id=@gc0 create Gateway_Chassis \
> -                    name=outside_gw1 chassis_name=gw1 priority=20 -- \
> -          --id=@gc1 create Gateway_Chassis \
> -                    name=outside_gw2 chassis_name=gw2 priority=10 -- \
> -          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
> -
> -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
> rp-outside \
> -    type=router options:router-port=outside \
> -    -- lsp-set-addresses rp-outside router
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -echo "---------NB dump-----"
> -ovn-nbctl show
> -echo "---------------------"
> -ovn-nbctl list logical_router
> -echo "---------------------"
> -ovn-nbctl list logical_router_port
> -echo "---------------------"
> -
> -echo "---------SB dump-----"
> -ovn-sbctl list datapath_binding
> -echo "---------------------"
> -ovn-sbctl list port_binding
> -echo "---------------------"
> -ovn-sbctl dump-flows
> -echo "---------------------"
> -ovn-sbctl list chassis
> -ovn-sbctl list encap
> -echo "---------------------"
> -echo "------ Gateway_Chassis dump (SBDB) -------"
> -ovn-sbctl list Gateway_Chassis
> -echo "------ Port_Binding chassisredirect -------"
> -ovn-sbctl find Port_Binding type=chassisredirect
> -echo "-------------------------------------------"
> -
> -# There should be one ha_chassis_group with the name "outside"
> -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
> -ha_chassis_group name="outside"`
> -
> -AT_CHECK([test $ha_chassi_grp_name = outside])
> -
> -# There should be 2 ha_chassis rows in SB DB.
> -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | awk '{print $3}' \
> -| grep '-' | wc -l ], [0], [2
> -])
> -
> -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
> -# Trim the spaces.
> -ha_ch=`echo $ha_ch | sed 's/ //g'`
> -
> -ha_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
> -do
> -    ha_ch_list="$ha_ch_list $i"
> -done
> -
> -# Trim the spaces.
> -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
> -
> -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
> -
> -for chassis in gw1 gw2 hv1 hv2; do
> -    as $chassis
> -    echo "------ $chassis dump ----------"
> -    ovs-ofctl show br-int
> -    ovs-ofctl dump-flows br-int
> -    echo "--------------------------"
> -done
> -bfd_dump() {
> -    for chassis in gw1 gw2 hv1 hv2; do
> -        as $chassis
> -        echo "------ $chassis dump (BFD)----"
> -        echo "BFD (from $chassis):"
> -        # dump BFD config and status to the other chassis
> -        for chassis2 in gw1 gw2 hv1 hv2; do
> -            if [[ "$chassis" != "$chassis2" ]]; then
> -                echo " -> $chassis2:"
> -                echo "   $(ovs-vsctl --bare --columns bfd,bfd_status find
> Interface name=ovn-$chassis2-0)"
> -            fi
> -        done
> -        echo "--------------------------"
> -    done
> -}
> -
> -bfd_dump
> -
> -hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface
> name=ovn-gw1-0)
> -hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface
> name=ovn-gw2-0)
> -hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface
> name=ovn-gw1-0)
> -hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface
> name=ovn-gw2-0)
> -
> -echo $hv1_gw1_ofport
> -echo $hv1_gw2_ofport
> -echo $hv2_gw1_ofport
> -echo $hv2_gw2_ofport
> -
> -echo "--- hv1 ---"
> -as hv1 ovs-ofctl dump-flows br-int table=32
> -
> -echo "--- hv2 ---"
> -as hv2 ovs-ofctl dump-flows br-int table=32
> -
> -gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw1)
> -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
> -
> -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
> -| wc -l], [0], [1
> -])
> -
> -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
> -| wc -l], [0], [1
> -])
> -
> -# make sure that flows for handling the outside router port reside on gw1
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# make sure ARP responder flows for outside router port reside on gw1 too
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
> -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
> arp_tpa=192.168.0.101 | wc -l], [0], [[0
> -]])
> -
> -# check that the chassis redirect port has been claimed by the gw1 chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
> -]])
> -
> -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
> -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
> -
> -exp_ref_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
> -do
> -    if test $i = $hv1_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    elif test $i = $hv2_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    fi
> -done
> -
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -
> -# at this point, we invert the priority of the gw chassis between gw1 and
> gw2
> -
> -ovn-nbctl --id=@gc0 create Gateway_Chassis \
> -                    name=outside_gw1 chassis_name=gw1 priority=10 -- \
> -          --id=@gc1 create Gateway_Chassis \
> -                    name=outside_gw2 chassis_name=gw2 priority=20 -- \
> -          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
> -
> -
> -# XXX: Let the change propagate down to the ovn-controllers
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -# we make sure that the hypervisors noticed, and inverted the slave ports
> -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
> -| wc -l], [0], [1
> -])
> -
> -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
> -| wc -l], [0], [1
> -])
> -
> -# check that the chassis redirect port has been reclaimed by the gw2
> chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
> -]])
> -
> -# check BFD enablement on tunnel ports from gw1 #########
> -as gw1
> -for chassis in gw2 hv1 hv2; do
> -    echo "checking gw1 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -
> -
> -# check BFD enablement on tunnel ports from gw2 ##########
> -as gw2
> -for chassis in gw1 hv1 hv2; do
> -    echo "checking gw2 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -
> -# check BFD enablement on tunnel ports from hv1 ###########
> -as hv1
> -for chassis in gw1 gw2; do
> -    echo "checking hv1 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -# make sure BFD is not enabled to hv2, we don't need it
> -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-hv2-0],[0],
> -         [[
> -]])
> -
> -
> -# check BFD enablement on tunnel ports from hv2 ##########
> -as hv2
> -for chassis in gw1 gw2; do
> -    echo "checking hv2 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -# make sure BFD is not enabled to hv1, we don't need it
> -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-hv1-0],[0],
> -         [[
> -]])
> -
> -# make sure that flows for handling the outside router port reside on gw2
> now
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# disconnect GW2 from the network, GW1 should take over
> -as gw2
> -port=${sandbox}_br-phys
> -as main ovs-vsctl del-port n1 $port
> -
> -bfd_dump
> -
> -# make sure that flows for handling the outside router port reside on gw2
> now
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# check that the chassis redirect port has been reclaimed by the gw1
> chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
> -]])
> -
> -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
> -as gw2
> -for chassis in gw1 hv1 hv2; do
> -    echo "checking gw2 -> $chassis"
> -    OVS_WAIT_UNTIL([
> -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0)
> -    test "$bfd_cfg" = "enable=true min_rx=2000"
> -])
> -done
> -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
> -for chassis in gw1 hv1 hv2; do
> -    echo "checking gw2 -> $chassis"
> -    OVS_WAIT_UNTIL([
> -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0)
> -    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
> -])
> -done
> -ovn-nbctl remove NB_Global . options "bfd-min-rx"
> -ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
> -for chassis in gw1 hv1 hv2; do
> -    echo "checking gw2 -> $chassis"
> -    OVS_WAIT_UNTIL([
> -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0)
> -    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
> -])
> -done
> -
> -# Delete the inside1 vif. The ref_chassis in ha_chassis_group shouldn't
> have
> -# reference to hv1.
> -as hv1 ovs-vsctl del-port hv1-vif1
> -
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$hv2_ch_uuid" = "$ref_ch_list"])
> -
> -# Delete the inside2 vif.
> -ovn-sbctl show
> -
> -echo "Deleting hv2-vif1"
> -as hv2 ovs-vsctl del-port hv2-vif1
> -
> -# ref_chassis of ha_chassis_group should be empty
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     exp_ref_ch_list=""
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# Delete the Gateway_Chassis for lrp - outside
> -ovn-nbctl clear Logical_Router_Port outside gateway_chassis
> -
> -# There shoud be no ha_chassis_group rows in SB DB.
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc -l`])
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
> -
> -ovn-nbctl remove NB_Global . options "bfd-min-rx"
> -ovn-nbctl remove NB_Global . options "bfd-min-tx"
> -ovn-nbctl remove NB_Global . options "bfd-mult"
> -
> -# Now test with HA chassis group instead of Gateway chassis in NB DB
> -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
> -
> -ovn-nbctl list ha_chassis_group
> -ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
> -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group
> name=hagrp1`
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
> -
> -# ovn-northd should not create HA chassis group and HA chassis rows
> -# unless the HA chassis group in OVN NB DB is associated to
> -# a logical router port.
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
> -
> -# Associate hagrp1 to outside logical router port
> -ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid
> -
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
> -find ha_chassis_group | wc -l`])
> -
> -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
> -grep -v chassis-name | wc -l`])
> -
> -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
> -| wc -l], [0], [1
> -])
> -
> -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
> -| wc -l], [0], [1
> -])
> -
> -# make sure that flows for handling the outside router port reside on gw1
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# make sure ARP responder flows for outside router port reside on gw1 too
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
> -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
> arp_tpa=192.168.0.101 | wc -l], [0], [[0
> -]])
> -
> -# check that the chassis redirect port has been claimed by the gw1 chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
> -]])
> -
> -# Re add the ovs ports.
> -for i in 1 2; do
> -    as hv$i
> -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
> -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
> -        options:tx_pcap=hv$i/vif1-tx.pcap \
> -        options:rxq_pcap=hv$i/vif1-rx.pcap \
> -        ofport-request=1
> -done
> -
> -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
> -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
> -
> -exp_ref_ch_list=''
> -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
> -do
> -    if test $i = $hv1_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    elif test $i = $hv2_ch_uuid; then
> -        exp_ref_ch_list="${exp_ref_ch_list}$i"
> -    fi
> -done
> -
> -OVS_WAIT_UNTIL(
> -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
> ha_chassis_group | sort`
> -     # Trim the spaces.
> -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
> -     test "$exp_ref_ch_list" = "$ref_ch_list"])
> -
> -# Increase the priority of gw2
> -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
> -
> -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
> -| wc -l], [0], [1
> -])
> -
> -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
> -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
> -| wc -l], [0], [1
> -])
> -
> -# check that the chassis redirect port has been reclaimed by the gw2
> chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
> -]])
> -
> -# check BFD enablement on tunnel ports from gw1 #########
> -as gw1
> -for chassis in gw2 hv1 hv2; do
> -    echo "checking gw1 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -
> -# check BFD enablement on tunnel ports from gw2 ##########
> -as gw2
> -for chassis in gw1 hv1 hv2; do
> -    echo "checking gw2 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -
> -# check BFD enablement on tunnel ports from hv1 ###########
> -as hv1
> -for chassis in gw1 gw2; do
> -    echo "checking hv1 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -# make sure BFD is not enabled to hv2, we don't need it
> -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-hv2-0],[0],
> -         [[
> -]])
> -
> -# check BFD enablement on tunnel ports from hv2 ##########
> -as hv2
> -for chassis in gw1 gw2; do
> -    echo "checking hv2 -> $chassis"
> -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-$chassis-0],[0],
> -             [[enable=true
> -]])
> -done
> -# make sure BFD is not enabled to hv1, we don't need it
> -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
> name=ovn-hv1-0],[0],
> -         [[
> -]])
> -
> -# make sure that flows for handling the outside router port reside on gw2
> now
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# disconnect GW2 from the network, GW1 should take over
> -as gw2
> -port=${sandbox}_br-phys
> -as main ovs-vsctl del-port n1 $port
> -
> -bfd_dump
> -
> -# make sure that flows for handling the outside router port reside on gw2
> now
> -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[1
> -]])
> -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
> -grep 00:00:02:01:02:04 | wc -l], [0], [[0
> -]])
> -
> -# check that the chassis redirect port has been reclaimed by the gw1
> chassis
> -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
> -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
> -]])
> -
> -OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA distributed
> router])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -ovn-nbctl ls-add ls0
> -ovn-nbctl ls-add ls1
> -ovn-nbctl create Logical_Router name=lr0
> -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
> -
> -ovn-nbctl --id=@gc0 create Gateway_Chassis \
> -                    name=outside_gw1 chassis_name=hv2 priority=10 -- \
> -          --id=@gc1 create Gateway_Chassis \
> -                    name=outside_gw2 chassis_name=hv3 priority=1 -- \
> -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
> -
> -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
> -    type=router options:router-port=lrp0 addresses="router"
> -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
> -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
> -    type=router options:router-port=lrp1 addresses="router"
> -
> -# Add NAT rules
> -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24])
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif
> options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -
> -sim_add hv3
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
> external-ids:ovn-bridge-mappings=physnet1:br-phys])
> -
> -# Create a localnet port.
> -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
> -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
> -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
> -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
> -
> -# wait for earlier changes to take effect
> -AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -as hv1 reset_pcap_file snoopvif hv1/snoopvif
> -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
> -# add nat-addresses option
> -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
> nat-addresses="router"
> -
> -# Wait for packets to be received through hv2.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -only_broadcast_from_lrp1() {
> -    grep "fffffffffffff00000000001"
> -}
> -
>
> -garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064"
> -echo $garp > expout
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv1_snoop_tx
> -echo "packets on hv1-snoopvif:"
> -cat hv1_snoop_tx
> -AT_CHECK([sort hv1_snoop_tx], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
> -echo "packets on hv2 br-phys tx"
> -cat hv2_br_phys_tx
> -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
> -echo "packets on hv3 br-phys tx"
> -cat hv3_br_phys_tx
> -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
> -
> -
> -# at this point, we invert the priority of the gw chassis between hv2 and
> hv3
> -
> -ovn-nbctl --wait=hv \
> -          --id=@gc0 create Gateway_Chassis \
> -                    name=outside_gw1 chassis_name=hv2 priority=1 -- \
> -          --id=@gc1 create Gateway_Chassis \
> -                    name=outside_gw2 chassis_name=hv3 priority=10 -- \
> -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
> -
> -
> -as hv1 reset_pcap_file snoopvif hv1/snoopvif
> -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
> -
> -# Wait for packets to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq >  hv1_snoopvif_tx
> -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
> -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
> -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
> -
> -# change localnet port tag.
> -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
> -
> -# wait for earlier changes to take effect
> -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int table=65 | \
> -grep "actions=mod_vlan_vid:2014" | wc -l`
> -])
> -
> -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int table=65 | \
> -grep "actions=mod_vlan_vid:2014" | wc -l`
> -])
> -
> -# update nat-addresses option
> -ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
> -
> -#Wait until the Port_Binding.nat_addresses is cleared.
> -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns nat_addresses find
> port_binding \
> -logical_port=lrp0-rp | grep is_chassis | wc -l`])
> -
> -as hv1 reset_pcap_file snoopvif hv1/snoopvif
> -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
> -
> -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
> nat-addresses="router"
> -
> -#Wait until the Port_Binding.nat_addresses is set.
> -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns nat_addresses find
> port_binding \
> -logical_port=lrp0-rp | grep is_chassis | wc -l`])
> -
> -# Wait for packets to be received.
> -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
>
> -garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064"
> -echo $garp > expout
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq >  hv1_snoopvif_tx
> -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
> -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap |
> trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
> -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't bounce
> the master])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -
> -# create two gateways with external network connectivity
> -for i in 1 2; do
> -    sim_add gw$i
> -    as gw$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -done
> -
> -ovn-nbctl ls-add inside
> -ovn-nbctl ls-add outside
> -
> -# create one hypervisors with a vif port the internal network
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.11
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=inside1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovn-nbctl lsp-add inside inside1 \
> -        -- lsp-set-addresses inside1 "f0:00:00:01:22:01 192.168.1.101"
> -
> -
> -OVN_POPULATE_ARP
> -
> -ovn-nbctl create Logical_Router name=R1
> -
> -# Connect inside to R1
> -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
> -    type=router options:router-port=inside \
> -    -- lsp-set-addresses rp-inside router
> -
> -# Connect outside to R1 as distributed router gateway port on gw1+gw2
> -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
> -
> -ovn-nbctl --id=@gc0 create Gateway_Chassis \
> -                    name=outside_gw1 chassis_name=gw1 priority=20 -- \
> -          --id=@gc1 create Gateway_Chassis \
> -                    name=outside_gw2 chassis_name=gw2 priority=10 -- \
> -          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
> -
> -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
> rp-outside \
> -    type=router options:router-port=outside \
> -    -- lsp-set-addresses rp-outside router
> -
> -# Create localnet port in outside
> -ovn-nbctl lsp-add outside ln-outside
> -ovn-nbctl lsp-set-addresses ln-outside unknown
> -ovn-nbctl lsp-set-type ln-outside localnet
> -ovn-nbctl lsp-set-options ln-outside network_name=phys
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -# currently when ovn-controller is restarted, the old entry is deleted
> -# and a new one is created, which leaves the Gateway_Chassis with
> -# an empty chassis for a while. NOTE: restarting ovn-controller in tests
> -# doesn't have the same effect because "name" is conserved, and the
> -# Chassis entry is not replaced.
> -
> -> gw1/ovn-controller.log
> -
> -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
> -ovn-sbctl destroy Chassis $gw2_chassis
> -
> -OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport"
> gw1/ovn-controller.log`])
> -
> -OVN_CLEANUP([gw1],[gw2],[hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
> -AT_KEYWORDS([ovn-nd_ns for unknown mac])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add sw0_ip6
> -ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
> -ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
> -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
> -
> -ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
> -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
> -
> -ovn-nbctl lr-add lr0_ip6
> -ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01 aef0:0:0:0:0:0:0:0/64
> -ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
> -ovn-nbctl lsp-set-type lrp0_ip6-attachment router
> -ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
> -ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
> -ovn-nbctl set logical_router_port lrp0_ip6
> ipv6_ra_configs:address_mode=slaac
> -
> -ovn-nbctl ls-add public
> -ovn-nbctl lsp-add public ln-public
> -ovn-nbctl lsp-set-addresses ln-public unknown
> -ovn-nbctl lsp-set-type ln-public localnet
> -ovn-nbctl lsp-set-options ln-public network_name=phys
> -
> -ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
> -2001:db8:1:0:200:02ff:fe01:0204/64 \
> --- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
> -
> -#install static route
> -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
> -ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
> --- add Logical_Router lr0_ip6 static_routes @lrt
> -
> -ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
> -rp-ip6_public  type=router options:router-port=ip6_public \
> --- lsp-set-addresses rp-ip6_public router
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
> -
> -# There should be 2 Neighbor Advertisement flows for the router port
> -# aef0:: ip address in logical switch pipeline with action nd_na_router.
> -AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
> -grep "nd_na_router" | wc -l], [0], [2
> -])
> -
> -# There should be 4 Neighbor Advertisement flows with action nd_na_router
> -# in the router pipeline for the router lr0_ip6.
> -AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
> -wc -l], [0], [4
> -])
> -
> -cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public | grep
> _uuid | cut -f2 -d ":"`
> -
> -# There is only one chassis.
> -chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d ":"`
> -OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding $cr_uuid
> chassis`])
> -
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for unknown MAC
> -# addresses. ovn-controller should generate an IPv6 NS request for IPv6
> -# packets whose MAC is unknown (in the ARP_REQUEST router pipeline stage.
> -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -# This function sends ipv6 packet
> -test_ipv6() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
> -
> -    local
> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
> -    packet=${packet}8000000000000000
> -
> -    src_mac=000002010204
> -
> expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
> -    expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
> -    expected_packet=${expected_packet}${nd_target}0101${src_mac}
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
> -    rm -f ipv6_ns.expected
> -    echo $expected_packet >> ipv6_ns.expected
> -}
> -
> -src_mac=506400000002
> -dst_mac=00000000af01
> -src_ip=aef0000000000000526400fffe000002
> -dst_ip=20010db800010000020002fffe010205
> -dst_mcast_mac=3333ff010205
> -mcast_node_ip=ff0200000000000000000001ff010205
> -nd_target=20010db800010000020002fffe010205
> -# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
> -# should be received by the ports attached to br-phys.
> -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
> -$mcast_node_ip $nd_target
> -
> -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " "
> -f1)])
> -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
> -trim_zeros > 1.packets
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
> -trim_zeros > 2.packets
> -
> -cat ipv6_ns.expected | cut -c -112 > expout
> -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
> -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum
> -cat ipv6_ns.expected | cut -c 117- > expout
> -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
> -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
> -
> -# Now send a packet with destination ip other than
> -# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
> -reset_pcap_file br-phys_n1 hv1/br-phys_n1
> -reset_pcap_file br-phys hv1/br-phys
> -
> -src_mac=506400000002
> -dst_mac=00000000af01
> -src_ip=aef0000000000000526400fffe000002
> -dst_ip=20020ab8000100000200020000020306
> -# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
> -dst_mcast_mac=3333ff011305
> -mcast_node_ip=ff0200000000000000000001ff011305
> -nd_target=20010db800010000020002fffe011305
> -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
> -$mcast_node_ip $nd_target
> -
> -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " "
> -f1)])
> -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
> -trim_zeros > 1.packets
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
> -trim_zeros > 2.packets
> -
> -cat ipv6_ns.expected | cut -c -112 > expout
> -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
> -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
> -
> -# Skipping the ICMPv6 checksum
> -cat ipv6_ns.expected | cut -c 117- > expout
> -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
> -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- options:requested-chassis for logical port])
> -ovn_start
> -
> -net_add n1
> -
> -ovn-nbctl ls-add ls0
> -ovn-nbctl lsp-add ls0 lsp0
> -
> -# create two hypervisors, each with one vif port
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.11
> -ovs-vsctl -- add-port br-int hv1-vif0 -- \
> -set Interface hv1-vif0 ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.12
> -ovs-vsctl -- add-port br-int hv2-vif0 -- \
> -set Interface hv2-vif0 ofport-request=1
> -
> -# Allow only chassis hv1 to bind logical port lsp0.
> -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -# Retrieve hv1 and hv2 chassis UUIDs from southbound database
> -ovn-sbctl wait-until chassis hv1
> -ovn-sbctl wait-until chassis hv2
> -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
> -hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
> -
> -# (1) Chassis hv2 should not bind lsp0 when requested-chassis is hv1.
> -echo "verifying that hv2 does not bind lsp0 when hv2 physical/logical
> mapping is added"
> -as hv2
> -ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
> -
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0"
> hv2/ovn-controller.log)])
> -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding
> logical_port=lsp0) = x], [0], [])
> -
> -# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and
> OFTABLE_LOG_TO_PHY tables.
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [1], [])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep output],
> [1], [])
> -
> -# (3) Chassis hv1 should bind lsp0 when physical to logical mapping
> exists on hv1.
> -echo "verifying that hv1 binds lsp0 when hv1 physical/logical mapping is
> added"
> -as hv1
> -ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
> -
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
> hv1/ovn-controller.log)])
> -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding
> logical_port=lsp0) = x"$hv1_uuid"], [0], [])
> -
> -# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and
> OFTABLE_LOG_TO_PHY tables.
> -as hv1 ovs-ofctl dump-flows br-int
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [0], [ignore])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
> actions=output:1], [0], [ignore])
> -
> -# (5) Chassis hv1 should release lsp0 binding and chassis hv2 should bind
> lsp0 when
> -# the requested chassis for lsp0 is changed from hv1 to hv2.
> -echo "verifying that lsp0 binding moves when requested-chassis is changed"
> -
> -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this
> chassis" hv1/ovn-controller.log)])
> -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
> port_binding logical_port=lsp0) = x"$hv2_uuid"])
> -
> -# (6) Chassis hv2 should add flows and hv1 should not.
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [0], [ignore])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
> actions=output:1], [0], [ignore])
> -
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [1], [])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output],
> [1], [])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- options:requested-chassis with hostname])
> -
> -ovn_start
> -
> -ovn-nbctl ls-add ls0
> -ovn-nbctl lsp-add ls0 lsp0
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.11
> -ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0
> ofport-request=1
> -
> -ovn-sbctl wait-until chassis hv1
> -hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis name=hv1)
> -echo "hv1_hostname=${hv1_hostname}"
> -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
> requested-chassis=${hv1_hostname}
> -as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
> -
> -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
> -echo "hv1_uuid=${hv1_uuid}"
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
> hv1/ovn-controller.log)])
> -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding
> logical_port=lsp0) = x"$hv1_uuid"], [0], [])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [0], [ignore])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
> actions=output:1], [0], [ignore])
> -
> -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
> requested-chassis=non-existant-chassis
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this
> chassis" hv1/ovn-controller.log)])
> -ovn-nbctl --wait=hv --timeout=3 sync
> -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding
> logical_port=lsp0) = x], [0], [])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1],
> [1], [])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output],
> [1], [])
> -
> -OVN_CLEANUP([hv1])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IPv6 periodic RA])
> -ovn_start
> -
> -# This test sets up two hypervisors.
> -# hv1 and hv2 run ovn-controllers, and
> -# each has a VIF connected to the same
> -# logical switch in OVN. The logical
> -# switch is connected to a logical
> -# router port that is configured to send
> -# periodic router advertisements.
> -#
> -# The reason for having two ovn-controller
> -# hypervisors is to ensure that the
> -# periodic RAs being sent by each ovn-controller
> -# are kept to their local hypervisors. If the
> -# packets are not kept local, then each port
> -# will receive too many RAs.
> -
> -net_add n1
> -sim_add hv1
> -sim_add hv2
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -
> -ovn-nbctl lr-add ro
> -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
> -
> -ovn-nbctl ls-add sw
> -ovn-nbctl lsp-add sw sw-ro
> -ovn-nbctl lsp-set-type sw-ro router
> -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
> -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
> -ovn-nbctl lsp-add sw sw-p1
> -ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02 aef0::200:ff:fe00:2"
> -ovn-nbctl lsp-add sw sw-p2
> -ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03 aef0::200:ff:fe00:3"
> -
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=4
> -ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=3
> -
> -for i in 1 2 ; do
> -    as hv$i
> -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
> -        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
> -        options:tx_pcap=hv$i/vif1-tx.pcap \
> -        options:rxq_pcap=hv$i/vif1-rx.pcap \
> -        ofport-request=1
> -done
> -
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -
> -}
> -
> -construct_expected_ra() {
> -    local src_mac=000000000001
> -    local dst_mac=333300000001
> -    local src_addr=fe80000000000000020000fffe000001
> -    local dst_addr=ff020000000000000000000000000001
> -
> -    local mtu=$1
> -    local ra_mo=$2
> -    local ra_prefix_la=$3
> -
> -    local slla=0101${src_mac}
> -    local mtu_opt=""
> -    if test $mtu != 0; then
> -        mtu_opt=05010000${mtu}
> -    fi
> -    shift 3
> -
> -    local prefix=""
> -    while [[ $# -gt 0 ]] ; do
> -        local size=$1
> -        local net=$2
> -
> prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
> -        shift 2
> -    done
> -
> -    local ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
> -    local icmp=8600XXXX${ra}
> -
> -    local ip_len=$(expr ${#icmp} / 2)
> -    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
> -
> -    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
> -    local eth=${dst_mac}${src_mac}86dd${ip}
> -    local packet=${eth}
> -    echo $packet >> expected
> -}
> -
> -ra_test() {
> -    construct_expected_ra $@
> -
> -    for i in hv1 hv2 ; do
> -        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut -d " "
> -f1)])
> -
> -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $i/vif1-tx.pcap >
> packets
> -
> -        cat expected | cut -c -112 > expout
> -        AT_CHECK([cat packets | cut -c -112], [0], [expout])
> -
> -        # Skip ICMPv6 checksum.
> -        cat expected | cut -c 117- > expout
> -        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
> -
> -        rm -f packets
> -        as $i reset_pcap_file $i-vif1 $i/vif1
> -    done
> -
> -    rm -f expected
> -}
> -
> -# Baseline test with no MTU
> -ra_test 0 00 c0 40 aef00000000000000000000000000000
> -
> -# Now make sure an MTU option makes it
> -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:mtu=1500
> -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
> -
> -# Now test for multiple network prefixes
> -ovn-nbctl --wait=hv set Logical_Router_port ro-sw networks='aef0\:\:1/64
> fd0f\:\:1/48'
> -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30
> fd0f0000000000000000000000000000
> -
> -# Test a different address mode now
> -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
> ipv6_ra_configs:address_mode=dhcpv6_stateful
> -ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30
> fd0f0000000000000000000000000000
> -
> -# And the other address mode
> -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
> ipv6_ra_configs:address_mode=dhcpv6_stateless
> -ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30
> fd0f0000000000000000000000000000
> -
> -OVN_CLEANUP([hv1],[hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ACL reject rule test])
> -AT_KEYWORDS([acl-reject])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM
> EXP_IP_CHKSUM EXP_ICMP_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv4 packet with
> -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
> -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the
> icmp destination
> -# unreachable frame generated from ACL rule hit
> -#
> -# INPORT is a lport number, e.g. 11 for vif11.
> -# HV is a hypervisor number
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC and IPV4_DST are each 8 hex digits.
> -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
> -test_ip_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6
> ip_chksum=$7
> -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
> -    shift 9
> -
> -    local ip_ttl=ff
> -    local
> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
> -
> -    local reply_icmp_ttl=ff
> -    local icmp_type_code_response=0301
> -    local icmp_data=00000000
> -    local
> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
> -    local
> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
> EXP_ICMP_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv6 packet with
> -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
> -# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination
> unreachable frame generated from ACL rule hit
> -test_ipv6_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6
> exp_icmp_chksum=$7
> -    shift 7
> -
> -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
> -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
> -
> -    local
> reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
> IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an TCP syn segment with
> -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT, TCP_DPORT,
> TCP_CHKSUM  as specified.
> -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of
> the tcp reset segment generated from ACL rule hit
> -#
> -# INPORT is an lport number, e.g. 11 for vif11.
> -# HV is an hypervisor number
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC and IPV4_DST are each 8 hex digits.
> -# TCP_SPORT and TCP_DPORT are 4 hex digits.
> -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4
> hex digits
> -test_tcp_syn_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6
> ip_chksum=$7
> -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
> -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
> -    shift 12
> -
> -    local ip_ttl=ff
> -    local
> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
> -
> -    local tcp_rst_ttl=ff
> -    local
> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# Create hypervisors hv[123].
> -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
> -# Add all of the vifs to a single logical switch sw0.
> -
> -net_add n1
> -ovn-nbctl ls-add sw0
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2 3; do
> -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
> -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
> 192.168.1.$i$j"
> -
> -        ovs-vsctl -- add-port br-int vif$i$j -- \
> -                set interface vif$i$j \
> -                external-ids:iface-id=sw0-p$i$j \
> -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
> -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
> -                ofport-request=$i$j
> -    done
> -done
> -
> -OVN_POPULATE_ARP
> -# allow some time for ovn-northd and ovn-controller to catch up.
> -sleep 1
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -for i in 1 2 3; do
> -    : > vif${i}1.expected
> -done
> -
> -ovn-nbctl --log acl-add sw0 to-lport 1000 "outport == \"sw0-p12\"" reject
> -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p11\"" reject
> -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p21\"" reject
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -ovn-nbctl --timeout=3 --wait=hv sync
> -
> -test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11)
> $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
> -test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21)
> $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
> -test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31)
> $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
> -
> -test_ipv6_packet 11 1 000000000011 000000000021
> fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 6183
> -
> -test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1
> 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 4486
> -test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1
> 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 4486
> -test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1
> 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 4486
> -
> -for i in 1 2 3; do
> -    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], [vif${i}1.expected])
> -done
> -
> -OVN_CLEANUP([hv1], [hv2], [hv3])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- Port Groups])
> -AT_KEYWORDS([ovnpg])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -#
> -# Three logical switches ls1, ls2, ls3.
> -# One logical router lr0 connected to ls[123],
> -# with nine subnets, three per logical switch:
> -#
> -#    lrp11 on ls1 for subnet 192.168.11.0/24
> -#    lrp12 on ls1 for subnet 192.168.12.0/24
> -#    lrp13 on ls1 for subnet 192.168.13.0/24
> -#    ...
> -#    lrp33 on ls3 for subnet 192.168.33.0/24
> -#
> -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
> -# digits are the subnet and the last digit distinguishes the VIF.
> -#
> -# This test will create two port groups and uses them in ACL.
> -
> -get_lsp_uuid () {
> -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
> -}
> -
> -pg1_ports=
> -pg2_ports=
> -for i in 1 2 3; do
> -    ovn-nbctl ls-add ls$i
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            ovn-nbctl \
> -                -- lsp-add ls$i lp$i$j$k \
> -                -- lsp-set-addresses lp$i$j$k \
> -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
> -            # logical ports lp[12]?1 belongs to port group pg1
> -            if test $i != 3 && test $k == 1; then
> -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
> -            fi
> -            # logical ports lp[23]?2 belongs to port group pg2
> -            if test $i != 1 && test $k == 2; then
> -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
> -            fi
> -        done
> -    done
> -done
> -
> -ovn-nbctl lr-add lr0
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
> 192.168.$i$j.254/24
> -        ovn-nbctl \
> -            -- lsp-add ls$i lrp$i$j-attachment \
> -            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
> -                             options:router-port=lrp$i$j \
> -                             addresses='"00:00:00:00:ff:'$i$j'"'
> -    done
> -done
> -
> -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
> -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
> -
> -# create ACLs on all lswitches to drop traffic from pg2 to pg1
> -ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src ==
> $pg2_ip4' drop
> -ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src ==
> $pg2_ip4' drop
> -ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src ==
> $pg2_ip4' drop
> -
> -# Physical network:
> -#
> -# Three hypervisors hv[123].
> -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on
> hv3.
> -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
> -# lp?3[123] all on hv3.
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    case $1 in dnl (
> -        ?11) echo 1 ;; dnl (
> -        ?12 | ?21 | ?22) echo 2 ;; dnl (
> -        ?13 | ?23 | ?3?) echo 3 ;;
> -    esac
> -}
> -
> -# Given the name of a logical port, prints the name of its logical router
> -# port, e.g. "vif_to_lrp 123" yields 12.
> -vif_to_lrp() {
> -    echo ${1%?}
> -}
> -
> -# Given the name of a logical port, prints the name of its logical
> -# switch, e.g. "vif_to_ls 123" yields 1.
> -vif_to_ls() {
> -    echo ${1%??}
> -}
> -
> -net_add n1
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -done
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            hv=`vif_to_hv $i$j$k`
> -                as hv$hv ovs-vsctl \
> -                -- add-port br-int vif$i$j$k \
> -                -- set Interface vif$i$j$k \
> -                    external-ids:iface-id=lp$i$j$k \
> -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
> -                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
> -                    ofport-request=$i$j$k
> -        done
> -    done
> -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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -#
> -# This shell function causes a packet to be received on INPORT.  The
> packet's
> -# content has Ethernet destination DST and source SRC (each exactly 12 hex
> -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
> -# more) list the VIFs on which the packet should be received.  INPORT and
> the
> -# OUTPORTs are specified as logical switch port numbers, e.g. 123 for
> vif123.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            : > $i$j$k.expected
> -        done
> -    done
> -done
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    in_ls=`vif_to_ls $inport`
> -    in_lrp=`vif_to_lrp $inport`
> -    for outport; do
> -        out_ls=`vif_to_ls $outport`
> -        if test $in_ls = $out_ls; then
> -            # Ports on the same logical switch receive exactly the same
> packet.
> -            echo $packet
> -        else
> -            # Routing decrements TTL and updates source and dest MAC
> -            # (and checksum).
> -            out_lrp=`vif_to_lrp $outport`
> -            echo
> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
> -        fi >> $outport.expected
> -    done
> -}
> -
> -as hv1 ovs-vsctl --columns=name,ofport list interface
> -as hv1 ovn-sbctl list port_binding
> -as hv1 ovn-sbctl list datapath_binding
> -as hv1 ovn-sbctl list port_group
> -as hv1 ovn-sbctl list address_set
> -as hv1 ovn-sbctl dump-flows
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Send IP packets between all pairs of source and destination ports,
> -# packets matches ACL (pg2 to pg1) should be dropped
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -for is in 1 2 3; do
> -  for js in 1 2 3; do
> -    for ks in 1 2 3; do
> -      bcast=
> -      s=$is$js$ks
> -      smac=f00000000$s
> -      sip=`ip_to_hex 192 168 $is$js $ks`
> -      for id in 1 2 3; do
> -          for jd in 1 2 3; do
> -              for kd in 1 2 3; do
> -                d=$id$jd$kd
> -                dip=`ip_to_hex 192 168 $id$jd $kd`
> -                if test $is = $id; then dmac=f00000000$d; else
> dmac=00000000ff$is$js; fi
> -                if test $d != $s; then unicast=$d; else unicast=; fi
> -
> -                # packets matches ACL should be dropped
> -                if test $id != 3 && test $kd == 1; then
> -                    if test $is != 1 && test $ks == 2; then
> -                        unicast=
> -                    fi
> -                fi
> -                test_ip $s $smac $dmac $sip $dip $unicast #1
> -              done
> -          done
> -        done
> -      done
> -  done
> -done
> -
> -# Allow some time for packet forwarding.
> -# XXX This can be improved.
> -sleep 1
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
> -                              [$i$j$k.expected])
> -        done
> -    done
> -done
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1], [hv2], [hv3])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ACLs on Port Groups])
> -AT_KEYWORDS([ovnpg_acl])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -#
> -# Three logical switches ls1, ls2, ls3.
> -# One logical router lr0 connected to ls[123],
> -# with nine subnets, three per logical switch:
> -#
> -#    lrp11 on ls1 for subnet 192.168.11.0/24
> -#    lrp12 on ls1 for subnet 192.168.12.0/24
> -#    lrp13 on ls1 for subnet 192.168.13.0/24
> -#    ...
> -#    lrp33 on ls3 for subnet 192.168.33.0/24
> -#
> -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
> -# digits are the subnet and the last digit distinguishes the VIF.
> -#
> -# This test will create two port groups and ACLs will be applied on them.
> -
> -get_lsp_uuid () {
> -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
> -}
> -
> -pg1_ports=
> -pg2_ports=
> -for i in 1 2 3; do
> -    ovn-nbctl ls-add ls$i
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            ovn-nbctl \
> -                -- lsp-add ls$i lp$i$j$k \
> -                -- lsp-set-addresses lp$i$j$k \
> -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
> -            # logical ports lp[12]?1 belongs to port group pg1
> -            if test $i != 3 && test $k == 1; then
> -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
> -            fi
> -            # logical ports lp[23]?2 belongs to port group pg2
> -            if test $i != 1 && test $k == 2; then
> -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
> -            fi
> -        done
> -    done
> -done
> -
> -ovn-nbctl lr-add lr0
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
> 192.168.$i$j.254/24
> -        ovn-nbctl \
> -            -- lsp-add ls$i lrp$i$j-attachment \
> -            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
> -                             options:router-port=lrp$i$j \
> -                             addresses='"00:00:00:00:ff:'$i$j'"'
> -    done
> -done
> -
> -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
> -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
> -
> -# create ACLs on pg1 to drop traffic from pg2 to pg1
> -ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
> -ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
> -        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
> -
> -# Physical network:
> -#
> -# Three hypervisors hv[123].
> -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on
> hv3.
> -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
> -# lp?3[123] all on hv3.
> -
> -# Given the name of a logical port, prints the name of the hypervisor
> -# on which it is located.
> -vif_to_hv() {
> -    case $1 in dnl (
> -        ?11) echo 1 ;; dnl (
> -        ?12 | ?21 | ?22) echo 2 ;; dnl (
> -        ?13 | ?23 | ?3?) echo 3 ;;
> -    esac
> -}
> -
> -# Given the name of a logical port, prints the name of its logical router
> -# port, e.g. "vif_to_lrp 123" yields 12.
> -vif_to_lrp() {
> -    echo ${1%?}
> -}
> -
> -# Given the name of a logical port, prints the name of its logical
> -# switch, e.g. "vif_to_ls 123" yields 1.
> -vif_to_ls() {
> -    echo ${1%??}
> -}
> -
> -net_add n1
> -for i in 1 2 3; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -done
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            hv=`vif_to_hv $i$j$k`
> -                as hv$hv ovs-vsctl \
> -                -- add-port br-int vif$i$j$k \
> -                -- set Interface vif$i$j$k \
> -                    external-ids:iface-id=lp$i$j$k \
> -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
> -                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
> -                    ofport-request=$i$j$k
> -        done
> -    done
> -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
> -
> -# Allow some time for ovn-northd and ovn-controller to catch up.
> -# XXX This should be more systematic.
> -sleep 1
> -
> -lsp_to_mac() {
> -    echo f0:00:00:00:0${1:0:1}:${1:1:2}
> -}
> -
> -lrp_to_mac() {
> -    echo 00:00:00:00:ff:$1
> -}
> -
> -# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
> -#
> -# This shell function causes a ICMP packet to be received on INPORT.
> -# The OUTPORTs (zero or more) list the VIFs on which the packet should
> -# be received.  INPORT and the OUTPORTs are specified as logical switch
> -# port numbers, e.g. 123 for vif123.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            : > $i$j$k.expected
> -        done
> -    done
> -done
> -
> -test_icmp() {
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
> -    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
> -                  eth.dst==$dst_mac && ip.ttl==64 && ip4.src==$src_ip
> -                  && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
> -                  icmp4.code==0"
> -    shift; shift; shift; shift; shift; shift
> -    hv=hv`vif_to_hv $inport`
> -    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
> -    in_ls=`vif_to_ls $inport`
> -    in_lrp=`vif_to_lrp $inport`
> -    for outport; do
> -        out_ls=`vif_to_ls $outport`
> -        if test $in_ls = $out_ls; then
> -            # Ports on the same logical switch receive exactly the same
> packet.
> -            echo $packet | ovstest test-ovn expr-to-packets
> -        else
> -            # Routing decrements TTL and updates source and dest MAC
> -            # (and checksum).
> -            out_lrp=`vif_to_lrp $outport`
> -            exp_smac=`lrp_to_mac $out_lrp`
> -            exp_dmac=`lsp_to_mac $outport`
> -            exp_packet="eth.src==$exp_smac && eth.dst==$exp_dmac &&
> -                ip.ttl==63 && ip4.src==$src_ip && ip4.dst==$dst_ip &&
> -                icmp4.type==$icmp_type && icmp4.code==0"
> -            echo $exp_packet | ovstest test-ovn expr-to-packets
> -
> -        fi >> $outport.expected
> -    done
> -}
> -
> -as hv1 ovs-vsctl --columns=name,ofport list interface
> -as hv1 ovn-sbctl list port_binding
> -as hv1 ovn-sbctl list datapath_binding
> -as hv1 ovn-sbctl list port_group
> -as hv1 ovn-sbctl list address_set
> -as hv1 ovn-sbctl dump-flows
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Send IP packets between all pairs of source and destination ports,
> -# packets matches ACL1 but not ACL2 should be dropped
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -for is in 1 2 3; do
> -  for js in 1 2 3; do
> -    for ks in 1 2 3; do
> -      bcast=
> -      s=$is$js$ks
> -      slsp_mac=`lsp_to_mac $s`
> -      slrp_mac=`lrp_to_mac $is$js`
> -      sip=192.168.$is$js.$ks
> -      for id in 1 2 3; do
> -          for jd in 1 2 3; do
> -              for kd in 1 2 3; do
> -                d=$id$jd$kd
> -                dlsp_mac=`lsp_to_mac $d`
> -                dlrp_mac=`lrp_to_mac $id$jd`
> -                dip=192.168.$id$jd.$kd
> -                if test $is = $id; then dmac=$dlsp_mac; else
> dmac=$slrp_mac; fi
> -                if test $d != $s; then unicast=$d; else unicast=; fi
> -
> -                # packets matches ACL1 but not ACL2 should be dropped
> -                if test $id != 3 && test $kd == 1; then
> -                    if test $is == 1 || test $ks != 2; then
> -                        unicast=
> -                    fi
> -                fi
> -                # icmp request (type = 8)
> -                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
> -
> -                # if packets are not dropped, test the return traffic
> (icmp echo)
> -                # to make sure stateful works, too.
> -                if test x$unicast != x; then
> -                    if test $is = $id; then dmac=$slsp_mac; else
> dmac=$dlrp_mac; fi
> -                    # icmp echo (type = 0)
> -                    test_icmp $unicast $dlsp_mac $dmac $dip $sip 0 $s
> -                fi
> -              done
> -          done
> -        done
> -      done
> -  done
> -done
> -
> -# Allow some time for packet forwarding.
> -# XXX This can be improved.
> -sleep 1
> -
> -# Now check the packets actually received against the ones expected.
> -for i in 1 2 3; do
> -    for j in 1 2 3; do
> -        for k in 1 2 3; do
> -            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
> -                              [$i$j$k.expected])
> -        done
> -    done
> -done
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1], [hv2], [hv3])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- Address Set generation from Port Groups (static
> addressing)])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -ovn-nbctl lsp-add ls1 lp1
> -ovn-nbctl lsp-add ls1 lp2
> -ovn-nbctl lsp-add ls1 lp3
> -
> -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1 2001:db8::1"
> -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2 2001:db8::2"
> -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3 2001:db8::3"
> -
> -ovn-nbctl create Port_Group name=pg1
> -ovn-nbctl create Port_Group name=pg2
> -
> -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports
> @p
> -
> -ovn-nbctl --wait=sb sync
> -
> -dnl Check if port group address sets were populated with ports' addresses
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
> -         [0], [[["10.0.0.1", "10.0.0.2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
> -         [0], [[["10.0.0.2", "10.0.0.3"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
> -         [0], [[["2001:db8::1", "2001:db8::2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
> -         [0], [[["2001:db8::2", "2001:db8::3"]]
> -])
> -
> -ovn-nbctl --wait=sb lsp-set-addresses lp1 \
> -    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
> -
> -dnl Check if updated address got propagated to the port group address sets
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
> -         [0], [[["10.0.0.11", "10.0.0.2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
> -         [0], [[["2001:db8::11", "2001:db8::2"]]
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic
> addressing)])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl ls-add ls2
> -ovn-nbctl ls-add ls3
> -
> -ovn-nbctl set Logical_Switch ls1 \
> -    other_config:subnet=10.1.0.0/24
> other_config:ipv6_prefix="2001:db8:1::"
> -ovn-nbctl set Logical_Switch ls2 \
> -    other_config:subnet=10.2.0.0/24
> other_config:ipv6_prefix="2001:db8:2::"
> -ovn-nbctl set Logical_Switch ls3 \
> -    other_config:subnet=10.3.0.0/24
> other_config:ipv6_prefix="2001:db8:3::"
> -
> -ovn-nbctl lsp-add ls1 lp1
> -ovn-nbctl lsp-add ls2 lp2
> -ovn-nbctl lsp-add ls3 lp3
> -
> -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
> -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
> -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
> -
> -ovn-nbctl create Port_Group name=pg1
> -ovn-nbctl create Port_Group name=pg2
> -
> -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports
> @p
> -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports
> @p
> -
> -ovn-nbctl --wait=sb sync
> -
> -dnl Check if port group address sets were populated with ports' addresses
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
> -         [0], [[["10.1.0.2", "10.2.0.2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
> -         [0], [[["10.2.0.2", "10.3.0.2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
> -         [0], [[["2001:db8:1::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
> -         [0], [[["2001:db8:2::ff:fe00:2", "2001:db8:3::ff:fe00:3"]]
> -])
> -
> -ovn-nbctl --wait=sb set Logical_Switch ls1 \
> -    other_config:subnet=10.11.0.0/24
> other_config:ipv6_prefix="2001:db8:11::"
> -
> -dnl Check if updated address got propagated to the port group address sets
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
> -         [0], [[["10.11.0.2", "10.2.0.2"]]
> -])
> -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
> -         [0], [[["2001:db8:11::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ACL conjunction])
> -ovn_start
> -
> -ovn-nbctl ls-add ls1
> -
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
> -
> -ovn-nbctl lsp-add ls1 ls1-lp2 \
> --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
> -
> -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
> -
> -net_add n1
> -sim_add hv1
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=2
> -
> -ovn-nbctl create Address_Set name=set1 \
> -addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
> -ovn-nbctl create Address_Set name=set2 \
> -addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
> -ovn-nbctl acl-add ls1 to-lport 1002 \
> -'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
> -ovn-nbctl acl-add ls1 to-lport 1001 \
> -'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
> -
> -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
> -#
> -# This shell function causes an ip packet to be received on INPORT.
> -# The packet's content has Ethernet destination DST and source SRC
> -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
> -# The OUTPORTs (zero or more) list the VIFs on which the packet should
> -# be received.  INPORT and the OUTPORTs are specified as logical switch
> -# port numbers, e.g. 11 for vif11.
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
> -${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -    for outport; do
> -        echo $packet >> $outport.expected
> -    done
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -
> -sip=`ip_to_hex 10 0 0 4`
> -dip=`ip_to_hex 10 0 0 6`
> -
> -test_ip 1 f00000000001 f00000000002 $sip $dip 2
> -
> -cat 2.expected > expout
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -AT_CHECK([cat 2.packets], [0], [expout])
> -
> -# There should be total of 12 flows present with conjunction action and 2
> flows
> -# with conj match. Eg.
> -# table=44, priority=2002,conj_id=2,metadata=0x1 actions=resubmit(,45)
> -# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
> -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(2,2/2)
> -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,2/2)
> -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(2,2/2)
> -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,2/2)
> -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(3,2/2)
> -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(3,2/2)
> -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(2,1/2)
> -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(2,1/2)
> -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(2,1/2)
> -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(3,1/2)
> -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(3,1/2)
> -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(3,1/2)
> -
> -OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
> -grep conjunction | wc -l`])
> -OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
> -grep conj_id | wc -l`])
> -
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -# Set the ip address for ls1-lp2 from set2 so that the drop ACL flow is
> hit.
> -ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7 20.0.0.4"
> -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.7
> 20.0.0.4"
> -
> -reset_pcap_file hv1-vif2 hv1/vif2
> -
> -rm -f 2.packets
> -
> -sip=`ip_to_hex 10 0 0 4`
> -dip=`ip_to_hex 10 0 0 7`
> -
> -test_ip 1 f00000000001 f00000000002 $sip $dip
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> -AT_CHECK([cat 2.packets], [0], [])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- TTL exceeded])
> -AT_KEYWORDS([ttl-exceeded])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IPV4_ROUTER
> IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv4 packet with
> -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified and TTL
> set to 1.
> -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the
> icmp time exceeded frame
> -# generated by OVN logical router
> -#
> -# INPORT is a lport number, e.g. 11 for vif11.
> -# HV is a hypervisor number
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
> -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
> -test_ip_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6
> ip_router=$7 ip_chksum=$8
> -    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
> -    shift 10
> -
> -    local ip_ttl=01
> -    local
> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
> -
> -    local reply_icmp_ttl=fe
> -    local icmp_type_code_response=0b00
> -    local icmp_data=00000000
> -    local
> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
> -    local
> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_ROUTER
> EXP_ICMP_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv6
> -# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified.
> -# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum of the
> icmpv6 ttl exceeded
> -# packet sent by OVN logical router
> -test_ip6_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6
> ipv6_router=$7 exp_icmp_chksum=$8
> -    shift 8
> -
> -    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
> -    local
> packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
> -
> -    local
> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -for i in 1 2; do
> -    net_add n$i
> -    ovn-nbctl ls-add sw$i
> -
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n$i br-phys 192.168.$i.1
> -
> -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
> -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1
> 2001:db8:$i::11"
> -
> -    ovs-vsctl -- add-port br-int vif$i -- \
> -        set interface vif$i \
> -        external-ids:iface-id=sw$i-p${i}0 \
> -            options:tx_pcap=hv$i/vif$i-tx.pcap \
> -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
> -            ofport-request=$i
> -done
> -
> -ovn-nbctl lr-add lr0
> -for i in 1 2; do
> -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24
> 2001:db8:$i::1/64
> -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
> -              -- set Logical_Switch_Port lrp$i-attachment type=router \
> -                options:router-port=lrp$i
> addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
> -done
> -
> -OVN_POPULATE_ARP
> -# allow some time for ovn-northd and ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -
> -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1)
> $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae f4ff
> -test_ip6_packet 1 1 000000000001 00000000ff01
> 20010db8000100000000000000000011 20010db8000200000000000000000011
> 20010db8000100000000000000000001 d461
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
> -
> -OVN_CLEANUP([hv1], [hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- router port unreachable])
> -AT_KEYWORDS([router-port-unreachable])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
> L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv4 packet with
> -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM as
> specified.
> -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the
> icmp frame generated by OVN logical router
> -# EXP_ICMP_CODE are code and type of the icmp frame generated by OVN
> logical router
> -#
> -# INPORT is a lport number, e.g. 11 for vif11.
> -# HV is a hypervisor number
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
> -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
> -test_ip_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6
> l4_proto=$7 ip_chksum=$8
> -    local exp_ip_chksum=$9 exp_icmp_chksum=${10} exp_icmp_code=${11}
> -    shift 11
> -
> -    local ip_ttl=ff
> -    local
> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
> -
> -    local reply_icmp_ttl=fe
> -    local icmp_data=00000000
> -    local
> reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
> -    local
> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
> IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an TCP syn segment with
> -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT,
> TCP_DPORT, TCP_CHKSUM  as specified.
> -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of
> the tcp reset segment generated by OVN logical router
> -#
> -# INPORT is an lport number, e.g. 11 for vif11.
> -# HV is an hypervisor number
> -# ETH_SRC and ETH_DST are each 12 hex digits.
> -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
> -# TCP_SPORT and TCP_DPORT are 4 hex digits.
> -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4
> hex digits
> -test_tcp_syn_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6
> ip_chksum=$7
> -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
> -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
> -    shift 12
> -
> -    local ip_ttl=ff
> -    local
> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
> -
> -    local tcp_rst_ttl=fe
> -    local
> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
> TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is a TCP syn segment with
> -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT and
> TCP_CHKSUM as specified.
> -# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset segment
> generated by OVN logical router
> -test_tcp6_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_router=$6
> -    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
> -    local exp_tcp_rst_chksum=${10}
> -    shift 10
> -
> -    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
> -    local
> packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
> -
> -    local
> reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_PROTO
> IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
> -#
> -# Causes a packet to be received on INPORT of the hypervisor HV. The
> packet is an IPv6
> -# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO, IPV6_LEN
> and DATA as specified.
> -# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of the
> icmp6 packet sent by OVN logical router
> -test_ip6_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6
> ipv6_proto=$7 ipv6_len=$8 data=$9
> -    local exp_icmp_code=${10} exp_icmp_chksum=${11}
> -    shift 11
> -
> -    local ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
> -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
> -
> -    local
> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}
> -    echo $reply >> vif$inport.expected
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -for i in 1 2; do
> -    net_add n$i
> -    ovn-nbctl ls-add sw$i
> -
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n$i br-phys 192.168.$i.1
> -
> -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
> -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1
> 2001:db8:$i::11"
> -
> -    ovs-vsctl -- add-port br-int vif$i -- \
> -        set interface vif$i \
> -        external-ids:iface-id=sw$i-p${i}0 \
> -            options:tx_pcap=hv$i/vif$i-tx.pcap \
> -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
> -            ofport-request=$i
> -done
> -
> -ovn-nbctl lr-add lr0
> -for i in 1 2; do
> -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24
> 2001:db8:$i::1/64
> -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
> -              -- set Logical_Switch_Port lrp$i-attachment type=router \
> -                options:router-port=lrp$i
> addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
> -done
> -
> -OVN_POPULATE_ARP
> -# allow some time for ovn-northd and ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -
> -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1)
> $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
> -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1)
> $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
> -test_ip6_packet 1 1 000000000001 00000000ff01
> 20010db8000100000000000000000011 20010db8000100000000000000000001 11 0015
> dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
> -
> -test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192 168 2
> 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
> -test_ip6_packet 2 2 000000000002 00000000ff02
> 20010db8000200000000000000000011 20010db8000200000000000000000001 84 0004
> 01020304 0103 627e
> -test_tcp6_packet 2 2 000000000002 00000000ff02
> 20010db8000200000000000000000011 20010db8000200000000000000000001 8b40 3039
> 0000 4486
> -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
> -
> -OVN_CLEANUP([hv1], [hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ovn-controller exit])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -# Logical network:
> -# One Logical Router: ro, with two logical switches sw1 and sw2.
> -# sw1 is for subnet 10.0.0.0/8
> -# sw2 is for subnet 20.0.0.0/8
> -# sw1 has a single port bound on hv1
> -# sw2 has a single port bound on hv2
> -
> -ovn-nbctl lr-add ro
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add sw2
> -
> -sw1_ro_mac=00:00:10:00:00:01
> -sw1_ro_ip=10.0.0.1
> -sw2_ro_mac=00:00:20:00:00:01
> -sw2_ro_ip=20.0.0.1
> -sw1_p1_mac=00:00:10:00:00:02
> -sw1_p1_ip=10.0.0.2
> -sw2_p1_mac=00:00:20:00:00:02
> -sw2_p1_ip=20.0.0.2
> -
> -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
> -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
> -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
> type=router \
> -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
> -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
> type=router \
> -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
> -
> -ovn-nbctl lsp-add sw1 sw1-p1 \
> --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
> -
> -ovn-nbctl lsp-add sw2 sw2-p1 \
> --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -OVN_POPULATE_ARP
> -
> -sleep 1
> -
> -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
> eth.dst==$sw1_ro_mac &&
> -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -
> -# Start by Sending the packet and make sure it makes it there as expected
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
> -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Stop ovn-controller on hv2
> -as hv2 ovs-appctl -t ovn-controller exit
> -
> -# Now send the packet again. This time, it should not arrive.
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
> -as hv2 start_daemon ovn-controller
> -
> -OVN_CLEANUP([hv1],[hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- external logical port])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -sim_add hv1
> -sim_add hv2
> -sim_add hv3
> -
> -ovn-nbctl ls-add ls1
> -ovn-nbctl lsp-add ls1 ls1-lp1 \
> --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
> -
> -# Add a couple of external logical port
> -ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
> --- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 ae70::6"
> -ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
> -"f0:00:00:00:00:03 10.0.0.6 ae70::6"
> -ovn-nbctl lsp-set-type ls1-lp_ext1 external
> -
> -ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
> --- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 ae70::7"
> -ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
> -"f0:00:00:00:00:04 10.0.0.7 ae70::8"
> -ovn-nbctl lsp-set-type ls1-lp_ext2 external
> -
> -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
> -options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
> -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
> -
> -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
> -options="\"server_id\"=\"00:00:00:10:00:01\"")"
> -
> -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
> -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
> -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
> -
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
> -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
> -
> -# Create a logical router and connect it to ls1
> -ovn-nbctl lr-add lr0
> -ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
> -ovn-nbctl lsp-add ls1 ls1-lr0
> -ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
> -    options:router-port=lr0-ls1 addresses=router
> -
> -# Create HA chassis group
> -ovn-nbctl ha-chassis-group-add hagrp1
> -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
> -
> -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group
> name="hagrp1"`
> -
> -# There should be 1 HA_Chassis rows with chassis sets
> -OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk '{print
> $3}' \
> -| grep '-' | wc -l ], [0], [1
> -])
> -
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-phys hv1-ext1 -- \
> -    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
> -    options:rxq_pcap=hv1/ext1-rx.pcap \
> -    ofport-request=2
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-phys hv2-ext2 -- \
> -    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
> -    options:rxq_pcap=hv2/ext2-rx.pcap \
> -    ofport-request=2
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -as hv3
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.3
> -ovs-vsctl -- add-port br-phys hv3-ext3 -- \
> -    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
> -    options:rxq_pcap=hv3/ext3-rx.pcap \
> -    ofport-request=2
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in
> hv1 and
> -# hv2 as ha-chassis-group is not set and no localnet port added to ls1.
> -AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
> -wc -l], [0], [0
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
> -])
> -
> -hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print $3}')
> -hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print $3}')
> -hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print $3}')
> -
> -# The port_binding row for ls1-lp_ext1 should have empty chassis
> -chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -
> -AT_CHECK([test x$chassis == x], [0], [])
> -
> -# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
> -ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
> -ha-chassis-group=$hagrp1_uuid
> -
> -# Get the hagrp1 uuid in SB DB.
> -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group \
> -name="hagrp1"`
> -
> -# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
> -OVS_WAIT_UNTIL(
> -    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group find \
> -port_binding logical_port=ls1-lp_ext1`
> -     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
> -
> -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in
> hv1 and hv2
> -# as no localnet port added to ls1 yet.
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
> -])
> -
> -# Add the localnet port to the logical switch ls1
> -ovn-nbctl lsp-add ls1 ln-public
> -ovn-nbctl lsp-set-addresses ln-public unknown
> -ovn-nbctl lsp-set-type ln-public localnet
> -ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
> -
> -ln_public_key=$(ovn-sbctl list port_binding ln-public | grep  tunnel_key
> | \
> -awk '{print $3}')
> -
> -# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of the
> -# ha chassis group.
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = "$hv1_uuid"])
> -
> -# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port in hv1
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
> -wc -l], [0], [3
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
> -grep reg14=0x$ln_public_key | wc -l], [0], [1
> -])
> -
> -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
> -])
> -
> -# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 - 10.0.0.7 in
> hv1 and
> -# hv2 as requested-chassis option is not set.
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
> -])
> -
> -as hv1
> -ovs-vsctl show
> -
> -# This shell function sends a DHCP request packet
> -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
> -test_dhcp() {
> -    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
> -    shift; shift; shift; shift; shift;
> -    if test $use_ip != 0; then
> -        src_ip=$1
> -        dst_ip=$2
> -        shift; shift;
> -    else
> -        src_ip=`ip_to_hex 0 0 0 0`
> -        dst_ip=`ip_to_hex 255 255 255 255`
> -    fi
> -    local
> request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip}
> -    # udp header and dhcp header
> -    request=${request}0044004300fc0000
> -
> request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac}
> -    # client hardware padding
> -    request=${request}00000000000000000000
> -    # server hostname
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -    # boot file name
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -
> request=${request}0000000000000000000000000000000000000000000000000000000000000000
> -    # dhcp magic cookie
> -    request=${request}63825363
> -    # dhcp message type
> -    request=${request}3501${dhcp_type}ff
> -
> -    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
> -    # total IP length will be the IP length of the request packet
> -    # (which is 272 in our case) + 8 (padding bytes) +
> (expected_dhcp_opts / 2)
> -    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
> -    udp_len=`expr $ip_len - 20`
> -    ip_len=$(printf "%x" $ip_len)
> -    udp_len=$(printf "%x" $udp_len)
> -    # $ip_len var will be in 3 digits i.e 134. So adding a '0' before
> $ip_len
> -    local
> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
> -    # udp header and dhcp header.
> -    # $udp_len var will be in 3 digits. So adding a '0' before $udp_len
> -    reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
> -    # your ip address
> -    reply=${reply}${offer_ip}
> -    # next server ip address, relay agent ip address, client mac address
> -    reply=${reply}0000000000000000${src_mac}
> -    # client hardware padding
> -    reply=${reply}00000000000000000000
> -    # server hostname
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -    # boot file name
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -
> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
> -    # dhcp magic cookie
> -    reply=${reply}63825363
> -    # dhcp message type
> -    local dhcp_reply_type=02
> -    if test $dhcp_type = 03; then
> -        dhcp_reply_type=05
> -    fi
> -
> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
> -    echo $reply >> ext1_v4.expected
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport}
> $request
> -}
> -
> -
> -trim_zeros() {
> -    sed 's/\(00\)\{1,\}$//'
> -}
> -
> -# This shell function sends a DHCPv6 request packet
> -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
> -# The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
> -# packet should be received twice (one from ovn-controller and the other
> -# from the "ovs-ofctl monitor br-int resume"
> -test_dhcpv6() {
> -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
> -    local req_pkt_in_expected=$6
> -    local request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
> -    # dst ip ff02::1:2
> -    request=${request}ff020000000000000000000000010002
> -    # udp header and dhcpv6 header
> -    request=${request}02220223002affff${msg_code}010203
> -    # Client identifier
> -    request=${request}0001000a00030001${src_mac}
> -    # IA-NA (Identity Association for Non Temporary Address)
> -    request=${request}0003000c0102030400000e1000001518
> -    shift; shift; shift; shift; shift;
> -
> -    local server_mac=000000100001
> -    local server_lla=fe80000000000000020000fffe100001
> -    local reply_code=07
> -    if test $msg_code = 01; then
> -        reply_code=02
> -    fi
> -    local msg_len=54
> -    if test $offer_ip = 1; then
> -        msg_len=28
> -    fi
> -    local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
> -    reply=${reply}${server_lla}${src_lla}
> -
> -    # udp header and dhcpv6 header
> -    reply=${reply}0223022200${msg_len}ffff${reply_code}010203
> -    # Client identifier
> -    reply=${reply}0001000a00030001${src_mac}
> -    # IA-NA
> -    if test $offer_ip != 1; then
> -        reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
> -        reply=${reply}ffffffffffffffff
> -    fi
> -    # Server identifier
> -    reply=${reply}0002000a00030001${server_mac}
> -
> -    echo $reply | trim_zeros >> ext${inport}_v6.expected
> -    # The inport also receives the request packet since it is connected
> -    # to the br-phys.
> -    #echo $request >> ext${inport}_v6.expected
> -
> -    as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport}
> $request
> -}
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
> -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
> -
> -AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
> -as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
> -
> -AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
> -as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
> ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
> -
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -# Send DHCPDISCOVER.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -server_mac=ff1000000001
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
> -$expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 1 in hv1.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 0 in hv2.
> -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap >
> ext1_v4.packets
> -cat ext1_v4.expected | cut -c -48 > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat ext1_v4.expected | cut -c 53- > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
> -
> -# ovs-ofctl also resumes the packets and this causes other ports to
> receive
> -# the DHCP request packet. So reset the pcap files so that its easier to
> test.
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -rm -f ext1_v4.expected
> -rm -f ext1_v4.packets
> -
> -# Send DHCPv6 request
> -src_mac=f00000000003
> -src_lla=fe80000000000000f20000fffe000003
> -offer_ip=ae700000000000000000000000000006
> -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
> -
> -# NXT_RESUMEs should be 2 in hv1.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 0 in hv2.
> -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
> -sort > ext1_v6.packets
> -cat ext1_v6.expected | cut -c -120 > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
> -# Skipping the UDP checksum
> -cat ext1_v6.expected | cut -c 125- > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
> -
> -rm -f ext1_v6.expected
> -rm -f ext1_v6.packets
> -
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -# Delete the ha-chassis hv1.
> -ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = ""])
> -
> -# Add hv2 to the ha chassis group
> -ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
> -
> -ovn-sbctl list ha_chassis_group
> -ovn-sbctl list ha_chassis
> -
> -ovn-sbctl find port_binding logical_port=ls1-lp_ext1
> -
> -# The ls1-lp_ext1 should be bound to hv2
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = "$hv2_uuid"])
> -
> -# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port in hv2
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
> -wc -l], [0], [3
> -])
> -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
> -grep reg14=0x$ln_public_key | wc -l], [0], [1
> -])
> -
> -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
> -])
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
> -grep controller | grep tp_src=546 | grep \
> -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
> -grep reg14=0x$ln_public_key | wc -l], [0], [0
> -])
> -
> -# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should come from
> -# hv2 ovn-controller.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -server_mac=ff1000000001
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
> -$expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 2 in hv1.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 1 in hv2.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap >
> ext1_v4.packets
> -cat ext1_v4.expected | cut -c -48 > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat ext1_v4.expected | cut -c 53- > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
> -
> -# ovs-ofctl also resumes the packets and this causes other ports to
> receive
> -# the DHCP request packet. So reset the pcap files so that its easier to
> test.
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -rm -f ext1_v4.expected
> -
> -# Send DHCPv6 request again
> -src_mac=f00000000003
> -src_lla=fe80000000000000f20000fffe000003
> -offer_ip=ae700000000000000000000000000006
> -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
> -
> -# NXT_RESUMEs should be 2 in hv1.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
> -sort > ext1_v6.packets
> -cat ext1_v6.expected | cut -c -120 > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
> -# Skipping the UDP checksum
> -cat ext1_v6.expected | cut -c 125- > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
> -
> -rm -f ext1_v6.expected
> -rm -f ext1_v6.packets
> -
> -as hv1
> -ovs-vsctl show
> -reset_pcap_file hv1-ext1 hv1/ext1
> -reset_pcap_file br-phys_n1 hv1/br-phys_n1
> -reset_pcap_file br-phys hv1/br-phys
> -
> -as hv2
> -ovs-vsctl show
> -reset_pcap_file hv2-ext2 hv2/ext2
> -reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -reset_pcap_file br-phys hv2/br-phys
> -
> -# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
> -# response should come from the router pipeline of hv2.
> -ext1_mac=f00000000003
> -router_mac=a01000000001
> -ext1_ip=`ip_to_hex 10 0 0 6`
> -router_ip=`ip_to_hex 10 0 0 1`
>
> -arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip}
> -
> -as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
>
> -expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip}
> -echo $expected_response > expout
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap >
> ext1_arp_resp
> -AT_CHECK([cat ext1_arp_resp], [0], [expout])
> -
> -# Verify that the response came from hv2
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap >
> ext1_arp_resp
> -AT_CHECK([cat ext1_arp_resp], [0], [expout])
> -
> -# Now add 3 ha chassis to the ha chassis group
> -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
> -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
> -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
> -
> -# hv1 should be master and claim ls1-lp_ext1
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = "$hv1_uuid"])
> -
> -as hv1
> -ovs-vsctl show
> -reset_pcap_file hv1-ext1 hv1/ext1
> -reset_pcap_file br-phys_n1 hv1/br-phys_n1
> -reset_pcap_file br-phys hv1/br-phys
> -
> -as hv2
> -ovs-vsctl show
> -reset_pcap_file hv2-ext2 hv2/ext2
> -reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -reset_pcap_file br-phys hv2/br-phys
> -
> -as hv3
> -ovs-vsctl show
> -reset_pcap_file hv3-ext3 hv3/ext3
> -reset_pcap_file br-phys_n1 hv3/br-phys_n1
> -reset_pcap_file br-phys hv3/br-phys
> -
> -# Send DHCPDISCOVER.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -server_mac=ff1000000001
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
> -$expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 3 in hv1.
> -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap >
> ext1_v4.packets
> -cat ext1_v4.expected | cut -c -48 > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat ext1_v4.expected | cut -c 53- > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
> -
> -# ovs-ofctl also resumes the packets and this causes other ports to
> receive
> -# the DHCP request packet. So reset the pcap files so that its easier to
> test.
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -rm -f ext1_v4.expected
> -rm -f ext1_v4.packets
> -
> -# Send DHCPv6 request
> -src_mac=f00000000003
> -src_lla=fe80000000000000f20000fffe000003
> -offer_ip=ae700000000000000000000000000006
> -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
> -
> -# NXT_RESUMEs should be 4 in hv1.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
> -sort > ext1_v6.packets
> -cat ext1_v6.expected | cut -c -120 > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
> -# Skipping the UDP checksum
> -cat ext1_v6.expected | cut -c 125- > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
> -
> -rm -f ext1_v6.expected
> -rm -f ext1_v6.packets
> -as hv1 reset_pcap_file hv1-ext1 hv1/ext1
> -
> -# Now increase the priority of hv3 so it becomes master.
> -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
> -
> -# hv3 should be master and claim ls1-lp_ext1
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = "$hv3_uuid"])
> -
> -as hv1
> -ovs-vsctl show
> -reset_pcap_file hv1-ext1 hv1/ext1
> -reset_pcap_file br-phys_n1 hv1/br-phys_n1
> -reset_pcap_file br-phys hv1/br-phys
> -
> -as hv2
> -ovs-vsctl show
> -reset_pcap_file hv2-ext2 hv2/ext2
> -reset_pcap_file br-phys_n1 hv2/br-phys_n1
> -reset_pcap_file br-phys hv2/br-phys
> -
> -as hv2
> -ovs-vsctl show
> -reset_pcap_file hv3-ext3 hv3/ext3
> -reset_pcap_file br-phys_n1 hv3/br-phys_n1
> -reset_pcap_file br-phys hv3/br-phys
> -
> -# Send DHCPDISCOVER.
> -offer_ip=`ip_to_hex 10 0 0 6`
> -server_ip=`ip_to_hex 10 0 0 1`
> -server_mac=ff1000000001
> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
> -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
> -$expected_dhcp_opts
> -
> -# NXT_RESUMEs should be 4 in hv1.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 1 in hv3.
> -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap >
> ext1_v4.packets
> -cat ext1_v4.expected | cut -c -48 > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
> -# Skipping the IPv4 checksum.
> -cat ext1_v4.expected | cut -c 53- > expout
> -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
> -
> -# ovs-ofctl also resumes the packets and this causes other ports to
> receive
> -# the DHCP request packet. So reset the pcap files so that its easier to
> test.
> -as hv1
> -reset_pcap_file hv1-ext1 hv1/ext1
> -
> -rm -f ext1_v4.expected
> -rm -f ext1_v4.packets
> -
> -# Send DHCPv6 request
> -src_mac=f00000000003
> -src_lla=fe80000000000000f20000fffe000003
> -offer_ip=ae700000000000000000000000000006
> -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
> -
> -# NXT_RESUMEs should be 4 in hv1.
> -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv2.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
> NXT_RESUME`])
> -
> -# NXT_RESUMEs should be 2 in hv3.
> -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c
> NXT_RESUME`])
> -
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
> -sort > ext1_v6.packets
> -cat ext1_v6.expected | cut -c -120 > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
> -# Skipping the UDP checksum
> -cat ext1_v6.expected | cut -c 125- > expout
> -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
> -
> -# disconnect hv3 from the network, hv1 should take over
> -as hv3
> -port=${sandbox}_br-phys
> -as main ovs-vsctl del-port n1 $port
> -
> -# hv1 should be master and claim ls1-lp_ext1
> -OVS_WAIT_UNTIL(
> -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
> -logical_port=ls1-lp_ext1`
> -    test "$chassis" = "$hv1_uuid"])
> -
> -OVN_CLEANUP([hv1],[hv2],[hv3])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- Address Set Incremental Processing])
> -AT_KEYWORDS([ovn_as_inc])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.10
> -
> -ovn-nbctl ls-add ls1
> -for i in 1 2; do
> -    ovn-nbctl lsp-add ls1 lp$i \
> -        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i"
> -    as hv1 ovs-vsctl \
> -        -- add-port br-int vif$i \
> -        -- set Interface vif$i \
> -            external-ids:iface-id=lp$i
> -done
> -
> -for i in 1 2 3; do
> -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
> -    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
> -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
> -            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}'
> allow-related
> -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [0],
> [ignore])
> -
> -    # Update address set as1
> -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"], [0],
> [ignore])
> -
> -    # Update address set as2
> -    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0],
> [ignore])
> -
> -    # Add another ACL referencing as1
> -    n_flows_before=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc
> -l`
> -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
> -            'outport=="lp2" && ip4 && ip4.src == $as1' allow-related
> -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
> -    AT_CHECK([test $(expr $n_flows_before \* 2) = $n_flows_after], [0],
> [ignore])
> -
> -    # Remove an ACL
> -    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
> -            'outport=="lp2" && ip4 && ip4.src == $as1'
> -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
> -    AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore])
> -
> -    # Remove as1 while it is still used by an ACL, the lflows should be
> reparsed and
> -    # parsing should fail.
> -    echo "before del as1"
> -    ovn-nbctl list addr | grep as1
> -    ovn-nbctl --wait=hv destroy addr $as1_uuid
> -    echo "after del as1"
> -    ovn-nbctl list addr | grep as1
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [1],
> [ignore])
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1],
> [ignore])
> -
> -    # Recreate as1
> -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0],
> [ignore])
> -
> -    # Remove ACLs and address sets
> -    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr $as2_uuid
> -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1],
> [ignore])
> -
> -    ovn-nbctl --wait=hv acl-del ls1
> -done
> -
> -# Gracefully terminate daemons
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ovn-controller restart])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One Logical Router: ro, with two logical switches sw1 and sw2.
> -# sw1 is for subnet 10.0.0.0/8
> -# sw2 is for subnet 20.0.0.0/8
> -# sw1 has a single port bound on hv1
> -# sw2 has a single port bound on hv2
> -
> -ovn-nbctl lr-add ro
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add sw2
> -
> -sw1_ro_mac=00:00:10:00:00:01
> -sw1_ro_ip=10.0.0.1
> -sw2_ro_mac=00:00:20:00:00:01
> -sw2_ro_ip=20.0.0.1
> -sw1_p1_mac=00:00:10:00:00:02
> -sw1_p1_ip=10.0.0.2
> -sw2_p1_mac=00:00:20:00:00:02
> -sw2_p1_ip=20.0.0.2
> -
> -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
> -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
> -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
> type=router \
> -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
> -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
> type=router \
> -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
> -
> -ovn-nbctl lsp-add sw1 sw1-p1 \
> --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
> -
> -ovn-nbctl lsp-add sw2 sw2-p1 \
> --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -OVN_POPULATE_ARP
> -
> -sleep 1
> -
> -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
> eth.dst==$sw1_ro_mac &&
> -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -
> -# Start by Sending the packet and make sure it makes it there as expected
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -# Expected packet has TTL decreased by 1
> -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
> -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
> -       udp && udp.src==53 && udp.dst==4369"
> -echo $expected | ovstest test-ovn expr-to-packets > expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -# Stop ovn-controller on hv2 with --restart flag
> -as hv2 ovs-appctl -t ovn-controller exit --restart
> -
> -# Now send the packet again. This time, it should still arrive
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -cat expected expected > expected2
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
> -
> -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
> -as hv2 start_daemon ovn-controller
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
> -ovn_start
> -
> -# Set up a switch with some switch ports of varying address types
> -ovn-nbctl ls-add sw1
> -ovn-nbctl set logical_switch sw1 other_config:subnet=192.168.0.0/24
> -
> -ovn-nbctl lsp-add sw1 sw1-p1
> -ovn-nbctl lsp-add sw1 sw1-p2
> -ovn-nbctl lsp-add sw1 sw1-p3
> -ovn-nbctl lsp-add sw1 sw1-p4
> -
> -ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1"
> "00:00:00:00:00:02 10.0.0.2 aef0::2"
> -ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
> -ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
> -ovn-nbctl lsp-set-addresses sw1-p4 "router"
> -ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
> -
> -ovn-nbctl list logical_switch_port
> -
> -# Now try to add duplicate addresses on a new port. These should all fail
> -ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> 10.0.0.1"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
> -])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> 10.0.0.2"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
> -])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> aef0::1"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
> -])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> aef0::2"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
> -])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> 192.168.0.2"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2
> -])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
> 192.168.0.3"], [1], [],
> -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3
> -])
> -
> -# Now try re-setting sw1-p1. This should succeed
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1
> aef0::1"])
> -
> -# Now create a new switch and try setting IP addresses the same as the
> -# first switch. This should succeed.
> -ovn-nbctl ls-add sw2
> -ovn-nbctl lsp-add sw2 sw2-p1
> -
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
> 10.0.0.1"])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
> 192.168.0.2"])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
> 192.168.0.3"])
> -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 aef0::1"])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- router - check packet length - icmp defrag])
> -AT_KEYWORDS([check packet length])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -ovn-nbctl ls-add sw0
> -ovn-nbctl lsp-add sw0 sw0-port1
> -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
> -
> -ovn-nbctl lr-add lr0
> -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
> -ovn-nbctl lsp-add sw0 sw0-lr0
> -ovn-nbctl lsp-set-type sw0-lr0 router
> -ovn-nbctl lsp-set-addresses sw0-lr0 router
> -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
> -
> -ovn-nbctl ls-add public
> -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
> -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> lsp-add public public-lr0
> -ovn-nbctl lsp-set-type public-lr0 router
> -ovn-nbctl lsp-set-addresses public-lr0 router
> -ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
> -
> -# localnet port
> -ovn-nbctl lsp-add public ln-public
> -ovn-nbctl lsp-set-type ln-public localnet
> -ovn-nbctl lsp-set-addresses ln-public unknown
> -ovn-nbctl lsp-set-options ln-public network_name=phys
> -
> -ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
> -ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -reset_pcap_file() {
> -     local iface=$1
> -     local pcap_file=$2
> -     ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> - options:rxq_pcap=dummy-rx.pcap
> -     rm -f ${pcap_file}*.pcap
> -     ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> - options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -ip_to_hex() {
> -     printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -test_ip_packet_larger() {
> -    local icmp_pmtu_reply_expected=$1
> -
> -    # Send ip packet from sw0-port1 to outside
> -    src_mac="505400000001" # sw-port1 mac
> -    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
> -    src_ip=`ip_to_hex 10 0 0 3`
> -    dst_ip=`ip_to_hex 172 168 0 3`
> -    # Set the packet length to 100.
> -    pkt_len=0064
> -    packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
> -    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
> -    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
> -    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
> -    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
> -    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
> -    packet=${packet}${orig_packet_l3}
> -
> -
> gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064
> -
> -    # If icmp_pmtu_reply_expected is 0, it means the packet is lesser than
> -    # the gateway mtu and should be delivered to the provider bridge via
> the
> -    # localnet port.
> -    # If icmp_pmtu_reply_expected is 1, it means the packet is larger than
> -    # the gateway mtu and ovn-controller should drop the packet and
> instead
> -    # generate ICMPv4  Destination Unreachable message with pmtu set to
> 42.
> -    if test $icmp_pmtu_reply_expected = 0; then
> -        # Packet to expect at br-phys.
> -        src_mac="000020201213"
> -        dst_mac="00000012af11"
> -        src_ip=`ip_to_hex 10 0 0 3`
> -        dst_ip=`ip_to_hex 172 168 0 3`
> -        expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
> -        expected=${expected}${src_ip}${dst_ip}0304000000000000
> -        expected=${expected}000000000000000000000000000000000000
> -        expected=${expected}000000000000000000000000000000000000
> -        expected=${expected}000000000000000000000000000000000000
> -        expected=${expected}000000000000000000000000000000000000
> -        echo $expected > br_phys_n1.expected
> -        echo $gw_ip_garp >> br_phys_n1.expected
> -    else
> -        # MTU would be 100 - 18 = 82 (hex 0052)
> -        mtu=0052
> -        src_ip=`ip_to_hex 10 0 0 1`
> -        dst_ip=`ip_to_hex 10 0 0 3`
> -        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip +
> payload))
> -        reply_pkt_len=0080
> -        ip_csum=bd91
> -
> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
> -        icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
> -        icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
> -        icmp_reply=${icmp_reply}${orig_packet_l3}
> -        echo $icmp_reply > hv1-vif1.expected
> -    fi
> -
> -    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
> -    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> -
> -    # Send packet from sw0-port1 to outside
> -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
> -
> -    if test $icmp_pmtu_reply_expected = 0; then
> -        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap], [br_phys_n1.expected])
> -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  >
> pkts
> -        # hv1/vif1-tx.pcap can receive the GARP packet generated by
> ovn-controller
> -        # for the gateway router port. So ignore this packet.
> -        cat pkts | grep -v $gw_ip_garp > packets
> -        AT_CHECK([cat packets], [0], [])
> -    else
> -        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
> -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> hv1/br-phys_n1-tx.pcap  > \
> -        pkts
> -        # hv1/br-phys_n1-tx.pcap can receive the GARP packet generated by
> ovn-controller
> -        # for the gateway router port. So ignore this packet.
> -        cat pkts | grep -v $gw_ip_garp > packets
> -        AT_CHECK([cat packets], [0], [])
> -    fi
> -}
> -
> -ovn-nbctl show
> -ovn-sbctl show
> -
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
> -| grep "check_pkt_larger" | wc -l], [0], [[0
> -]])
> -dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \
> -awk '{print $3}')
> -ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
> -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
> -
> -# Set the gateway mtu to 100. If the packet length is > 100,
> ovn-controller
> -# should send icmp host not reachable with pmtu set to 100.
> -ovn-nbctl --wait=hv set logical_router_port lr0-public
> options:gateway_mtu=100
> -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
> -OVS_WAIT_UNTIL([
> -    test `as hv1 ovs-ofctl dump-flows br-int | grep
> "check_pkt_larger(100)" | \
> -    wc -l` -eq 1
> -])
> -
> -icmp_reply_expected=1
> -test_ip_packet_larger $icmp_reply_expected
> -
> -# Set the gateway mtu to 500.
> -ovn-nbctl --wait=hv set logical_router_port lr0-public
> options:gateway_mtu=500
> -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
> -OVS_WAIT_UNTIL([
> -    test `as hv1 ovs-ofctl dump-flows br-int | grep
> "check_pkt_larger(500)" | \
> -    wc -l` -eq 1
> -])
> -
> -# Now the packet should be sent via the localnet port to br-phys.
> -icmp_reply_expected=0
> -test_ip_packet_larger $icmp_reply_expected
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IP packet buffering])
> -AT_KEYWORDS([ip-buffering])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# One LR lr0 that has switches sw0 (192.168.1.0/24) and
> -# sw1 (172.16.1.0/24) connected to it.
> -#
> -# Physical network:
> -# Tw0 hypervisors hv[12].
> -# hv1 hosts vif sw0-p0.
> -# hv1 hosts vif sw1-p0.
> -
> -send_icmp_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6
> ip_chksum=$7 data=$8
> -    shift 8
> -
> -    local ip_ttl=ff
> -    local ip_len=001c
> -    local
> packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data}
> -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
> -}
> -
> -send_icmp6_packet() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6
> ipv6_router=$7 exp_icmp_chksum=$8
> -    shift 8
> -
> -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
> -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
> -}
> -
> -get_arp_req() {
> -    local eth_src=$1 spa=$2 tpa=$3
> -    local
> request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa}
> -    echo $request
> -}
> -
> -send_arp_reply() {
> -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
> -    local
> request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa}
> -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
> -}
> -
> -send_na() {
> -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 dst_ip=$6
> -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
> -    local
> request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src}
> -
> -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
> -}
> -
> -get_nd() {
> -    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
> -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
> -
> request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src}
> -
> -    echo $request
> -}
> -
> -net_add n1
> -
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -
> -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
> -ovn-nbctl ls-add sw0
> -ovn-nbctl ls-add sw1
> -
> -ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24
> 2001:0:0:0:0:0:0:1/64
> -ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
> -    type=router options:router-port=sw0 \
> -    -- lsp-set-addresses rp-sw0 router
> -
> -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24
> 2002:0:0:0:0:0:0:1/64
> -ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
> -    type=router options:router-port=sw1 \
> -    -- lsp-set-addresses rp-sw1 router
> -
> -ovn-nbctl lsp-add sw0 sw0-p0 \
> -    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2 2001::2"
> -
> -ovn-nbctl lsp-add sw1 sw1-p0 \
> -    -- lsp-set-addresses sw1-p0 unknown
> -
> -OVN_POPULATE_ARP
> -ovn-nbctl --wait=hv sync
> -
> -ip_to_hex() {
> -    printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -src_mac=f00000010203
> -src_ip=$(ip_to_hex 192 168 1 2)
> -src_ip6=20010000000000000000000000000002
> -
> -router_mac0=000001010203
> -router_mac1=000002010203
> -router_ip=$(ip_to_hex 172 16 1 1)
> -router_ip6=20020000000000000000000000000001
> -
> -dst_mac=001122334455
> -dst_ip=$(ip_to_hex 172 16 1 10)
> -dst_ip6=20020000000000000000000000000010
> -
> -data=0800bee4391a0001
> -
> -send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 $data
> -send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
> -echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
> -echo
> "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}"
> >> expected
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -nd_ip=ff0200000000000000000001ff000010
> -ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
> -
> -send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
> -echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
> -echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >> expected
> -send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
> -
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- neighbor update on same HV])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# A public switch (pub) with a localnet port connected to two LRs (lr0
> and lr1)
> -# each with a distributed gateway port.
> -# Two VMs: lp0 on sw0 connected to lr0
> -#          lp1 on sw1 connected to lr1
> -#
> -# This test adds a floating IP to each VM so when they are bound to the
> same
> -# hypervisor, it checks that the GARP sent by ovn-controller causes the
> -# MAC_Binding entries to be updated properly on each logical router.
> -# It will also capture packets on the physical interface to make sure
> that the
> -# GARPs have been sent out to the external network as well.
> -
> -# Create logical switches
> -ovn-nbctl ls-add sw0
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add pub
> -
> -# Created localnet port on public switch
> -ovn-nbctl lsp-add pub ln-pub
> -ovn-nbctl lsp-set-type ln-pub localnet
> -ovn-nbctl lsp-set-addresses ln-pub unknown
> -ovn-nbctl lsp-set-options ln-pub network_name=phys
> -
> -# Create logical routers and connect them to public switch
> -ovn-nbctl create Logical_Router name=lr0
> -ovn-nbctl create Logical_Router name=lr1
> -
> -ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
> -ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
> -    type=router options:router-port=lr0-pub
> options:nat-addresses="router" addresses="router"
> -ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
> -ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
> -    type=router options:router-port=lr1-pub
> options:nat-addresses="router" addresses="router"
> -
> -ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
> -ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
> -
> -# Connect sw0 and sw1 to lr0 and lr1
> -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
> -ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0
> type=router \
> -    options:router-port=lr0-sw0 addresses="router"
> -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
> -ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1
> type=router \
> -    options:router-port=lr1-sw1 addresses="router"
> -
> -
> -# Add SNAT rules
> -ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
> -ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 172.24.4.1
> -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -
> -ovs-vsctl add-port br-int vif0 -- set Interface vif0
> external-ids:iface-id=lp0
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
> external-ids:iface-id=lp1
> -
> -ovn-nbctl lsp-add sw0 lp0
> -ovn-nbctl lsp-add sw1 lp1
> -ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
> -ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
> -
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
> -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
> -
> -# Create two floating IPs, one for each VIF
> -ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
> -ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
> -
> -# Check that the MAC_Binding entries have been properly created
> -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr0-pub"
> ip="172.24.4.200" | wc -l` -gt 0])
> -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr1-pub"
> ip="172.24.4.100" | wc -l` -gt 0])
> -
> -# Check that the GARPs went also to the external physical network
> -# Wait until at least 4 packets have arrived and copy them to a separate
> file as
> -# more GARPs are expected in the capture in order to avoid race
> conditions.
> -OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in"
> hv1/br-phys-tx.pcap | wc -l` -gt 4])
> -$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | head
> -n4 > hv1/br-phys-tx4.pcap
> -
> -# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
> -echo
> "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464"
> > expout
> -# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
> -echo
> "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc"
> >> expout
> -# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
> -echo
> "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8"
> >> expout
> -# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
> -echo
> "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd"
> >> expout
> -AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
> -#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
> -
> -OVN_CLEANUP([hv1])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ipam to non-ipam])
> -ovn_start
> -
> -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
> -ovn-nbctl ls-add sw0
> -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
> -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=
> 192.168.1.0/24
> -
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
> -    ["0a:00:00:a8:01:03 192.168.1.2"
> -])
> -
> -ovn-nbctl --wait=sb lsp-set-addresses p0 router
> -
> -ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
> -
> -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
> [[[]]
> -])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- ipam router ports])
> -ovn_start
> -
> -ovn-nbctl ls-add sw
> -ovn-nbctl set logical_switch sw other-config:subnet=192.168.1.0/24
> -
> -for i in 2 3 4; do
> -    ovn-nbctl lr-add ro$i
> -    ovn-nbctl lsp-add sw swp$i
> -    ovn-nbctl --wait=sb lsp-set-addresses swp$i "02:00:00:00:00:0$i
> dynamic"
> -    cidr=$(ovn-nbctl get logical_switch_port swp$i dynamic_addresses |cut
> -f2 -d' '|cut -f1 -d\")
> -    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 -- set
> logical_switch_port swp$i type=router options:router-port=rop$i
> addresses=router;
> -    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i networks],
> [0], [[["192.168.1.$i/24"]]
> -])
> -done
> -
> -ovn-nbctl list logical_switch_port
> -ovn-nbctl list logical_router_port
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- test transport zones])
> -ovn_start
> -
> -net_add n1
> -for i in 1 2 3 4 5; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.$i.1
> -done
> -
> -dnl Wait for the changes to be propagated
> -ovn-nbctl --wait=sb --timeout=3 sync
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -dnl Assert that each Chassis has a tunnel formed to every other Chassis
> -as hv1
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv2
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv3-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv3
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv4
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv5-0
> -]])
> -
> -as hv5
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv4-0
> -]])
> -
> -dnl Let's now add some Chassis to different transport zones
> -dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
> -dnl   should have tunnels formed between the other two Chassis (hv2 and
> hv3)
> -dnl
> -dnl * hv2: Will be part of one transport zone: tz1. It should have a
> tunnel
> -dnl   to hv1 but not to hv3
> -dnl
> -dnl * hv3: Will be part of one transport zone: tz2. It should have a
> tunnel
> -dnl   to hv1 but not to hv2
> -dnl
> -dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels
> -dnl   between themselves and remove the tunnels to other Chassis which now
> -dnl   belongs to some TZs
> -dnl
> -as hv1
> -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
> -
> -as hv2
> -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
> -
> -as hv3
> -ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
> -
> -dnl Wait for the changes to be propagated
> -ovn-nbctl --wait=sb --timeout=3 sync
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -as hv1
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv2-0
> -ovn-hv3-0
> -]])
> -
> -as hv2
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -]])
> -
> -as hv3
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -]])
> -
> -as hv4
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv5-0
> -]])
> -
> -as hv5
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv4-0
> -]])
> -
> -dnl Removing the transport zones should make all Chassis to create
> -dnl tunnels between every other Chassis again
> -for i in 1 2 3; do
> -    as hv$i
> -    ovs-vsctl remove open . external-ids ovn-transport-zones
> -done
> -
> -dnl Wait for the changes to be propagated
> -ovn-nbctl --wait=sb --timeout=3 sync
> -ovn-nbctl --wait=hv --timeout=3 sync
> -
> -as hv1
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv2
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv3-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv3
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv4-0
> -ovn-hv5-0
> -]])
> -
> -as hv4
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv5-0
> -]])
> -
> -as hv5
> -AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" |
> awk NF | sort], [0],
> -[[ovn-hv1-0
> -ovn-hv2-0
> -ovn-hv3-0
> -ovn-hv4-0
> -]])
> -
> -OVN_CLEANUP([hv1], [hv2], [hv3])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac])
> -ovn_start
> -
> -
> -# In this test cases we create 2 switches, all connected to same
> -# physical network (through br-phys on each HV). Each switch has
> -# 1 VIF. Each HV has 1 VIF port. The first digit
> -# of VIF port name indicates the hypervisor it is bound to, e.g.
> -# lp23 means VIF 3 on hv2.
> -#
> -# Each switch's VLAN tag and their logical switch ports are:
> -#   - ls1:
> -#       - tagged with VLAN 101
> -#       - ports: lp11
> -#   - ls2:
> -#       - tagged with VLAN 201
> -#       - ports: lp22
> -#
> -# Note: a localnet port is created for each switch to connect to
> -# physical network.
> -
> -for i in 1 2; do
> -    ls_name=ls$i
> -    ovn-nbctl ls-add $ls_name
> -    ln_port_name=ln$i
> -    if test $i -eq 1; then
> -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
> -    elif test $i -eq 2; then
> -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
> -    fi
> -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
> -    ovn-nbctl lsp-set-type $ln_port_name localnet
> -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
> -done
> -
> -# lsp_to_ls LSP
> -#
> -# Prints the name of the logical switch that contains LSP.
> -lsp_to_ls () {
> -    case $1 in dnl (
> -        lp?[[11]]) echo ls1 ;; dnl (
> -        lp?[[12]]) echo ls2 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -vif_to_ls () {
> -    case $1 in dnl (
> -        vif?[[11]]) echo ls1 ;; dnl (
> -        vif?[[12]]) echo ls2 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -hv_to_num () {
> -    case $1 in dnl (
> -        hv1) echo 1 ;; dnl (
> -        hv2) echo 2 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -vif_to_num () {
> -    case $1 in dnl (
> -        vif22) echo 22 ;; dnl (
> -        vif21) echo 21 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -vif_to_hv () {
> -    case $1 in dnl (
> -        vif[[1]]?) echo hv1 ;; dnl (
> -        vif[[2]]?) echo hv2 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -vif_to_lrp () {
> -    echo router-to-`vif_to_ls $1`
> -}
> -
> -hv_to_chassis_mac () {
> -     case $1 in dnl (
> -        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
> -        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
> -        *) AT_FAIL_IF([:]) ;;
> -    esac
> -}
> -
> -ip_to_hex() {
> -       printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -net_add n1
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> -    ovs-vsctl set open .
> external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    ovs-vsctl add-port br-int vif$i$i -- \
> -        set Interface vif$i$i external-ids:iface-id=lp$i$i \
> -                              options:tx_pcap=hv$i/vif$i$i-tx.pcap \
> -                              options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
> -                              ofport-request=$i$i
> -
> -    lsp_name=lp$i$i
> -    ls_name=$(lsp_to_ls $lsp_name)
> -
> -    ovn-nbctl lsp-add $ls_name $lsp_name
> -    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i
> 192.168.$i.$i"
> -    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
> -
> -    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
> -
> -done
> -
> -ovn-nbctl lr-add router
> -ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03 192.168.1.3/24
> -ovn-nbctl <http://192.168.1.3/24-ovn-nbctl> lrp-add router router-to-ls2
> 00:00:01:01:02:05 192.168.2.3/24
> -
> -ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port
> ls1-to-router type=router options:router-port=router-to-ls1 --
> lsp-set-addresses ls1-to-router router
> -ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port
> ls2-to-router type=router options:router-port=router-to-ls2 --
> lsp-set-addresses ls2-to-router router
> -
> -ovn-nbctl --wait=sb sync
> -#ovn-sbctl dump-flows
> -
> -ovn-nbctl show
> -ovn-sbctl show
> -
> -OVN_POPULATE_ARP
> -
> -test_ip() {
> -    # This packet has bad checksums but logical L3 routing doesn't check.
> -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
> -    local
> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
> -    shift; shift; shift; shift; shift
> -    hv=`vif_to_hv $inport`
> -    hv_num=`hv_to_num $hv`
> -    chassis_mac=`hv_to_chassis_mac $hv`
> -    as $hv ovs-appctl netdev-dummy/receive $inport $packet
> -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
> -    in_ls=`vif_to_ls $inport`
> -    in_lrp=`vif_to_lrp $inport`
> -    for outport; do
> -        out_ls=`vif_to_ls $outport`
> -        if test $in_ls = $out_ls; then
> -            # Ports on the same logical switch receive exactly the same
> packet.
> -            echo $packet
> -        else
> -            # Routing decrements TTL and updates source and dest MAC
> -            # (and checksum).
> -            outport_num=`vif_to_num $outport`
> -            out_lrp=`vif_to_lrp $outport`
> -            echo
> f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
> -        fi >> $outport.expected
> -    done
> -}
> -
> -# Dump a bunch of info helpful for debugging if there's a failure.
> -
> -echo "------ OVN dump ------"
> -ovn-nbctl show
> -ovn-sbctl show
> -
> -echo "------ hv1 dump ------"
> -as hv1 ovs-vsctl show
> -as hv1 ovs-vsctl list Open_Vswitch
> -
> -echo "------ hv2 dump ------"
> -as hv2 ovs-vsctl show
> -as hv2 ovs-vsctl list Open_Vswitch
> -
> -echo "Send traffic"
> -sip=`ip_to_hex 192 168 1 1`
> -dip=`ip_to_hex 192 168 2 2`
> -test_ip vif11 f00000000011  000001010203 $sip $dip vif22
> -
> -echo "----------- Post Traffic hv1 dump -----------"
> -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -as hv1 ovs-appctl fdb/show br-phys
> -
> -echo "----------- Post Traffic hv2 dump -----------"
> -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
> -as hv2 ovs-appctl fdb/show br-phys
> -
> -OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
> -
> -OVN_CLEANUP([hv1],[hv2])
> -
> -AT_CLEANUP
> -
> -# Run ovn-nbctl in daemon mode, change to a backup database and verify
> that
> -# an insert operation is not allowed.
> -AT_SETUP([ovn -- can't write to a backup database server instance])
> -ovn_start
> -on_exit 'kill $(cat ovn-nbctl.pid)'
> -export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
> -
> -AT_CHECK([ovn-nbctl ls-add sw0])
> -as ovn-nb
> -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status | grep
> active | wc -l], [0], [1
> -])
> -ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server tcp:
> 192.0.2.2:6641
> -ovs-appctl -t ovsdb-server ovsdb-server/connect-active-ovsdb-server
> -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status | grep -c
> backup], [0], [1
> -])
> -AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
> -[ovn-nbctl: transaction error: {"details":"insert operation not allowed
> when database server is in read only mode","error":"not allowed"}
> -])
> -
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- controller event])
> -AT_KEYWORDS([ovn_controller_event])
> -ovn_start
> -
> -# Create hypervisors hv[12].
> -# Add vif1[12] to hv1, vif2[12] to hv2
> -# Add all of the vifs to a single logical switch sw0.
> -
> -net_add n1
> -ovn-nbctl ls-add sw0
> -for i in 1 2; do
> -    sim_add hv$i
> -    as hv$i
> -    ovs-vsctl add-br br-phys
> -    ovn_attach n1 br-phys 192.168.0.$i
> -
> -    for j in 1 2; do
> -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
> -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
> 192.168.1.$i$j"
> -
> -        ovs-vsctl -- add-port br-int vif$i$j -- \
> -                set interface vif$i$j \
> -                external-ids:iface-id=sw0-p$i$j \
> -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
> -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
> -                ofport-request=$i$j
> -    done
> -done
> -
> -ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
> -ovn-nbctl lb-add lb0 192.168.1.100:80 ""
> -ovn-nbctl ls-lb-add sw0 lb0
> -uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer name=lb0)
> -
> -OVN_POPULATE_ARP
> -ovn-nbctl --timeout=3 --wait=hv sync
> -ovn-sbctl lflow-list
> -as hv1 ovs-ofctl dump-flows br-int
> -
> -packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 &&
> eth.dst==00:00:00:00:00:21 &&
> -       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 &&
> ip4.dst==192.168.1.100 &&
> -       tcp && tcp.src==10000 && tcp.dst==80"
> -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
> -
> -ovn-sbctl list controller_event
> -uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
> -AT_CHECK([ovn-sbctl get controller_event $uuid event_type], [0], [dnl
> -empty_lb_backends
> -])
> -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip], [0], [dnl
> -"192.168.1.100:80"
> -])
> -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:protocol], [0],
> [dnl
> -tcp
> -])
> -AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid
> event_info:load_balancer], [0], [dnl
> -"$uuid_lb"
> -])
> -AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], [dnl
> -1
> -])
> -
> -OVN_CLEANUP([hv1], [hv2])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- IGMP snoop/querier])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
> -ovn_start
> -
> -# Logical network:
> -# Two independent logical switches (sw1 and sw2).
> -# sw1:
> -#   - subnet 10.0.0.0/8
> -#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
> -#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
> -# sw2:
> -#   - subnet 20.0.0.0/8
> -#   - 1 port bound on hv1 (sw2-p1)
> -#   - 1 port bound on hv2 (sw2-p2)
> -#   - IGMP Querier from 20.0.0.254
> -
> -reset_pcap_file() {
> -    local iface=$1
> -    local pcap_file=$2
> -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> -options:rxq_pcap=dummy-rx.pcap
> -    rm -f ${pcap_file}*.pcap
> -    ovs-vsctl -- set Interface $iface
> options:tx_pcap=${pcap_file}-tx.pcap \
> -options:rxq_pcap=${pcap_file}-rx.pcap
> -}
> -
> -ip_to_hex() {
> -     printf "%02x%02x%02x%02x" "$@"
> -}
> -
> -#
> -# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP REC_TYPE
> -#                     IGMP_CSUM OUTFILE
> -#
> -# This shell function causes an IGMPv3 report to be received on INPORT of
> HV.
> -# The packet's content has Ethernet destination 01:00:5E:00:00:22 and
> source
> -# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
> -# GROUP is the IP multicast group to be joined/to leave (based on
> REC_TYPE).
> -# REC_TYPE == 04: join GROUP
> -# REC_TYPE == 03: leave GROUP
> -# The packet hexdump is also stored in OUTFILE.
> -#
> -send_igmp_v3_report() {
> -    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 group=$6
> -    local rec_type=$7 igmp_chksum=$8 outfile=$9
> -
> -    local eth_dst=01005e000016
> -    local ip_dst=$(ip_to_hex 224 0 0 22)
> -    local ip_ttl=01
> -    local ip_ra_opt=94040000
> -
> -    local igmp_type=2200
> -    local num_rec=00000001
> -    local aux_dlen=00
> -    local num_src=0000
> -
> -    local eth=${eth_dst}${eth_src}0800
> -    local
> ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt}
> -    local
> igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group}
> -    local packet=${eth}${ip}${igmp}
> -
> -    echo ${packet} >> ${outfile}
> -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
> -}
> -
> -#
> -# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
> -#
> -# This shell function builds an IGMPv3 general query from ETH_SRC and
> IP_SRC
> -# and stores the hexdump of the packet in OUTFILE.
> -#
> -store_igmp_v3_query() {
> -    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
> -
> -    local eth_dst=01005e000001
> -    local ip_dst=$(ip_to_hex 224 0 0 1)
> -    local ip_ttl=01
> -    local igmp_type=11
> -    local max_resp=0a
> -    local igmp_chksum=eeeb
> -    local addr=00000000
> -
> -    local eth=${eth_dst}${eth_src}0800
> -    local ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
> -    local igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
> -    local packet=${eth}${ip}${igmp}
> -
> -    echo ${packet} >> ${outfile}
> -}
> -
> -#
> -# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST IP_LEN
> -#    IP_PROTO DATA OUTFILE
> -#
> -# This shell function causes an IP multicast packet to be received on
> INPORT
> -# of HV.
> -# The hexdump of the packet is stored in OUTFILE.
> -#
> -send_ip_multicast_pkt() {
> -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 ip_dst=$6
> -    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} outfile=${11}
> -
> -    local ip_ttl=20
> -
> -    local eth=${eth_dst}${eth_src}0800
> -    local
> ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst}
> -    local packet=${eth}${ip}${data}
> -
> -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
> -    echo ${packet} >> ${outfile}
> -}
> -
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add sw2
> -
> -ovn-nbctl lsp-add sw1 sw1-p11
> -ovn-nbctl lsp-add sw1 sw1-p12
> -ovn-nbctl lsp-add sw1 sw1-p21
> -ovn-nbctl lsp-add sw1 sw1-p22
> -ovn-nbctl lsp-add sw2 sw2-p1
> -ovn-nbctl lsp-add sw2 sw2-p2
> -
> -net_add n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl -- add-port br-int hv1-vif1 -- \
> -    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
> -    options:tx_pcap=hv1/vif1-tx.pcap \
> -    options:rxq_pcap=hv1/vif1-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv1-vif2 -- \
> -    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
> -    options:tx_pcap=hv1/vif2-tx.pcap \
> -    options:rxq_pcap=hv1/vif2-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv1-vif3 -- \
> -    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
> -    options:tx_pcap=hv1/vif3-tx.pcap \
> -    options:rxq_pcap=hv1/vif3-rx.pcap \
> -    ofport-request=1
> -
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl -- add-port br-int hv2-vif1 -- \
> -    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
> -    options:tx_pcap=hv2/vif1-tx.pcap \
> -    options:rxq_pcap=hv2/vif1-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv2-vif2 -- \
> -    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
> -    options:tx_pcap=hv2/vif2-tx.pcap \
> -    options:rxq_pcap=hv2/vif2-rx.pcap \
> -    ofport-request=1
> -ovs-vsctl -- add-port br-int hv2-vif3 -- \
> -    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
> -    options:tx_pcap=hv2/vif3-tx.pcap \
> -    options:rxq_pcap=hv2/vif3-rx.pcap \
> -    ofport-request=1
> -
> -OVN_POPULATE_ARP
> -
> -# Enable IGMP snooping on sw1.
> -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
> -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
> -
> -# No IGMP query should be generated by sw1 (mcast_querier="false").
> -truncate -s 0 expected
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
> -
> -ovn-nbctl --wait=hv sync
> -
> -# Inject IGMP Join for 239.0.1.68 on sw1-p11.
> -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 IGMP Join for 239.0.1.68 on sw1-p21.
> -send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0 2) f9f9 \
> -    $(ip_to_hex 239 0 1 68) 04 e9b9 \
> -    /dev/null
> -
> -# Check that the IGMP Group is learned on both hv.
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    test "${total_entries}" = "2"
> -])
> -
> -# Send traffic and make sure it gets forwarded only on the two ports that
> -# joined.
> -truncate -s 0 expected
> -truncate -s 0 expected_empty
> -send_ip_multicast_pkt hv1-vif2 hv1 \
> -    000000000001 01005e000144 \
> -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
> -    e518e518000a3b3a0000 \
> -    expected
> -
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
> -
> -# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
> -send_igmp_v3_report hv1-vif1 hv1 \
> -    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
> -    $(ip_to_hex 239 0 1 68) 03 eab9 \
> -    /dev/null
> -
> -# Check IGMP_Group table on both HV.
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    test "${total_entries}" = "1"
> -])
> -
> -# Send traffic traffic and make sure it gets forwarded only on the port
> that
> -# joined.
> -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
> -as hv2 reset_pcap_file hv2-vif1 hv2/vif1
> -truncate -s 0 expected
> -truncate -s 0 expected_empty
> -send_ip_multicast_pkt hv1-vif2 hv1 \
> -    000000000001 01005e000144 \
> -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
> -    e518e518000a3b3a0000 \
> -    expected
> -
> -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
> -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
> -
> -# Flush IGMP groups.
> -ovn-sbctl ip-multicast-flush sw1
> -ovn-nbctl --wait=hv -t 3 sync
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    test "${total_entries}" = "0"
> -])
> -
> -# Enable IGMP snooping and querier on sw2 and set query interval to
> minimum.
> -ovn-nbctl set Logical_Switch sw2 \
> -    other_config:mcast_snoop="true" \
> -    other_config:mcast_querier="true" \
> -    other_config:mcast_query_interval=1 \
> -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
> -    other_config:mcast_ip4_src="20.0.0.254"
> -
> -# Wait for 1 query interval (1 sec) and check that two queries are
> generated.
> -truncate -s 0 expected
> -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
> -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
> -
> -sleep 1
> -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
> -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
> -
> -OVN_CLEANUP([hv1], [hv2])
> -AT_CLEANUP
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> deleted file mode 100644
> index f88ad31..0000000
> --- a/tests/system-ovn.at
> +++ /dev/null
> @@ -1,1667 +0,0 @@
> -AT_BANNER([system-ovn])
> -
> -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT])
> -AT_KEYWORDS([ovnnat])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
> -# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24)
> connected
> -# to it.  R2 is a gateway router on which we add NAT rules.
> -#
> -#    foo -- R1 -- join - R2 -- alice
> -#           |
> -#    bar ----
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Static routes.
> -ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
> -"192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
> -
> -# Add a DNAT rule.
> -ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
> -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
> -
> -# Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
> -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
> -
> -# wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=30.0.0.1)'])
> -
> -# 'alice1' should be able to ping 'foo1' directly.
> -NS_CHECK_EXEC([alice1], [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
> -])
> -
> -# North-South DNAT: 'alice1' should also be able to ping 'foo1' via
> 30.0.0.2
> -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# Check conntrack entries.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
> -# from 30.0.0.1
> -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# Add static routes to handle east-west NAT.
> -ovn-nbctl lr-route-add R1 30.0.0.0/24 20.0.0.2
> -
> -# wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -
> -# Flush conntrack entries for easier output parsing of next test.
> -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> -
> -# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' receives it.
> -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# As we have a static route that sends all packets with destination
> -# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to
> 192.168.1.2
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1, the
> source is
> -# SNATted and 'foo1' receives it.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy SNAT])
> -AT_KEYWORDS([ovnnat])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) connected
> -# to it.  R2 has alice (172.16.1.0/24) connected to it.
> -# R2 is a gateway router on which we add NAT rules.
> -#
> -#    foo -- R1 -- join - R2 -- alice
> -
> -ovn-nbctl lr-add R1
> -ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add join
> -
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -
> -# Connect foo to R1
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect alice to R2
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Static routes.
> -ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.1.2 \
> -    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
> -
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
> -
> -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives traffic
> -# from 172.16.1.1
> -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
> -AT_KEYWORDS([ovnnat])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
> -# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24)
> connected
> -# to it.  R3 has bob (172.16.1.0/24) connected to it. Note how both
> alice and
> -# bob have the same subnet behind it.  We are trying to simulate external
> -# network via those 2 switches. In real world the switch ports of these
> -# switches will have addresses set as "unknown" to make them learning
> switches.
> -# Or those switches will be "localnet" ones.
> -#
> -#    foo -- R1 -- join - R2 -- alice
> -#           |          |
> -#    bar ----          - R3 --- bob
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
> -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add bob
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect bob to R3
> -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
> -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
> -    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Connect R3 to join
> -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
> -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
> -    type=router options:router-port=R3_join
> addresses='"00:00:04:01:02:05"'
> -
> -# Install static routes with source ip address as the policy for routing.
> -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via
> R3.
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
> -
> -# Static routes.
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
> -
> -# For gateway routers R2 and R3, set a force SNAT rule.
> -ovn-nbctl set logical_router R2 options:dnat_force_snat_ip=20.0.0.2
> -ovn-nbctl set logical_router R3 options:dnat_force_snat_ip=20.0.0.3
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24", "f0:00:00:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
> -"192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
> -
> -# Logical port 'bob1' in switch 'bob'.
> -ADD_NAMESPACES(bob1)
> -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24", "f0:00:00:01:02:06", \
> -         "172.16.1.2")
> -ovn-nbctl lsp-add bob bob1 \
> --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
> -
> -# Router R2
> -# Add a DNAT rule.
> -ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
> -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
> -
> -# Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.1.2 \
> -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
> -
> -# Router R3
> -# Add a DNAT rule.
> -ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
> -    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
> -
> -# Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
> -    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
> -
> -# wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=30.0.0.4)'])
> -
> -# North-South DNAT: 'alice1' should be able to ping 'foo1' via 30.0.0.2
> -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# Check conntrack entries.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# But foo1 should receive traffic from 20.0.0.2
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# North-South DNAT: 'bob1' should be able to ping 'foo1' via 30.0.0.3
> -NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 | FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# Check conntrack entries.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# But foo1 should receive traffic from 20.0.0.3
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.3) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives traffic
> -# from 30.0.0.4
> -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.4) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives traffic
> -# from 30.0.0.1
> -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- load-balancing])
> -AT_KEYWORDS([ovnlb])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# 2 logical switches "foo" (192.168.1.0/24) and "bar" (172.16.1.0/24)
> -# connected to a router R1.
> -# foo has foo1 to act as a client.
> -# bar has bar1, bar2, bar3 to act as servers.
> -#
> -# Loadbalancer VIPs in 30.0.0.0/24 network.
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Create logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24", "f0:00:0f:01:02:03", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
> -
> -ADD_NAMESPACES(bar2)
> -ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24", "f0:00:0f:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add bar bar2 \
> --- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
> -
> -ADD_NAMESPACES(bar3)
> -ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24", "f0:00:0f:01:02:05", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add bar bar3 \
> --- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
> -
> -# Config OVN load-balancer with a VIP.
> -uuid=`ovn-nbctl  create load_balancer
> vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
> -ovn-nbctl set logical_switch foo load_balancer=$uuid
> -
> -# Create another load-balancer with another VIP.
> -uuid=`ovn-nbctl create load_balancer
> vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
> -ovn-nbctl add logical_switch foo load_balancer $uuid
> -
> -# Config OVN load-balancer with another VIP (this time with ports).
> -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"172.16.1.2:80,
> 172.16.1.3:80,172.16.1.4:80"'
> -
> -# Wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
> -grep 'nat(dst=172.16.1.4:80)'])
> -
> -# Start webservers in 'bar1', 'bar2' and 'bar3'.
> -OVS_START_L7([bar1], [http])
> -OVS_START_L7([bar2], [http])
> -OVS_START_L7([bar3], [http])
> -
> -dnl Should work with the virtual IP 30.0.0.1 address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v
> -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Should work with the virtual IP 30.0.0.3 address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1 --retry-connrefused -v
> -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Test load-balancing that includes L4 ports in NAT.
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1
> --retry-connrefused -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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"])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- load-balancing - same subnet.])
> -AT_KEYWORDS([ovnlb])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# 1 logical switch "foo" (192.168.1.0/24) connected to router R1.
> -# foo has foo1, foo2, foo3, foo4 as logical ports.
> -#
> -# Loadbalancer VIPs in 30.0.0.0/24 network. Router is needed for default
> -# gateway. We will test load-balancing with foo1 as a client and foo2,
> foo3 and
> -# foo4 as servers.
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl ls-add foo
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch 'foo'.
> -ADD_NAMESPACES(foo1, foo2, foo3, foo4)
> -for i in `seq 1 4`; do
> -    j=`expr $i + 1`
> -    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24",
> "f0:00:00:01:02:0$j", \
> -             "192.168.1.1")
> -    ovn-nbctl lsp-add foo foo$i \
> -        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 192.168.1.$j"
> -done
> -
> -# Config OVN load-balancer with a VIP.
> -uuid=`ovn-nbctl  create load_balancer
> vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
> -ovn-nbctl set logical_switch foo load_balancer=$uuid
> -
> -# Config OVN load-balancer with another VIP (this time with ports).
> -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.3:80
> ,192.168.1.4:80,192.168.1.5:80"'
> -
> -# Wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
> -grep 'nat(dst=192.168.1.5:80)'])
> -
> -# Start webservers in 'foo2', 'foo3' and 'foo4'.
> -OVS_START_L7([foo2], [http])
> -OVS_START_L7([foo3], [http])
> -OVS_START_L7([foo4], [http])
> -
> -dnl Should work with the virtual IP address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v
> -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Test load-balancing that includes L4 ports in NAT.
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1
> --retry-connrefused -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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"])
> -AT_CLEANUP
> -
> -AT_SETUP([ovn -- load balancing in gateway router])
> -AT_KEYWORDS([ovnlb])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Two LRs - R1 and R2 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
> -# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24)
> connected
> -# to it.  R2 is a gateway router on which we add load-balancing rules.
> -#
> -#    foo -- R1 -- join - R2 -- alice
> -#           |
> -#    bar ----
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Static routes.
> -ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
> -"192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
> -
> -# Config OVN load-balancer with a VIP.
> -uuid=`ovn-nbctl  create load_balancer
> vips:30.0.0.1="192.168.1.2,192.168.2.2"`
> -ovn-nbctl set logical_router R2 load_balancer=$uuid
> -
> -# Config OVN load-balancer with another VIP (this time with ports).
> -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80
> ,192.168.2.2:80"'
> -
> -# Add SNAT rule to make sure that Load-balancing still works with a SNAT
> rule.
> -ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
> -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
> -
> -
> -# Wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
> -grep 'nat(dst=192.168.2.2:80)'])
> -
> -# Start webservers in 'foo1', 'bar1'.
> -OVS_START_L7([foo1], [http])
> -OVS_START_L7([bar1], [http])
> -
> -dnl Should work with the virtual IP address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused
> -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Test load-balancing that includes L4 ports in NAT.
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1
> --retry-connrefused -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- multiple gateway routers, load-balancing])
> -AT_KEYWORDS([ovnlb])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
> -# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
> -# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24)
> connected
> -# to it.  R3 has bob (172.16.1.0/24) connected to it. Note how both
> alice and
> -# bob have the same subnet behind it.  We are trying to simulate external
> -# network via those 2 switches. In real world the switch ports of these
> -# switches will have addresses set as "unknown" to make them learning
> switches.
> -# Or those switches will be "localnet" ones.
> -#
> -#    foo -- R1 -- join - R2 -- alice
> -#           |          |
> -#    bar ----          - R3 --- bob
> -
> -ovn-nbctl create Logical_Router name=R1
> -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
> -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -ovn-nbctl ls-add bob
> -ovn-nbctl ls-add join
> -
> -# Connect foo to R1
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> -
> -# Connect bar to R1
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
> -
> -# Connect alice to R2
> -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> -
> -# Connect bob to R3
> -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
> -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
> -    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
> -
> -# Connect R1 to join
> -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> -    type=router options:router-port=R1_join
> addresses='"00:00:04:01:02:03"'
> -
> -# Connect R2 to join
> -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> -    type=router options:router-port=R2_join
> addresses='"00:00:04:01:02:04"'
> -
> -# Connect R3 to join
> -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
> -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
> -    type=router options:router-port=R3_join
> addresses='"00:00:04:01:02:05"'
> -
> -# Install static routes with source ip address as the policy for routing.
> -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via
> R3.
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
> -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
> -
> -# Static routes.
> -ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> -ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
> -
> -# For gateway routers R2 and R3, set a force SNAT rule.
> -ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
> -ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24", "f0:00:00:01:02:04", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
> -"192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
> -
> -# Logical port 'bob1' in switch 'bob'.
> -ADD_NAMESPACES(bob1)
> -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24", "f0:00:00:01:02:06", \
> -         "172.16.1.2")
> -ovn-nbctl lsp-add bob bob1 \
> --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
> -
> -# Config OVN load-balancer with a VIP.
> -uuid=`ovn-nbctl  create load_balancer
> vips:30.0.0.1="192.168.1.2,192.168.2.2"`
> -ovn-nbctl set logical_router R2 load_balancer=$uuid
> -ovn-nbctl set logical_router R3 load_balancer=$uuid
> -
> -# Wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
> -grep 'nat(dst=192.168.2.2)'])
> -
> -# Start webservers in 'foo1', 'bar1'.
> -OVS_START_L7([foo1], [http])
> -OVS_START_L7([bar1], [http])
> -
> -dnl Should work with the virtual IP address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused
> -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Force SNAT should have worked.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- load balancing in router with gateway router port])
> -AT_KEYWORDS([ovnlb])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
> -# and alice (172.16.1.0/24) connected to it.  The port between R1 and
> -# alice is the router gateway port where the R1 LB rules are applied.
> -#
> -#    foo -- R1 -- bar
> -#           |
> -#    alice ----
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
> -
> -# Connect foo to R1
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect bar to R1
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar \
> -    -- lsp-set-addresses rp-bar router
> -
> -# Connect alice to R1
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'foo2' in switch 'foo'.
> -ADD_NAMESPACES(foo2)
> -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo2 \
> --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
> -         "192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
> -
> -# Config OVN load-balancer with a VIP.
> -uuid=`ovn-nbctl  create load_balancer
> vips:172.16.1.10="192.168.1.2,192.168.2.2"`
> -ovn-nbctl set logical_router R1 load_balancer=$uuid
> -
> -# Config OVN load-balancer with another VIP (this time with ports).
> -ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000"'='"
> 192.168.1.2:80,192.168.2.2:80"'
> -
> -# Wait for ovn-controller to catch up.
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
> -grep 'nat(dst=192.168.2.2:80)'])
> -
> -# Start webservers in 'foo1', 'bar1'.
> -OVS_START_L7([foo1], [http])
> -OVS_START_L7([bar1], [http])
> -
> -dnl Should work with the virtual IP address through NAT
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1
> --retry-connrefused -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -dnl Test load-balancing that includes L4 ports in NAT.
> -for i in `seq 1 20`; do
> -    echo Request $i
> -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1
> --retry-connrefused -v -o wget$i.log])
> -done
> -
> -dnl Each server should have at least one connection.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>
> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
> -AT_KEYWORDS([ovnnat])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
> -# and alice (172.16.1.0/24) connected to it.  The port between R1 and
> -# alice is the router gateway port where the R1 NAT rules are applied.
> -#
> -#    foo -- R1 -- alice
> -#           |
> -#    bar ----
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
> -
> -# Connect foo to R1
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect bar to R1
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar \
> -    -- lsp-set-addresses rp-bar router
> -
> -# Connect alice to R1
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'foo2' in switch 'foo'.
> -ADD_NAMESPACES(foo2)
> -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo2 \
> --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
> -         "192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
> -
> -# Add DNAT rules
> -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2
> foo1 00:00:02:02:03:04])
> -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.1.3
> foo2 00:00:02:02:03:05])
> -
> -# Add a SNAT rule
> -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
> -
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
> -
> -# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
> -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that DNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic
> -# from 172.16.1.4
> -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> -
> -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
> -# from 172.16.1.1
> -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that SNAT indeed happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
> -AT_KEYWORDS([ovnnat])
> -
> -CHECK_CONNTRACK()
> -CHECK_CONNTRACK_NAT()
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
> -# and alice (172.16.1.0/24) connected to it.  The port between R1 and
> -# alice is the router gateway port where the R1 NAT rules are applied.
> -#
> -#    foo -- R1 -- alice
> -#           |
> -#    bar ----
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add foo
> -ovn-nbctl ls-add bar
> -ovn-nbctl ls-add alice
> -
> -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
> -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
> -
> -# Connect foo to R1
> -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> -    type=router options:router-port=foo \
> -    -- lsp-set-addresses rp-foo router
> -
> -# Connect bar to R1
> -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
> -    type=router options:router-port=bar \
> -    -- lsp-set-addresses rp-bar router
> -
> -# Connect alice to R1
> -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> -    type=router options:router-port=alice \
> -    -- lsp-set-addresses rp-alice router
> -
> -# Logical port 'foo1' in switch 'foo'.
> -ADD_NAMESPACES(foo1)
> -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo1 \
> --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> -
> -# Logical port 'foo2' in switch 'foo'.
> -ADD_NAMESPACES(foo2)
> -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add foo foo2 \
> --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
> -
> -# Logical port 'bar1' in switch 'bar'.
> -ADD_NAMESPACES(bar1)
> -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
> -         "192.168.2.1")
> -ovn-nbctl lsp-add bar bar1 \
> --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
> -
> -# Logical port 'alice1' in switch 'alice'.
> -ADD_NAMESPACES(alice1)
> -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
> -         "172.16.1.1")
> -ovn-nbctl lsp-add alice alice1 \
> --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
> -
> -# Add DNAT rules
> -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2
> foo1 00:00:02:02:03:04])
> -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.2.2
> bar1 00:00:02:02:03:05])
> -
> -# Add a SNAT rule
> -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
> -
> -ovn-nbctl --wait=hv sync
> -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
> -
> -echo "------ hv dump ------"
> -ovs-ofctl show br-int
> -ovs-ofctl dump-flows br-int
> -echo "---------------------"
> -
> -# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
> -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that no NAT happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
> -])
> -
> -# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
> -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that no NAT happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
> -])
> -
> -# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
> -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# We verify that no NAT happened via 'dump-conntrack' command.
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
> -])
> -
> -# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
> -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# Check conntrack entries.  First SNAT of 'foo1' address happens.
> -# Then DNAT of 'bar1' address happens (listed first below).
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>
> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> -
> -# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
> -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
> FORMAT_PING], \
> -[0], [dnl
> -3 packets transmitted, 3 received, 0% packet loss, time 0ms
> -])
> -
> -# Check conntrack entries.  First SNAT of 'foo2' address happens.
> -# Then DNAT of 'bar1' address happens (listed first below).
> -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
> -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>
> -icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> -
> -AT_SETUP([ovn -- 2 LSs IGMP])
> -AT_KEYWORDS([ovnigmp])
> -
> -ovn_start
> -
> -OVS_TRAFFIC_VSWITCHD_START()
> -ADD_BR([br-int])
> -
> -# Set external-ids in br-int needed for ovn-controller
> -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.0.0.1 \
> -        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> -
> -# Start ovn-controller
> -start_daemon ovn-controller
> -
> -# Logical network:
> -# Two independent logical switches (sw1 and sw2).
> -# sw1:
> -#   - subnet 10.0.0.0/8
> -#   - 2 ports (sw1-p1 - sw1-p2)
> -# sw2:
> -#   - subnet 20.0.0.0/8
> -#   - 2 port (sw2-p1 - sw2-p2)
> -#   - IGMP Querier from 20.0.0.254
> -
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add sw2
> -
> -for i in `seq 1 2`
> -do
> -    ADD_NAMESPACES(sw1-p$i)
> -    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24",
> "00:00:00:00:01:0$i", \
> -            "10.0.0.254")
> -    ovn-nbctl lsp-add sw1 sw1-p$i \
> -        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 10.0.0.$i"
> -done
> -
> -for i in `seq 1 2`
> -do
> -    ADD_NAMESPACES(sw2-p$i)
> -    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24",
> "00:00:00:00:02:0$i", \
> -            "20.0.0.254")
> -    ovn-nbctl lsp-add sw2 sw2-p$i \
> -        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 20.0.0.$i"
> -done
> -
> -# Enable IGMP snooping on sw1.
> -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
> -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
> -
> -# Inject IGMP Join for 239.0.1.68 on sw1-p1.
> -NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32 autojoin],
> [0])
> -
> -# Inject IGMP Join for 239.0.1.68 on sw1-p2
> -NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32 autojoin],
> [0])
> -
> -# Check that the IGMP Group is learned.
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d ":" | wc
> -w`
> -    test "${total_entries}" = "1"
> -    test "${ports}" = "2"
> -])
> -
> -# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
> -NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32], [0])
> -
> -# Check that only one port is left in the group.
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d ":" | wc
> -w`
> -    test "${total_entries}" = "1"
> -    test "${ports}" = "1"
> -])
> -
> -# Flush IGMP groups.
> -ovn-sbctl ip-multicast-flush sw1
> -ovn-nbctl --wait=hv -t 3 sync
> -OVS_WAIT_UNTIL([
> -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
> -    test "${total_entries}" = "0"
> -])
> -
> -# Enable IGMP snooping and querier on sw2 and set query interval to
> minimum.
> -ovn-nbctl set Logical_Switch sw2 \
> -    other_config:mcast_snoop="true" \
> -    other_config:mcast_querier="true" \
> -    other_config:mcast_query_interval=1 \
> -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
> -    other_config:mcast_ip4_src="20.0.0.254"
> -
> -# Check that queries are generated.
> -NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp > sw2-p1.pcap &])
> -
> -OVS_WAIT_UNTIL([
> -    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
> -    test "${total_queries}" = "2"
> -])
> -
> -OVS_APP_EXIT_AND_WAIT([ovn-controller])
> -
> -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
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> deleted file mode 100644
> index 0b9e824..0000000
> --- a/tests/test-ovn.c
> +++ /dev/null
> @@ -1,1584 +0,0 @@
> -/*
> - * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at:
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -#include <config.h>
> -#include <errno.h>
> -#include <getopt.h>
> -#include <sys/wait.h>
> -
> -#include "command-line.h"
> -#include "dp-packet.h"
> -#include "fatal-signal.h"
> -#include "flow.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "openvswitch/match.h"
> -#include "openvswitch/ofp-actions.h"
> -#include "openvswitch/ofpbuf.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/actions.h"
> -#include "ovn/expr.h"
> -#include "ovn/lex.h"
> -#include "ovn/logical-fields.h"
> -#include "ovn/lib/ovn-l7.h"
> -#include "ovn/lib/extend-table.h"
> -#include "ovs-thread.h"
> -#include "ovstest.h"
> -#include "openvswitch/shash.h"
> -#include "simap.h"
> -#include "util.h"
> -
> -/* --relops: Bitmap of the relational operators to test, in exhaustive
> test. */
> -static unsigned int test_relops;
> -
> -/* --nvars: Number of numeric variables to test, in exhaustive test. */
> -static int test_nvars = 2;
> -
> -/* --svars: Number of string variables to test, in exhaustive test. */
> -static int test_svars = 2;
> -
> -/* --bits: Number of bits per variable, in exhaustive test. */
> -static int test_bits = 3;
> -
> -/* --operation: The operation to test, in exhaustive test. */
> -static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW } operation
> -    = OP_FLOW;
> -
> -/* --parallel: Number of parallel processes to use in test. */
> -static int test_parallel = 1;
> -
> -/* -m, --more: Message verbosity */
> -static int verbosity;
> -
> -static void
> -compare_token(const struct lex_token *a, const struct lex_token *b)
> -{
> -    if (a->type != b->type) {
> -        fprintf(stderr, "type differs: %d -> %d\n", a->type, b->type);
> -        return;
> -    }
> -
> -    if (!((a->s && b->s && !strcmp(a->s, b->s))
> -          || (!a->s && !b->s))) {
> -        fprintf(stderr, "string differs: %s -> %s\n",
> -                a->s ? a->s : "(null)",
> -                b->s ? b->s : "(null)");
> -        return;
> -    }
> -
> -    if (a->type == LEX_T_INTEGER || a->type == LEX_T_MASKED_INTEGER) {
> -        if (memcmp(&a->value, &b->value, sizeof a->value)) {
> -            fprintf(stderr, "value differs\n");
> -            return;
> -        }
> -
> -        if (a->type == LEX_T_MASKED_INTEGER
> -            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
> -            fprintf(stderr, "mask differs\n");
> -            return;
> -        }
> -
> -        if (a->format != b->format
> -            && !(a->format == LEX_F_HEXADECIMAL
> -                 && b->format == LEX_F_DECIMAL
> -                 && a->value.integer == 0)) {
> -            fprintf(stderr, "format differs: %d -> %d\n",
> -                    a->format, b->format);
> -        }
> -    }
> -}
> -
> -static void
> -test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    struct ds input;
> -    struct ds output;
> -
> -    ds_init(&input);
> -    ds_init(&output);
> -    while (!ds_get_test_line(&input, stdin)) {
> -        struct lexer lexer;
> -
> -        lexer_init(&lexer, ds_cstr(&input));
> -        ds_clear(&output);
> -        while (lexer_get(&lexer) != LEX_T_END) {
> -            size_t len = output.length;
> -            lex_token_format(&lexer.token, &output);
> -
> -            /* Check that the formatted version can really be parsed back
> -             * losslessly. */
> -            if (lexer.token.type != LEX_T_ERROR) {
> -                const char *s = ds_cstr(&output) + len;
> -                struct lexer l2;
> -
> -                lexer_init(&l2, s);
> -                lexer_get(&l2);
> -                compare_token(&lexer.token, &l2.token);
> -                lexer_destroy(&l2);
> -            }
> -            ds_put_char(&output, ' ');
> -        }
> -        lexer_destroy(&lexer);
> -
> -        ds_chomp(&output, ' ');
> -        puts(ds_cstr(&output));
> -    }
> -    ds_destroy(&input);
> -    ds_destroy(&output);
> -}
> -
> -static void
> -create_symtab(struct shash *symtab)
> -{
> -    ovn_init_symtab(symtab);
> -
> -    /* For negative testing. */
> -    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0, "xyzzy",
> false);
> -    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
> -                          "self_recurse != 0", false);
> -    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
> -                          "mutual_recurse_2 != 0", false);
> -    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
> -                          "mutual_recurse_1 != 0", false);
> -    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
> -}
> -
> -static void
> -create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> -                struct hmap *nd_ra_opts,
> -                struct controller_event_options *event_opts)
> -{
> -    hmap_init(dhcp_opts);
> -    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
> -    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
> -    dhcp_opt_add(dhcp_opts, "classless_static_route", 121,
> "static_routes");
> -    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
> -    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
> -    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
> -    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
> -    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
> -    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
> -    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
> -    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
> -    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
> -    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
> -    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
> -
> -    /* DHCPv6 options. */
> -    hmap_init(dhcpv6_opts);
> -    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
> -    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
> -    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
> -    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
> -
> -    /* IPv6 ND RA options. */
> -    hmap_init(nd_ra_opts);
> -    nd_ra_opts_init(nd_ra_opts);
> -
> -    /* OVN controller events options. */
> -    controller_event_opts_init(event_opts);
> -}
> -
> -static void
> -create_addr_sets(struct shash *addr_sets)
> -{
> -    shash_init(addr_sets);
> -
> -    static const char *const addrs1[] = {
> -        "10.0.0.1", "10.0.0.2", "10.0.0.3",
> -    };
> -    static const char *const addrs2[] = {
> -        "::1", "::2", "::3",
> -    };
> -    static const char *const addrs3[] = {
> -        "00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03",
> -    };
> -    static const char *const addrs4[] = { NULL };
> -
> -    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
> -    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
> -    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
> -    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
> -}
> -
> -static void
> -create_port_groups(struct shash *port_groups)
> -{
> -    shash_init(port_groups);
> -
> -    static const char *const pg1[] = {
> -        "lsp1", "lsp2", "lsp3",
> -    };
> -    static const char *const pg2[] = { NULL };
> -
> -    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
> -    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
> -}
> -
> -static bool
> -lookup_port_cb(const void *ports_, const char *port_name, unsigned int
> *portp)
> -{
> -    const struct simap *ports = ports_;
> -    const struct simap_node *node = simap_find(ports, port_name);
> -    if (!node) {
> -        return false;
> -    }
> -    *portp = node->data;
> -    return true;
> -}
> -
> -static bool
> -is_chassis_resident_cb(const void *ports_, const char *port_name)
> -{
> -    const struct simap *ports = ports_;
> -    const struct simap_node *node = simap_find(ports, port_name);
> -    if (node) {
> -        return true;
> -    }
> -    return false;
> -}
> -
> -static void
> -test_parse_expr__(int steps)
> -{
> -    struct shash symtab;
> -    struct shash addr_sets;
> -    struct shash port_groups;
> -    struct simap ports;
> -    struct ds input;
> -
> -    create_symtab(&symtab);
> -    create_addr_sets(&addr_sets);
> -    create_port_groups(&port_groups);
> -
> -    simap_init(&ports);
> -    simap_put(&ports, "eth0", 5);
> -    simap_put(&ports, "eth1", 6);
> -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
> -    simap_put(&ports, "lsp1", 0x11);
> -    simap_put(&ports, "lsp2", 0x12);
> -    simap_put(&ports, "lsp3", 0x13);
> -
> -    ds_init(&input);
> -    while (!ds_get_test_line(&input, stdin)) {
> -        struct expr *expr;
> -        char *error;
> -
> -        expr = expr_parse_string(ds_cstr(&input), &symtab, &addr_sets,
> -                                 &port_groups, NULL, &error);
> -        if (!error && steps > 0) {
> -            expr = expr_annotate(expr, &symtab, &error);
> -        }
> -        if (!error) {
> -            if (steps > 1) {
> -                expr = expr_simplify(expr, is_chassis_resident_cb,
> &ports);
> -            }
> -            if (steps > 2) {
> -                expr = expr_normalize(expr);
> -                ovs_assert(expr_is_normalized(expr));
> -            }
> -        }
> -        if (!error) {
> -            if (steps > 3) {
> -                struct hmap matches;
> -
> -                expr_to_matches(expr, lookup_port_cb, &ports, &matches);
> -                expr_matches_print(&matches, stdout);
> -                expr_matches_destroy(&matches);
> -            } else {
> -                struct ds output = DS_EMPTY_INITIALIZER;
> -                expr_format(expr, &output);
> -                puts(ds_cstr(&output));
> -                ds_destroy(&output);
> -            }
> -        } else {
> -            puts(error);
> -            free(error);
> -        }
> -        expr_destroy(expr);
> -    }
> -    ds_destroy(&input);
> -
> -    simap_destroy(&ports);
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -    expr_const_sets_destroy(&addr_sets);
> -    shash_destroy(&addr_sets);
> -    expr_const_sets_destroy(&port_groups);
> -    shash_destroy(&port_groups);
> -}
> -
> -static void
> -test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    test_parse_expr__(0);
> -}
> -
> -static void
> -test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    test_parse_expr__(1);
> -}
> -
> -static void
> -test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    test_parse_expr__(2);
> -}
> -
> -static void
> -test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    test_parse_expr__(3);
> -}
> -
> -static void
> -test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    test_parse_expr__(4);
> -}
> -
> -/* Print the symbol table. */
> -
> -static void
> -test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    struct shash symtab;
> -    create_symtab(&symtab);
> -
> -    const struct shash_node **nodes = shash_sort(&symtab);
> -    for (size_t i = 0; i < shash_count(&symtab); i++) {
> -        const struct expr_symbol *symbol = nodes[i]->data;
> -        struct ds s = DS_EMPTY_INITIALIZER;
> -        expr_symbol_format(symbol, &s);
> -        puts(ds_cstr(&s));
> -        ds_destroy(&s);
> -    }
> -
> -    free(nodes);
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -}
> -
> -/* Evaluate an expression. */
> -
> -static bool
> -lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
> -               unsigned int *portp)
> -{
> -    *portp = atoi(port_name);
> -    return true;
> -}
> -
> -static void
> -test_evaluate_expr(struct ovs_cmdl_context *ctx)
> -{
> -    struct shash symtab;
> -    struct ds input;
> -
> -    ovn_init_symtab(&symtab);
> -
> -    struct flow uflow;
> -    char *error = expr_parse_microflow(ctx->argv[1], &symtab, NULL, NULL,
> -                                       lookup_atoi_cb, NULL, &uflow);
> -    if (error) {
> -        ovs_fatal(0, "%s", error);
> -    }
> -
> -    ds_init(&input);
> -    while (!ds_get_test_line(&input, stdin)) {
> -        struct expr *expr;
> -
> -        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL, NULL,
> NULL,
> -                                 &error);
> -        if (!error) {
> -            expr = expr_annotate(expr, &symtab, &error);
> -        }
> -        if (!error) {
> -            printf("%d\n", expr_evaluate(expr, &uflow, lookup_atoi_cb,
> NULL));
> -        } else {
> -            puts(error);
> -            free(error);
> -        }
> -        expr_destroy(expr);
> -    }
> -    ds_destroy(&input);
> -
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -}
> -
> -/* Compositions.
> - *
> - * The "compositions" of a positive integer N are all of the ways that
> one can
> - * add up positive integers to sum to N.  For example, the compositions
> of 3
> - * are 3, 2+1, 1+2, and 1+1+1.
> - *
> - * We use compositions to find all the ways to break up N terms of a
> Boolean
> - * expression into subexpressions.  Suppose we want to generate all
> expressions
> - * with 3 terms.  The compositions of 3 (ignoring 3 itself) provide the
> - * possibilities (x && x) || x, x || (x && x), and x || x || x.  (Of
> course one
> - * can exchange && for || in each case.)  One must recursively compose the
> - * sub-expressions whose values are 3 or greater; that is what the "tree
> shape"
> - * concept later covers.
> - *
> - * To iterate through all compositions of, e.g., 5:
> - *
> - *     unsigned int state;
> - *     int s[5];
> - *     int n;
> - *
> - *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
> - *          n = next_composition(&state, s, n)) {
> - *          // Do something with composition 's' with 'n' elements.
> - *     }
> - *
> - * Algorithm from D. E. Knuth, _The Art of Computer Programming, Vol. 4A:
> - * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to exercise
> - * 12(a).
> - */
> -
> -/* Begins iteration through the compositions of 'n'.  Initializes 's' to
> the
> - * number of elements in the first composition of 'n' and returns that
> number
> - * of elements.  The first composition in fact is always 'n' itself, so
> the
> - * return value will be 1.
> - *
> - * Initializes '*state' to some internal state information.  The caller
> must
> - * maintain this state (and 's') for use by next_composition().
> - *
> - * 's' must have room for at least 'n' elements. */
> -static int
> -first_composition(int n, unsigned int *state, int s[])
> -{
> -    *state = 0;
> -    s[0] = n;
> -    return 1;
> -}
> -
> -/* Advances 's', with 'sn' elements, to the next composition and returns
> the
> - * number of elements in this new composition, or 0 if no compositions are
> - * left.  'state' is the same internal state passed to
> first_composition(). */
> -static int
> -next_composition(unsigned int *state, int s[], int sn)
> -{
> -    int j = sn - 1;
> -    if (++*state & 1) {
> -        if (s[j] > 1) {
> -            s[j]--;
> -            s[j + 1] = 1;
> -            j++;
> -        } else {
> -            j--;
> -            s[j]++;
> -        }
> -    } else {
> -        if (s[j - 1] > 1) {
> -            s[j - 1]--;
> -            s[j + 1] = s[j];
> -            s[j] = 1;
> -            j++;
> -        } else {
> -            j--;
> -            if (!j) {
> -                return 0;
> -            }
> -            s[j] = s[j + 1];
> -            s[j - 1]++;
> -        }
> -    }
> -    return j + 1;
> -}
> -
> -static void
> -test_composition(struct ovs_cmdl_context *ctx)
> -{
> -    int n = atoi(ctx->argv[1]);
> -    unsigned int state;
> -    int s[50];
> -
> -    for (int sn = first_composition(n, &state, s); sn;
> -         sn = next_composition(&state, s, sn)) {
> -        for (int i = 0; i < sn; i++) {
> -            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
> -        }
> -    }
> -}
> -
> -/* Tree shapes.
> - *
> - * This code generates all possible Boolean expressions with a specified
> number
> - * of terms N (equivalent to the number of external nodes in a tree).
> - *
> - * See test_tree_shape() for a simple example. */
> -
> -/* An array of these structures describes the shape of a tree.
> - *
> - * A single element of struct tree_shape describes a single node in the
> tree.
> - * The node has 'sn' direct children.  From left to right, for i in
> 0...sn-1,
> - * s[i] is 1 if the child is a leaf node, otherwise the child is a
> subtree and
> - * s[i] is the number of leaf nodes within that subtree.  In the latter
> case,
> - * the subtree is described by another struct tree_shape within the
> enclosing
> - * array.  The tree_shapes are ordered in the array in in-order.
> - */
> -struct tree_shape {
> -    unsigned int state;
> -    int s[50];
> -    int sn;
> -};
> -
> -static int
> -init_tree_shape__(struct tree_shape ts[], int n)
> -{
> -    if (n <= 2) {
> -        return 0;
> -    }
> -
> -    int n_tses = 1;
> -    /* Skip the first composition intentionally. */
> -    ts->sn = first_composition(n, &ts->state, ts->s);
> -    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
> -    for (int i = 0; i < ts->sn; i++) {
> -        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
> -    }
> -    return n_tses;
> -}
> -
> -/* Initializes 'ts[]' as the first in the set of all of possible shapes of
> - * trees with 'n' leaves.  Returns the number of "struct tree_shape"s in
> the
> - * first tree shape. */
> -static int
> -init_tree_shape(struct tree_shape ts[], int n)
> -{
> -    switch (n) {
> -    case 1:
> -        ts->sn = 1;
> -        ts->s[0] = 1;
> -        return 1;
> -    case 2:
> -        ts->sn = 2;
> -        ts->s[0] = 1;
> -        ts->s[1] = 1;
> -        return 1;
> -    default:
> -        return init_tree_shape__(ts, n);
> -    }
> -}
> -
> -/* Advances 'ts', which currently has 'n_tses' elements, to the next
> possible
> - * tree shape with the number of leaves passed to init_tree_shape().
> Returns
> - * the number of "struct tree_shape"s in the next shape, or 0 if all tree
> - * shapes have been visited. */
> -static int
> -next_tree_shape(struct tree_shape ts[], int n_tses)
> -{
> -    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1] == 1) {
> -        return 0;
> -    }
> -    while (n_tses > 0) {
> -        struct tree_shape *p = &ts[n_tses - 1];
> -        p->sn = p->sn > 1 ? next_composition(&p->state, p->s, p->sn) : 0;
> -        if (p->sn) {
> -            for (int i = 0; i < p->sn; i++) {
> -                n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
> -            }
> -            break;
> -        }
> -        n_tses--;
> -    }
> -    return n_tses;
> -}
> -
> -static void
> -print_tree_shape(const struct tree_shape ts[], int n_tses)
> -{
> -    for (int i = 0; i < n_tses; i++) {
> -        if (i) {
> -            printf(", ");
> -        }
> -        for (int j = 0; j < ts[i].sn; j++) {
> -            int k = ts[i].s[j];
> -            if (k > 9) {
> -                printf("(%d)", k);
> -            } else {
> -                printf("%d", k);
> -            }
> -        }
> -    }
> -}
> -
> -static void
> -test_tree_shape(struct ovs_cmdl_context *ctx)
> -{
> -    int n = atoi(ctx->argv[1]);
> -    struct tree_shape ts[50];
> -    int n_tses;
> -
> -    for (n_tses = init_tree_shape(ts, n); n_tses;
> -         n_tses = next_tree_shape(ts, n_tses)) {
> -        print_tree_shape(ts, n_tses);
> -        putchar('\n');
> -    }
> -}
> -
> -/* Iteration through all possible terminal expressions (e.g. EXPR_T_CMP
> and
> - * EXPR_T_BOOLEAN expressions).
> - *
> - * Given a tree shape, this allows the code to try all possible ways to
> plug in
> - * terms.
> - *
> - * Example use:
> - *
> - *     struct expr terminal;
> - *     const struct expr_symbol *vars = ...;
> - *     int n_vars = ...;
> - *     int n_bits = ...;
> - *
> - *     init_terminal(&terminal, vars[0]);
> - *     do {
> - *         // Something with 'terminal'.
> - *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
> - */
> -
> -/* Sets 'expr' to the first possible terminal expression.  'var' should
> be the
> - * first variable in the ones to be tested. */
> -static void
> -init_terminal(struct expr *expr, int phase,
> -              const struct expr_symbol *nvars[], int n_nvars,
> -              const struct expr_symbol *svars[], int n_svars)
> -{
> -    if (phase < 1 && n_nvars) {
> -        expr->type = EXPR_T_CMP;
> -        expr->cmp.symbol = nvars[0];
> -        expr->cmp.relop = rightmost_1bit_idx(test_relops);
> -        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
> -        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
> -        expr->cmp.value.integer = htonll(0);
> -        expr->cmp.mask.integer = htonll(0);
> -        return;
> -    }
> -
> -    if (phase < 2 && n_svars) {
> -        expr->type = EXPR_T_CMP;
> -        expr->cmp.symbol = svars[0];
> -        expr->cmp.relop = EXPR_R_EQ;
> -        expr->cmp.string = xstrdup("0");
> -        return;
> -    }
> -
> -    expr->type = EXPR_T_BOOLEAN;
> -    expr->boolean = false;
> -}
> -
> -/* Returns 'x' with the rightmost contiguous string of 1s changed to 0s,
> - * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's Delight_,
> 2nd
> - * ed., section 2-1. */
> -static unsigned int
> -turn_off_rightmost_1s(unsigned int x)
> -{
> -    return ((x & -x) + x) & x;
> -}
> -
> -static const struct expr_symbol *
> -next_var(const struct expr_symbol *symbol,
> -         const struct expr_symbol *vars[], int n_vars)
> -{
> -    for (int i = 0; i < n_vars; i++) {
> -        if (symbol == vars[i]) {
> -            return i + 1 >= n_vars ? NULL : vars[i + 1];
> -        }
> -    }
> -    OVS_NOT_REACHED();
> -}
> -
> -static enum expr_relop
> -next_relop(enum expr_relop relop)
> -{
> -    unsigned int remaining_relops = test_relops & ~((1u << (relop + 1)) -
> 1);
> -    return (remaining_relops
> -            ? rightmost_1bit_idx(remaining_relops)
> -            : rightmost_1bit_idx(test_relops));
> -}
> -
> -/* Advances 'expr' to the next possible terminal expression within the
> 'n_vars'
> - * variables of 'n_bits' bits each in 'vars[]'. */
> -static bool
> -next_terminal(struct expr *expr,
> -              const struct expr_symbol *nvars[], int n_nvars, int n_bits,
> -              const struct expr_symbol *svars[], int n_svars)
> -{
> -    if (expr->type == EXPR_T_BOOLEAN) {
> -        if (expr->boolean) {
> -            return false;
> -        } else {
> -            expr->boolean = true;
> -            return true;
> -        }
> -    }
> -
> -    if (!expr->cmp.symbol->width) {
> -        int next_value = atoi(expr->cmp.string) + 1;
> -        free(expr->cmp.string);
> -        if (next_value > 1) {
> -            expr->cmp.symbol = next_var(expr->cmp.symbol, svars, n_svars);
> -            if (!expr->cmp.symbol) {
> -                init_terminal(expr, 2, nvars, n_nvars, svars, n_svars);
> -                return true;
> -            }
> -            next_value = 0;
> -        }
> -        expr->cmp.string = xasprintf("%d", next_value);
> -        return true;
> -    }
> -
> -    unsigned int next;
> -
> -    next = (ntohll(expr->cmp.value.integer)
> -            + (ntohll(expr->cmp.mask.integer) << n_bits));
> -    for (;;) {
> -        next++;
> -        unsigned m = next >> n_bits;
> -        unsigned v = next & ((1u << n_bits) - 1);
> -        if (next >= (1u << (2 * n_bits))) {
> -            enum expr_relop old_relop = expr->cmp.relop;
> -            expr->cmp.relop = next_relop(old_relop);
> -            if (expr->cmp.relop <= old_relop) {
> -                expr->cmp.symbol = next_var(expr->cmp.symbol, nvars,
> n_nvars);
> -                if (!expr->cmp.symbol) {
> -                    init_terminal(expr, 1, nvars, n_nvars, svars,
> n_svars);
> -                    return true;
> -                }
> -            }
> -            next = UINT_MAX;
> -        } else if (v & ~m) {
> -            /* Skip: 1-bits in value correspond to 0-bits in mask. */
> -        } else if ((!m || turn_off_rightmost_1s(m))
> -                   && (expr->cmp.relop != EXPR_R_EQ &&
> -                       expr->cmp.relop != EXPR_R_NE)) {
> -            /* Skip: can't have discontiguous or all-0 mask for > >= <
> <=. */
> -        } else {
> -            expr->cmp.value.integer = htonll(v);
> -            expr->cmp.mask.integer = htonll(m);
> -            return true;
> -        }
> -    }
> -}
> -
> -static struct expr *
> -make_terminal(struct expr ***terminalp)
> -{
> -    struct expr *e = expr_create_boolean(true);
> -    **terminalp = e;
> -    (*terminalp)++;
> -    return e;
> -}
> -
> -static struct expr *
> -build_simple_tree(enum expr_type type, int n, struct expr ***terminalp)
> -{
> -    if (n == 2) {
> -        struct expr *e = expr_create_andor(type);
> -        for (int i = 0; i < 2; i++) {
> -            struct expr *sub = make_terminal(terminalp);
> -            ovs_list_push_back(&e->andor, &sub->node);
> -        }
> -        return e;
> -    } else if (n == 1) {
> -        return make_terminal(terminalp);
> -    } else {
> -        OVS_NOT_REACHED();
> -    }
> -}
> -
> -static struct expr *
> -build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
> -                 struct expr ***terminalp)
> -{
> -    const struct tree_shape *ts = *tsp;
> -    (*tsp)++;
> -
> -    struct expr *e = expr_create_andor(type);
> -    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
> -    for (int i = 0; i < ts->sn; i++) {
> -        struct expr *sub = (ts->s[i] > 2
> -                            ? build_tree_shape(t, tsp, terminalp)
> -                            : build_simple_tree(t, ts->s[i], terminalp));
> -        ovs_list_push_back(&e->andor, &sub->node);
> -    }
> -    return e;
> -}
> -
> -struct test_rule {
> -    struct cls_rule cr;
> -};
> -
> -static void
> -free_rule(struct test_rule *test_rule)
> -{
> -    cls_rule_destroy(&test_rule->cr);
> -    free(test_rule);
> -}
> -
> -static bool
> -tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
> -                                  const char *port_name OVS_UNUSED)
> -{
> -    return true;
> -}
> -
> -static int
> -test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab,
> -                             struct expr *terminals[], int n_terminals,
> -                             const struct expr_symbol *nvars[], int
> n_nvars,
> -                             int n_bits,
> -                             const struct expr_symbol *svars[], int
> n_svars)
> -{
> -    int n_tested = 0;
> -
> -    const unsigned int var_mask = (1u << n_bits) - 1;
> -    for (int i = 0; i < n_terminals; i++) {
> -        init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
> -    }
> -
> -    struct ds s = DS_EMPTY_INITIALIZER;
> -    struct flow f;
> -    memset(&f, 0, sizeof f);
> -    for (;;) {
> -        for (int i = n_terminals - 1; ; i--) {
> -            if (!i) {
> -                ds_destroy(&s);
> -                return n_tested;
> -            }
> -            if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
> -                              svars, n_svars)) {
> -                break;
> -            }
> -            init_terminal(terminals[i], 0, nvars, n_nvars, svars,
> n_svars);
> -        }
> -        ovs_assert(expr_honors_invariants(expr));
> -
> -        n_tested++;
> -
> -        struct expr *modified;
> -        if (operation == OP_CONVERT) {
> -            ds_clear(&s);
> -            expr_format(expr, &s);
> -
> -            char *error;
> -            modified = expr_parse_string(ds_cstr(&s), symtab, NULL,
> -                                         NULL, NULL, &error);
> -            if (error) {
> -                fprintf(stderr, "%s fails to parse (%s)\n",
> -                        ds_cstr(&s), error);
> -                exit(EXIT_FAILURE);
> -            }
> -        } else if (operation >= OP_SIMPLIFY) {
> -            modified = expr_simplify(expr_clone(expr),
> -                                     tree_shape_is_chassis_resident_cb,
> -                                     NULL);
> -            ovs_assert(expr_honors_invariants(modified));
> -
> -            if (operation >= OP_NORMALIZE) {
> -                modified = expr_normalize(modified);
> -                ovs_assert(expr_honors_invariants(modified));
> -                ovs_assert(expr_is_normalized(modified));
> -            }
> -        }
> -
> -        struct hmap matches;
> -        struct classifier cls;
> -        if (operation >= OP_FLOW) {
> -            struct expr_match *m;
> -            struct test_rule *test_rule;
> -
> -            expr_to_matches(modified, lookup_atoi_cb, NULL, &matches);
> -
> -            classifier_init(&cls, NULL);
> -            HMAP_FOR_EACH (m, hmap_node, &matches) {
> -                test_rule = xmalloc(sizeof *test_rule);
> -                cls_rule_init(&test_rule->cr, &m->match, 0);
> -                classifier_insert(&cls, &test_rule->cr, OVS_VERSION_MIN,
> -                                  m->conjunctions, m->n);
> -            }
> -        }
> -        for (int subst = 0; subst < 1 << (n_bits * n_nvars + n_svars);
> -             subst++) {
> -            for (int i = 0; i < n_nvars; i++) {
> -                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
> -            }
> -            for (int i = 0; i < n_svars; i++) {
> -                f.regs[n_nvars + i] = ((subst >> (n_nvars * n_bits + i))
> -                                       & 1);
> -            }
> -
> -            bool expected = expr_evaluate(expr, &f, lookup_atoi_cb, NULL);
> -            bool actual = expr_evaluate(modified, &f, lookup_atoi_cb,
> NULL);
> -            if (actual != expected) {
> -                struct ds expr_s, modified_s;
> -
> -                ds_init(&expr_s);
> -                expr_format(expr, &expr_s);
> -
> -                ds_init(&modified_s);
> -                expr_format(modified, &modified_s);
> -
> -                fprintf(stderr,
> -                        "%s evaluates to %d, but %s evaluates to %d, for",
> -                        ds_cstr(&expr_s), expected,
> -                        ds_cstr(&modified_s), actual);
> -                for (int i = 0; i < n_nvars; i++) {
> -                    if (i > 0) {
> -                        fputs(",", stderr);
> -                    }
> -                    fprintf(stderr, " n%d = 0x%x", i,
> -                            (subst >> (n_bits * i)) & var_mask);
> -                }
> -                for (int i = 0; i < n_svars; i++) {
> -                    fprintf(stderr, ", s%d = \"%d\"", i,
> -                            (subst >> (n_bits * n_nvars + i)) & 1);
> -                }
> -                putc('\n', stderr);
> -                exit(EXIT_FAILURE);
> -            }
> -
> -            if (operation >= OP_FLOW) {
> -                bool found = classifier_lookup(&cls, OVS_VERSION_MIN,
> -                                               &f, NULL) != NULL;
> -                if (expected != found) {
> -                    struct ds expr_s, modified_s;
> -
> -                    ds_init(&expr_s);
> -                    expr_format(expr, &expr_s);
> -
> -                    ds_init(&modified_s);
> -                    expr_format(modified, &modified_s);
> -
> -                    fprintf(stderr,
> -                            "%s and %s evaluate to %d, for",
> -                            ds_cstr(&expr_s), ds_cstr(&modified_s),
> expected);
> -                    for (int i = 0; i < n_nvars; i++) {
> -                        if (i > 0) {
> -                            fputs(",", stderr);
> -                        }
> -                        fprintf(stderr, " n%d = 0x%x", i,
> -                                (subst >> (n_bits * i)) & var_mask);
> -                    }
> -                    for (int i = 0; i < n_svars; i++) {
> -                        fprintf(stderr, ", s%d = \"%d\"", i,
> -                                (subst >> (n_bits * n_nvars + i)) & 1);
> -                    }
> -                    fputs(".\n", stderr);
> -
> -                    fprintf(stderr, "Converted to classifier:\n");
> -                    expr_matches_print(&matches, stderr);
> -                    fprintf(stderr,
> -                            "However, %s flow was found in the
> classifier.\n",
> -                            found ? "a" : "no");
> -                    exit(EXIT_FAILURE);
> -                }
> -            }
> -        }
> -        if (operation >= OP_FLOW) {
> -            struct test_rule *test_rule;
> -
> -            CLS_FOR_EACH (test_rule, cr, &cls) {
> -                classifier_remove_assert(&cls, &test_rule->cr);
> -                ovsrcu_postpone(free_rule, test_rule);
> -            }
> -            classifier_destroy(&cls);
> -            ovsrcu_quiesce();
> -
> -            expr_matches_destroy(&matches);
> -        }
> -        expr_destroy(modified);
> -    }
> -}
> -
> -#ifndef _WIN32
> -static void
> -wait_pid(pid_t *pids, int *n)
> -{
> -    int status;
> -    pid_t pid;
> -
> -    pid = waitpid(-1, &status, 0);
> -    if (pid < 0) {
> -        ovs_fatal(errno, "waitpid failed");
> -    } else if (WIFEXITED(status)) {
> -        if (WEXITSTATUS(status)) {
> -            exit(WEXITSTATUS(status));
> -        }
> -    } else if (WIFSIGNALED(status)) {
> -        raise(WTERMSIG(status));
> -        exit(1);
> -    } else {
> -        OVS_NOT_REACHED();
> -    }
> -
> -    for (int i = 0; i < *n; i++) {
> -        if (pids[i] == pid) {
> -            pids[i] = pids[--*n];
> -            return;
> -        }
> -    }
> -    ovs_fatal(0, "waitpid returned unknown child");
> -}
> -#endif
> -
> -static void
> -test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    int n_terminals = atoi(ctx->argv[1]);
> -    struct tree_shape ts[50];
> -    int n_tses;
> -
> -    struct shash symtab;
> -    const struct expr_symbol *nvars[4];
> -    const struct expr_symbol *svars[4];
> -
> -    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
> -    ovs_assert(test_svars <= ARRAY_SIZE(svars));
> -    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
> -
> -    shash_init(&symtab);
> -    for (int i = 0; i < test_nvars; i++) {
> -        char *name = xasprintf("n%d", i);
> -        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0 + i,
> NULL,
> -                                         false);
> -        free(name);
> -    }
> -    for (int i = 0; i < test_svars; i++) {
> -        char *name = xasprintf("s%d", i);
> -        svars[i] = expr_symtab_add_string(&symtab, name,
> -                                          MFF_REG0 + test_nvars + i,
> NULL);
> -        free(name);
> -    }
> -
> -#ifndef _WIN32
> -    pid_t *children = xmalloc(test_parallel * sizeof *children);
> -    int n_children = 0;
> -#endif
> -
> -    int n_tested = 0;
> -    for (int i = 0; i < 2; i++) {
> -        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
> -
> -        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
> -             n_tses = next_tree_shape(ts, n_tses)) {
> -            const struct tree_shape *tsp = ts;
> -            struct expr *terminals[50];
> -            struct expr **terminalp = terminals;
> -            struct expr *expr = build_tree_shape(base_type, &tsp,
> &terminalp);
> -            ovs_assert(terminalp == &terminals[n_terminals]);
> -
> -            if (verbosity > 0) {
> -                print_tree_shape(ts, n_tses);
> -                printf(": ");
> -                struct ds s = DS_EMPTY_INITIALIZER;
> -                expr_format(expr, &s);
> -                puts(ds_cstr(&s));
> -                ds_destroy(&s);
> -            }
> -
> -#ifndef _WIN32
> -            if (test_parallel > 1) {
> -                pid_t pid = xfork();
> -                if (!pid) {
> -                    test_tree_shape_exhaustively(expr, &symtab,
> -                                                 terminals, n_terminals,
> -                                                 nvars, test_nvars,
> test_bits,
> -                                                 svars, test_svars);
> -                    expr_destroy(expr);
> -                    exit(0);
> -                } else {
> -                    if (n_children >= test_parallel) {
> -                        wait_pid(children, &n_children);
> -                    }
> -                    children[n_children++] = pid;
> -                }
> -            } else
> -#endif
> -            {
> -                n_tested += test_tree_shape_exhaustively(
> -                    expr, &symtab, terminals, n_terminals,
> -                    nvars, test_nvars, test_bits,
> -                    svars, test_svars);
> -            }
> -            expr_destroy(expr);
> -        }
> -    }
> -#ifndef _WIN32
> -    while (n_children > 0) {
> -        wait_pid(children, &n_children);
> -    }
> -    free(children);
> -#endif
> -
> -    printf("Tested ");
> -    switch (operation) {
> -    case OP_CONVERT:
> -        printf("converting");
> -        break;
> -    case OP_SIMPLIFY:
> -        printf("simplifying");
> -        break;
> -    case OP_NORMALIZE:
> -        printf("normalizing");
> -        break;
> -    case OP_FLOW:
> -        printf("converting to flows");
> -        break;
> -    }
> -    if (n_tested) {
> -        printf(" %d expressions of %d terminals", n_tested, n_terminals);
> -    } else {
> -        printf(" all %d-terminal expressions", n_terminals);
> -    }
> -    if (test_nvars || test_svars) {
> -        printf(" with");
> -        if (test_nvars) {
> -            printf(" %d numeric vars (each %d bits) in terms of
> operators",
> -                   test_nvars, test_bits);
> -            for (unsigned int relops = test_relops; relops;
> -                 relops = zero_rightmost_1bit(relops)) {
> -                enum expr_relop r = rightmost_1bit_idx(relops);
> -                printf(" %s", expr_relop_to_string(r));
> -            }
> -        }
> -        if (test_nvars && test_svars) {
> -            printf (" and");
> -        }
> -        if (test_svars) {
> -            printf(" %d string vars", test_svars);
> -        }
> -    } else {
> -        printf(" in terms of Boolean constants only");
> -    }
> -    printf(".\n");
> -
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -}
> -
> -static void
> -test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    struct shash symtab;
> -    struct ds input;
> -
> -    create_symtab(&symtab);
> -
> -    ds_init(&input);
> -    while (!ds_get_test_line(&input, stdin)) {
> -        struct flow uflow;
> -        char *error = expr_parse_microflow(ds_cstr(&input), &symtab, NULL,
> -                                           NULL, lookup_atoi_cb, NULL,
> &uflow);
> -        if (error) {
> -            puts(error);
> -            free(error);
> -            continue;
> -        }
> -
> -        uint64_t packet_stub[128 / 8];
> -        struct dp_packet packet;
> -        dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
> -        flow_compose(&packet, &uflow, NULL, 64);
> -
> -        struct ds output = DS_EMPTY_INITIALIZER;
> -        const uint8_t *buf = dp_packet_data(&packet);
> -        for (int i = 0; i < dp_packet_size(&packet); i++) {
> -            uint8_t val = buf[i];
> -            ds_put_format(&output, "%02"PRIx8, val);
> -        }
> -        puts(ds_cstr(&output));
> -        ds_destroy(&output);
> -
> -        dp_packet_uninit(&packet);
> -    }
> -    ds_destroy(&input);
> -
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -}
> -
> -/* Actions. */
> -
> -static void
> -test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
> -{
> -    struct shash symtab;
> -    struct hmap dhcp_opts;
> -    struct hmap dhcpv6_opts;
> -    struct hmap nd_ra_opts;
> -    struct controller_event_options event_opts;
> -    struct simap ports;
> -    struct ds input;
> -    bool ok = true;
> -
> -    create_symtab(&symtab);
> -    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts, &event_opts);
> -
> -    /* Initialize group ids. */
> -    struct ovn_extend_table group_table;
> -    ovn_extend_table_init(&group_table);
> -
> -    /* Initialize meter ids for QoS. */
> -    struct ovn_extend_table meter_table;
> -    ovn_extend_table_init(&meter_table);
> -
> -    simap_init(&ports);
> -    simap_put(&ports, "eth0", 5);
> -    simap_put(&ports, "eth1", 6);
> -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
> -
> -    ds_init(&input);
> -    while (!ds_get_test_line(&input, stdin)) {
> -        struct ofpbuf ovnacts;
> -        struct expr *prereqs;
> -        char *error;
> -
> -        puts(ds_cstr(&input));
> -
> -        ofpbuf_init(&ovnacts, 0);
> -
> -        const struct ovnact_parse_params pp = {
> -            .symtab = &symtab,
> -            .dhcp_opts = &dhcp_opts,
> -            .dhcpv6_opts = &dhcpv6_opts,
> -            .nd_ra_opts = &nd_ra_opts,
> -            .controller_event_opts = &event_opts,
> -            .n_tables = 24,
> -            .cur_ltable = 10,
> -        };
> -        error = ovnacts_parse_string(ds_cstr(&input), &pp, &ovnacts,
> &prereqs);
> -        if (!error) {
> -            /* Convert the parsed representation back to a string and
> print it,
> -             * if it's different from the input. */
> -            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
> -            ovnacts_format(ovnacts.data, ovnacts.size, &ovnacts_s);
> -            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
> -                printf("    formats as %s\n", ds_cstr(&ovnacts_s));
> -            }
> -
> -            /* Encode the actions into OpenFlow and print. */
> -            const struct ovnact_encode_params ep = {
> -                .lookup_port = lookup_port_cb,
> -                .aux = &ports,
> -                .is_switch = true,
> -                .group_table = &group_table,
> -                .meter_table = &meter_table,
> -
> -                .pipeline = OVNACT_P_INGRESS,
> -                .ingress_ptable = 8,
> -                .egress_ptable = 40,
> -                .output_ptable = 64,
> -                .mac_bind_ptable = 65,
> -            };
> -            struct ofpbuf ofpacts;
> -            ofpbuf_init(&ofpacts, 0);
> -            ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts);
> -            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
> -            struct ofpact_format_params fp = { .s = &ofpacts_s };
> -            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
> -            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
> -            ds_destroy(&ofpacts_s);
> -            ofpbuf_uninit(&ofpacts);
> -
> -            /* Print prerequisites if any. */
> -            if (prereqs) {
> -                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
> -                expr_format(prereqs, &prereqs_s);
> -                printf("    has prereqs %s\n", ds_cstr(&prereqs_s));
> -                ds_destroy(&prereqs_s);
> -            }
> -
> -            /* Now re-parse and re-format the string to verify that it's
> -             * round-trippable. */
> -            struct ofpbuf ovnacts2;
> -            struct expr *prereqs2;
> -            ofpbuf_init(&ovnacts2, 0);
> -            error = ovnacts_parse_string(ds_cstr(&ovnacts_s), &pp,
> &ovnacts2,
> -                                         &prereqs2);
> -            if (!error) {
> -                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
> -                ovnacts_format(ovnacts2.data, ovnacts2.size, &ovnacts2_s);
> -                if (strcmp(ds_cstr(&ovnacts_s), ds_cstr(&ovnacts2_s))) {
> -                    printf("    bad reformat: %s\n",
> ds_cstr(&ovnacts2_s));
> -                    ok = false;
> -                }
> -                ds_destroy(&ovnacts2_s);
> -            } else {
> -                printf("    reparse error: %s\n", error);
> -                free(error);
> -                ok = false;
> -            }
> -            expr_destroy(prereqs2);
> -
> -            ovnacts_free(ovnacts2.data, ovnacts2.size);
> -            ofpbuf_uninit(&ovnacts2);
> -            ds_destroy(&ovnacts_s);
> -        } else {
> -            printf("    %s\n", error);
> -            free(error);
> -        }
> -
> -        expr_destroy(prereqs);
> -        ovnacts_free(ovnacts.data, ovnacts.size);
> -        ofpbuf_uninit(&ovnacts);
> -    }
> -    ds_destroy(&input);
> -
> -    simap_destroy(&ports);
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -    dhcp_opts_destroy(&dhcp_opts);
> -    dhcp_opts_destroy(&dhcpv6_opts);
> -    nd_ra_opts_destroy(&nd_ra_opts);
> -    controller_event_opts_destroy(&event_opts);
> -    ovn_extend_table_destroy(&group_table);
> -    ovn_extend_table_destroy(&meter_table);
> -    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
> -}
> -
> -static unsigned int
> -parse_relops(const char *s)
> -{
> -    unsigned int relops = 0;
> -    struct lexer lexer;
> -
> -    lexer_init(&lexer, s);
> -    lexer_get(&lexer);
> -    do {
> -        enum expr_relop relop;
> -
> -        if (expr_relop_from_token(lexer.token.type, &relop)) {
> -            relops |= 1u << relop;
> -            lexer_get(&lexer);
> -        } else {
> -            ovs_fatal(0, "%s: relational operator expected at `%.*s'",
> -                      s, (int) (lexer.input - lexer.start), lexer.start);
> -        }
> -        lexer_match(&lexer, LEX_T_COMMA);
> -    } while (lexer.token.type != LEX_T_END);
> -    lexer_destroy(&lexer);
> -
> -    return relops;
> -}
> -
> -static void
> -usage(void)
> -{
> -    printf("\
> -%s: OVN test utility\n\
> -usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
> -\n\
> -lex\n\
> -  Lexically analyzes OVN input from stdin and print them back on
> stdout.\n\
> -\n\
> -parse-expr\n\
> -annotate-expr\n\
> -simplify-expr\n\
> -normalize-expr\n\
> -expr-to-flows\n\
> -  Parses OVN expressions from stdin and prints them back on stdout
> after\n\
> -  differing degrees of analysis.  Available fields are based on packet\n\
> -  headers.\n\
> -\n\
> -expr-to-packets\n\
> -  Parses OVN expressions from stdin and prints out matching packets in\n\
> -  hexadecimal on stdout.\n\
> -\n\
> -evaluate-expr MICROFLOW\n\
> -  Parses OVN expressions from stdin and evaluates them against the flow\n\
> -  specified in MICROFLOW, which must be an expression that constrains\n\
> -  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with
> source\n\
> -  port 80, and prints the results on stdout, either 1 for true or 0 for\n\
> -  false.  Use quoted integers, e.g. \"123\", for string fields.\n\
> -\n\
> -  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type ==
> 0x800\"\n\
> -  evaluates to true, \"udp\" evaluates to false, and \"udp || tcp\"\n\
> -  evaluates to true.\n\
> -\n\
> -composition N\n\
> -  Prints all the compositions of N on stdout.\n\
> -\n\
> -tree-shape N\n\
> -  Prints all the tree shapes with N terminals on stdout.\n\
> -\n\
> -exhaustive N\n\
> -  Tests that all possible Boolean expressions with N terminals are
> properly\n\
> -  simplified, normalized, and converted to flows.  Available options:\n\
> -   Overall options:\n\
> -    --operation=OPERATION  Operation to test, one of: convert,
> simplify,\n\
> -        normalize, flow.  Default: flow.  'normalize' includes
> 'simplify',\n\
> -        'flow' includes 'simplify' and 'normalize'.\n\
> -    --parallel=N  Number of processes to use in parallel, default 1.\n\
> -   Numeric vars:\n\
> -    --nvars=N  Number of numeric vars to test, in range 0...4, default
> 2.\n\
> -    --bits=N  Number of bits per variable, in range 1...3, default 3.\n\
> -    --relops=OPERATORS   Test only the specified Boolean operators.\n\
> -                         OPERATORS may include == != < <= > >=, space
> or\n\
> -                         comma separated.  Default is all operators.\n\
> -   String vars:\n\
> -    --svars=N  Number of string vars to test, in range 0...4, default
> 2.\n\
> -\n\
> -parse-actions\n\
> -  Parses OVN actions from stdin and prints the equivalent OpenFlow
> actions\n\
> -  on stdout.\n\
> -",
> -           program_name, program_name);
> -    exit(EXIT_SUCCESS);
> -}
> -
> -static void
> -test_ovn_main(int argc, char *argv[])
> -{
> -    enum {
> -        OPT_RELOPS = UCHAR_MAX + 1,
> -        OPT_NVARS,
> -        OPT_SVARS,
> -        OPT_BITS,
> -        OPT_OPERATION,
> -        OPT_PARALLEL
> -    };
> -    static const struct option long_options[] = {
> -        {"relops", required_argument, NULL, OPT_RELOPS},
> -        {"nvars", required_argument, NULL, OPT_NVARS},
> -        {"svars", required_argument, NULL, OPT_SVARS},
> -        {"bits", required_argument, NULL, OPT_BITS},
> -        {"operation", required_argument, NULL, OPT_OPERATION},
> -        {"parallel", required_argument, NULL, OPT_PARALLEL},
> -        {"more", no_argument, NULL, 'm'},
> -        {"help", no_argument, NULL, 'h'},
> -        {NULL, 0, NULL, 0},
> -    };
> -    char *short_options =
> ovs_cmdl_long_options_to_short_options(long_options);
> -
> -    set_program_name(argv[0]);
> -
> -    test_relops = parse_relops("== != < <= > >=");
> -    for (;;) {
> -        int option_index = 0;
> -        int c = getopt_long (argc, argv, short_options, long_options,
> -                             &option_index);
> -
> -        if (c == -1) {
> -            break;
> -        }
> -        switch (c) {
> -        case OPT_RELOPS:
> -            test_relops = parse_relops(optarg);
> -            break;
> -
> -        case OPT_NVARS:
> -            test_nvars = atoi(optarg);
> -            if (test_nvars < 0 || test_nvars > 4) {
> -                ovs_fatal(0, "number of numeric variables must be "
> -                          "between 0 and 4");
> -            }
> -            break;
> -
> -        case OPT_SVARS:
> -            test_svars = atoi(optarg);
> -            if (test_svars < 0 || test_svars > 4) {
> -                ovs_fatal(0, "number of string variables must be "
> -                          "between 0 and 4");
> -            }
> -            break;
> -
> -        case OPT_BITS:
> -            test_bits = atoi(optarg);
> -            if (test_bits < 1 || test_bits > 3) {
> -                ovs_fatal(0, "number of bits must be between 1 and 3");
> -            }
> -            break;
> -
> -        case OPT_OPERATION:
> -            if (!strcmp(optarg, "convert")) {
> -                operation = OP_CONVERT;
> -            } else if (!strcmp(optarg, "simplify")) {
> -                operation = OP_SIMPLIFY;
> -            } else if (!strcmp(optarg, "normalize")) {
> -                operation = OP_NORMALIZE;
> -            } else if (!strcmp(optarg, "flow")) {
> -                operation = OP_FLOW;
> -            } else {
> -                ovs_fatal(0, "%s: unknown operation", optarg);
> -            }
> -            break;
> -
> -        case OPT_PARALLEL:
> -            test_parallel = atoi(optarg);
> -            break;
> -
> -        case 'm':
> -            verbosity++;
> -            break;
> -
> -        case 'h':
> -            usage();
> -            /* fall through */
> -
> -        case '?':
> -            exit(1);
> -
> -        default:
> -            abort();
> -        }
> -    }
> -    free(short_options);
> -
> -    static const struct ovs_cmdl_command commands[] = {
> -        /* Lexer. */
> -        {"lex", NULL, 0, 0, test_lex, OVS_RO},
> -
> -        /* Symbol table. */
> -        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
> -
> -        /* Expressions. */
> -        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
> -        {"annotate-expr", NULL, 0, 0, test_annotate_expr, OVS_RO},
> -        {"simplify-expr", NULL, 0, 0, test_simplify_expr, OVS_RO},
> -        {"normalize-expr", NULL, 0, 0, test_normalize_expr, OVS_RO},
> -        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, OVS_RO},
> -        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, OVS_RO},
> -        {"composition", NULL, 1, 1, test_composition, OVS_RO},
> -        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
> -        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
> -        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets, OVS_RO},
> -
> -        /* Actions. */
> -        {"parse-actions", NULL, 0, 0, test_parse_actions, OVS_RO},
> -
> -        {NULL, NULL, 0, 0, NULL, OVS_RO},
> -    };
> -    struct ovs_cmdl_context ctx;
> -    ctx.argc = argc - optind;
> -    ctx.argv = argv + optind;
> -    ovs_cmdl_run_command(&ctx, commands);
> -}
> -
> -OVSTEST_REGISTER("test-ovn", test_ovn_main);
> diff --git a/tests/testsuite.at b/tests/testsuite.at
> index 4d5e816..e759123 100644
> --- a/tests/testsuite.at
> +++ b/tests/testsuite.at
> @@ -19,7 +19,6 @@ m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
>  m4_include([tests/ovs-macros.at])
>  m4_include([tests/ovsdb-macros.at])
>  m4_include([tests/ofproto-macros.at])
> -m4_include([tests/ovn-macros.at])
>
>  m4_include([tests/completion.at])
>  m4_include([tests/checkpatch.at])
> @@ -74,13 +73,6 @@ m4_include([tests/rstp.at])
>  m4_include([tests/vlog.at])
>  m4_include([tests/vtep-ctl.at])
>  m4_include([tests/auto-attach.at])
> -m4_include([tests/ovn.at])
> -m4_include([tests/ovn-northd.at])
> -m4_include([tests/ovn-nbctl.at])
> -m4_include([tests/ovn-sbctl.at])
> -m4_include([tests/ovn-controller.at])
> -m4_include([tests/ovn-controller-vtep.at])
>  m4_include([tests/mcast-snooping.at])
>  m4_include([tests/packet-type-aware.at])
>  m4_include([tests/nsh.at])
> -m4_include([tests/ovn-performance.at])
> --
> 1.8.3.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Gregory Rose Sept. 5, 2019, 9:30 p.m. UTC | #2
On 9/5/2019 12:00 PM, Numan Siddique wrote:
>
> [snip]
> Hi Greg,
>
> This seems reasonable to me. Mark has already submitted a patch to delete
> the OVN folder. But we may have to keep ovn-nbctl/ovn-sbctl utilities
> and OVN schema files for ovsdb-server RAFT tests.
>
> Until that patch is merged, this seems fine to me.

I should have a look at Mark's patch - this work probably needs integration
with that.

>
> Can you please provide the steps you use to run the system tests ?
> I will try to run in the new ovn repo and see if we see failures there.
> I tried sometime back and all the tests fail for me. Probably I wasn't
> running as expected.

Build OVS using the '--with-linux=/lib/modules/$(uname -r)/build 
--enable-Werror'
to get the kernel datapath and then in the directory where you built OVS 
run this
command:

'sudo make check-kmod'

To only run the ovn tests:

'sudo make check-kmod TESTSUITEFLAGS="-k ovn"'

Thanks!

- Greg

>     ---
>      tests/automake.mk <http://automake.mk>         |    23 +-
>      tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at> | 
>      467 --
>      tests/ovn-controller.at <http://ovn-controller.at>     |   294 -
>      tests/ovn-macros.at <http://ovn-macros.at>         |   180 -
>      tests/ovn-nbctl.at <http://ovn-nbctl.at>        |  1660 -----
>      tests/ovn-northd.at <http://ovn-northd.at>         |   900 ---
>      tests/ovn-performance.at <http://ovn-performance.at>    |   424 --
>      tests/ovn-sbctl.at <http://ovn-sbctl.at>        |   150 -
>      tests/ovn.at <http://ovn.at>        | 14702
>     -----------------------------------------
>      tests/system-ovn.at <http://system-ovn.at>         |  1667 -----
>      tests/test-ovn.c             |  1584 -----
>      tests/testsuite.at <http://testsuite.at>        |     8 -
>      12 files changed, 4 insertions(+), 22055 deletions(-)
>      delete mode 100644 tests/ovn-controller-vtep.at
>     <http://ovn-controller-vtep.at>
>      delete mode 100644 tests/ovn-controller.at <http://ovn-controller.at>
>      delete mode 100644 tests/ovn-macros.at <http://ovn-macros.at>
>      delete mode 100644 tests/ovn-nbctl.at <http://ovn-nbctl.at>
>      delete mode 100644 tests/ovn-northd.at <http://ovn-northd.at>
>      delete mode 100644 tests/ovn-performance.at
>     <http://ovn-performance.at>
>      delete mode 100644 tests/ovn-sbctl.at <http://ovn-sbctl.at>
>      delete mode 100644 tests/ovn.at <http://ovn.at>
>      delete mode 100644 tests/system-ovn.at <http://system-ovn.at>
>      delete mode 100644 tests/test-ovn.c
>
>     diff --git a/tests/automake.mk <http://automake.mk>
>     b/tests/automake.mk <http://automake.mk>
>     index d6ab517..decca46 100644
>     --- a/tests/automake.mk <http://automake.mk>
>     +++ b/tests/automake.mk <http://automake.mk>
>     @@ -23,8 +23,7 @@ EXTRA_DIST += \
>      COMMON_MACROS_AT = \
>             tests/ovsdb-macros.at <http://ovsdb-macros.at> \
>             tests/ovs-macros.at <http://ovs-macros.at> \
>     -       tests/ofproto-macros.at <http://ofproto-macros.at> \
>     -       tests/ovn-macros.at <http://ovn-macros.at>
>     +       tests/ofproto-macros.at <http://ofproto-macros.at>
>
>      TESTSUITE_AT = \
>             tests/testsuite.at <http://testsuite.at> \
>     @@ -104,16 +103,9 @@ TESTSUITE_AT = \
>             tests/vlog.at <http://vlog.at> \
>             tests/vtep-ctl.at <http://vtep-ctl.at> \
>             tests/auto-attach.at <http://auto-attach.at> \
>     -       tests/ovn.at <http://ovn.at> \
>     -       tests/ovn-northd.at <http://ovn-northd.at> \
>     -       tests/ovn-nbctl.at <http://ovn-nbctl.at> \
>     -       tests/ovn-sbctl.at <http://ovn-sbctl.at> \
>     -       tests/ovn-controller.at <http://ovn-controller.at> \
>     -       tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at> \
>             tests/mcast-snooping.at <http://mcast-snooping.at> \
>             tests/packet-type-aware.at <http://packet-type-aware.at> \
>     -       tests/nsh.at <http://nsh.at> \
>     -       tests/ovn-performance.at <http://ovn-performance.at>
>     +       tests/nsh.at <http://nsh.at>
>
>      EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
>      FUZZ_REGRESSION_TESTS = \
>     @@ -158,7 +150,6 @@ SYSTEM_KMOD_TESTSUITE_AT = \
>
>      SYSTEM_USERSPACE_TESTSUITE_AT = \
>             tests/system-userspace-testsuite.at
>     <http://system-userspace-testsuite.at> \
>     -       tests/system-ovn.at <http://system-ovn.at> \
>             tests/system-userspace-macros.at
>     <http://system-userspace-macros.at> \
>             tests/system-userspace-packet-type-aware.at
>     <http://system-userspace-packet-type-aware.at>
>
>     @@ -169,7 +160,6 @@ SYSTEM_AFXDP_TESTSUITE_AT = \
>
>      SYSTEM_TESTSUITE_AT = \
>             tests/system-common-macros.at
>     <http://system-common-macros.at> \
>     -       tests/system-ovn.at <http://system-ovn.at> \
>             tests/system-layer3-tunnels.at
>     <http://system-layer3-tunnels.at> \
>             tests/system-traffic.at <http://system-traffic.at> \
>             tests/system-interface.at <http://system-interface.at>
>     @@ -197,7 +187,7 @@ SYSTEM_DPDK_TESTSUITE =
>     $(srcdir)/tests/system-dpdk-testsuite
>      OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
>      DISTCLEANFILES += tests/atconfig tests/atlocal
>
>     -AUTOTEST_PATH =
>     utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller
>     +AUTOTEST_PATH =
>     utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR)
>
>      check-local:
>             set $(SHELL) '$(TESTSUITE)' -C tests
>     AUTOTEST_PATH=$(AUTOTEST_PATH); \
>     @@ -238,10 +228,6 @@ check-lcov: all $(check_DATA) clean-lcov
>      # valgrind support
>
>      valgrind_wrappers = \
>     -       tests/valgrind/ovn-controller \
>     -       tests/valgrind/ovn-nbctl \
>     -       tests/valgrind/ovn-northd \
>     -       tests/valgrind/ovn-sbctl \
>             tests/valgrind/ovs-appctl \
>             tests/valgrind/ovs-ofctl \
>             tests/valgrind/ovs-vsctl \
>     @@ -446,7 +432,6 @@ tests_ovstest_SOURCES = \
>             tests/test-netflow.c \
>             tests/test-odp.c \
>             tests/test-ofpbuf.c \
>     -       tests/test-ovn.c \
>             tests/test-packets.c \
>             tests/test-random.c \
>             tests/test-rcu.c \
>     @@ -474,7 +459,7 @@ tests_ovstest_SOURCES += \
>             tests/test-netlink-conntrack.c
>      endif
>
>     -tests_ovstest_LDADD = lib/libopenvswitch.la
>     <http://libopenvswitch.la> ovn/lib/libovn.la <http://libovn.la>
>     +tests_ovstest_LDADD = lib/libopenvswitch.la
>     <http://libopenvswitch.la>
>
>      noinst_PROGRAMS += tests/test-stream
>      tests_test_stream_SOURCES = tests/test-stream.c
>     diff --git a/tests/ovn-controller-vtep.at
>     <http://ovn-controller-vtep.at> b/tests/ovn-controller-vtep.at
>     <http://ovn-controller-vtep.at>
>     deleted file mode 100644
>     index a3fe8cb..0000000
>     --- a/tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at>
>     +++ /dev/null
>     @@ -1,467 +0,0 @@
>     -AT_BANNER([ovn_controller_vtep])
>     -
>     -# OVN_CONTROLLER_VTEP_START
>     -#
>     -# Starts the test with a setup with vtep device.  Each test case
>     must first
>     -# call this macro.
>     -#
>     -# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two
>     physical ports
>     -# 'p0', 'p1'.
>     -#
>     -# Configures ovn-nb with a logical switch 'br-test'.
>     -#
>     -#
>     -m4_define([OVN_CONTROLLER_VTEP_START],
>     -  [
>     -   AT_KEYWORDS([ovn])
>     -   # this will cause skip when 'make check' using Windows setup.
>     -   AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -
>     -   dnl Create databases (ovn-nb, ovn-sb, vtep).
>     -   AT_CHECK([ovsdb-tool create vswitchd.db
>     $abs_top_srcdir/vswitchd/vswitch.ovsschema])
>     -   for daemon in ovn-nb ovn-sb vtep; do
>     -      AT_CHECK([ovsdb-tool create $daemon.db
>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>     -   done
>     -
>     -   dnl Start ovsdb-server.
>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>     --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db
>     vtep.db], [0], [], [stderr])
>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>     --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log
>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>     [stderr])
>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>     --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log
>     --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db],
>     [0], [], [stderr])
>     -   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid`
>     `cat ovsdb-sb-server.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d
>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>     -
>     -   dnl Start ovs-vswitchd.
>     -   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system
>     --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif],
>     [0], [], [stderr])
>     -   AT_CAPTURE_FILE([ovs-vswitchd.log])
>     -   on_exit "kill `cat ovs-vswitchd.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/ovs_numa|INFO|Discovered /d
>     -/vlog|INFO|opened log file/d
>     -/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
>     -/reconnect|INFO|/d
>     -/ofproto|INFO|using datapath ID/d
>     -/netlink_socket|INFO|netlink: could not enable listening to all
>     nsid/d
>     -/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
>     -   AT_CHECK([ovs-vsctl -- add-br br-vtep \
>     -              -- set bridge br-vtep datapath-type=dummy
>     other-config:datapath-id=fedcba9876543210
>     other-config:hwaddr=aa:55:aa:55:00:00
>     protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]]
>     fail-mode=secure \
>     -              -- add-port br-vtep p0 -- set Interface p0
>     type=dummy ofport_request=1 \
>     -              -- add-port br-vtep p1 -- set Interface p1
>     type=dummy ofport_request=2])
>     -
>     -   dnl Start ovs-vtep.
>     -   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch
>     br-vtep tunnel_ips=1.2.3.4])
>     -   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log
>     --pidfile=ovs-vtep.pid --detach --no-chdir br-vtep \], [0], [],
>     [stderr])
>     -   on_exit "kill `cat ovs-vtep.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d']])
>     -   # waits until ovs-vtep starts up.
>     -   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])
>     -
>     -   dnl Start ovn-northd.
>     -   AT_CHECK([ovn-nbctl ls-add br-test])
>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile
>     --log-file], [0], [], [stderr])
>     -   on_exit "kill `cat ovn-northd.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d']])
>     -   AT_CAPTURE_FILE([ovn-northd.log])
>     -
>     -   dnl Start ovn-controllger-vtep.
>     -   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile
>     --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock
>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>     -   AT_CAPTURE_FILE([ovn-controller-vtep.log])
>     -   on_exit "kill `cat ovn-controller-vtep.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d
>     -/reconnect|INFO|/d']])
>     -])
>     -
>     -# OVN_CONTROLLER_VTEP_STOP
>     -#
>     -# So many exits... Yeah, we started a lot daemons~
>     -#
>     -m4_define([OVN_CONTROLLER_VTEP_STOP],
>     -  [AT_CHECK([check_logs "$1"])
>     -   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>     -   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
>     -
>     -# Adds logical port for a vtep gateway chassis in ovn-nb database.
>     -#
>     -# $1: logical switch name in ovn-nb database
>     -# $2: logical port name
>     -# $3: physical vtep gateway name
>     -# $4: logical switch name on vtep gateway chassis
>     -m4_define([OVN_NB_ADD_VTEP_PORT], [
>     -AT_CHECK([ovn-nbctl lsp-add $1 $2])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
>     -AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3
>     vtep-logical-switch=$4])
>     -])
>     -
>     -##############################################
>     -
>     -# tests chassis related updates.
>     -AT_SETUP([ovn-controller-vtep - chassis])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# verifies the initial ovn-sb db configuration.
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>     -Chassis br-vtep
>     -    Encap vxlan
>     -        ip: "1.2.3.4"
>     -        options: {csum="false"}
>     -])
>     -
>     -# deletes the chassis via ovn-sbctl and check that it is readded back
>     -# with the log.
>     -AT_CHECK([ovn-sbctl chassis-del br-vtep])
>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>     ovn-controller-vtep.log], [0], [dnl
>     -|WARN|Chassis for VTEP physical switch (br-vtep) disappears,
>     maybe deleted by ovn-sbctl, adding it back
>     -])
>     -
>     -# changes the tunnel_ip on physical switch, watches the update of
>     chassis's
>     -# encap.
>     -AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
>     -AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr
>     -d ' '], [0], [dnl
>     -"1.2.3.5"
>     -])
>     -
>     -# adds vlan_bindings to physical ports.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1
>     300 lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>     lswitch0`"])
>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>     -[[lswitch0]]
>     -])
>     -
>     -# adds another logical switch and new vlan_bindings.
>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300
>     lswitch1])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>     lswitch1`"])
>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -[[lswitch0,lswitch1]]
>     -])
>     -
>     -# unbinds one port from lswitch0, nothing should change.
>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list
>     physical_port p0 | grep -- '200='`"])
>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>     -[[lswitch0,lswitch1]]
>     -])
>     -
>     -# unbinds all ports from lswitch0.
>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep
>     p1 300])
>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>     br-vtep_lswitch0`"])
>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>     -[[lswitch1]]
>     -])
>     -
>     -# unbinds all ports from lswitch1.
>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>     br-vtep_lswitch1`"])
>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -[[]]
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch
>     (br-vtep) disappears/d])
>     -AT_CLEANUP
>     -
>     -
>     -# Tests binding updates.
>     -AT_SETUP([ovn-controller-vtep - binding 1])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# adds logical switch 'lswitch0' and vlan_bindings.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
>     -# adds logical switch port in ovn-nb database, and sets the type
>     and options.
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>     [lswitch0])
>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>     chassis!='[[]]'
>     -# should see one binding, associated to chassis of 'br-vtep'.
>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>     cut -d ':' -f2 | tr -d ' ')
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -${chassis_uuid}
>     -])
>     -
>     -# adds another logical switch 'lswitch1' and vlan_bindings.
>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>     lswitch1])
>     -# adds logical switch port in ovn-nb database for lswitch1.
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep],
>     [lswitch1])
>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1
>     chassis!='[[]]'
>     -# This is allowed, but not recommended, to have two vlan_bindings
>     (to different vtep logical switches)
>     -# from one vtep gateway physical port in one ovn-nb logical swithch.
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>     -
>     -${chassis_uuid}
>     -${chassis_uuid}
>     -])
>     -
>     -# adds another logical switch port in ovn-nb database for lswitch0.
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup],
>     [br-vtep], [lswitch0])
>     -ovn-sbctl --timeout=10 wait-until Port_Binding
>     br-vtep_lswitch0_dup chassis!='[[]]'
>     -# it is not allowed to have more than one ovn-nb logical port for
>     the same
>     -# vtep logical switch on a vtep gateway chassis, so should still
>     see only
>     -# two port_binding entries bound.
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>     | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
>     -
>     -
>     -[[]]
>     -${chassis_uuid}
>     -${chassis_uuid}
>     -])
>     -# confirms the warning log.
>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>     ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g'
>     | uniq], [0], [dnl
>     -|WARN|logical switch (), on vtep gateway chassis () has already
>     been associated with logical port (), ignore logical port ()
>     -])
>     -
>     -# deletes physical ports from vtep.
>     -AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>     br-vtep_lswitch`"])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
>     -# should see empty chassis column in both binding entries.
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>     -
>     -
>     -[[]]
>     -[[]]
>     -[[]]
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>     logical port/d])
>     -AT_CLEANUP
>     -
>     -
>     -# Tests corner case: Binding the vtep logical switch from two
>     different
>     -# datapath.
>     -AT_SETUP([ovn-controller-vtep - binding 2])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# adds logical switch 'lswitch0' and vlan_bindings.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0])
>     -# adds logical switch port in ovn-nb database, and sets the type
>     and options.
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>     [lswitch0])
>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>     chassis!='[[]]'
>     -
>     -# adds another lswitch 'br-void' in ovn-nb database.
>     -AT_CHECK([ovn-nbctl ls-add br-void])
>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>     p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
>     -# adds a conflicting logical port (both br-vtep_lswitch0 and
>     br-vtep-void_lswitch0
>     -# are bound to the same logical switch, but they are on different
>     datapath).
>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0],
>     [br-vtep-void], [lswitch0])
>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>     -# confirms the warning log.
>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>     ovn-controller-vtep.log | sed
>     's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key
>     [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
>     -|WARN|logical switch (), on vtep gateway chassis () has already
>     been associated with logical datapath (), ignore logical port ()
>     which belongs to logical datapath ()
>     -])
>     -
>     -# then deletes 'br-void' and 'br-vtep-void', should see
>     'br-vtep_lswitch0'
>     -# bound correctly.
>     -AT_CHECK([ovn-nbctl ls-del br-void])
>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep
>     br-vtep-void_lswitch0`"])
>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>     cut -d ':' -f2 | tr -d ' ')
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -${chassis_uuid}
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>     logical datapath/d])
>     -AT_CLEANUP
>     -
>     -
>     -# Tests vtep module vtep logical switch tunnel key update.
>     -AT_SETUP([ovn-controller-vtep - vtep-lswitch])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# creates the logical switch in vtep and adds the corresponding
>     logical
>     -# port to 'br-test'.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0])
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>     [lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>     br-vtep_lswitch0`"])
>     -
>     -# retrieves the expected tunnel key.
>     -datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding
>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
>     -tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding
>     ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>     Logical_Switch | grep 0`"])
>     -# checks the vtep logical switch tunnel key configuration.
>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -${tunnel_key}
>     -])
>     -
>     -# creates a second physical switch in vtep database, and binds
>     its p0 vlan-100
>     -# to the same logical switch 'lswitch0'.
>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>     p0 -- bind-ls br-vtep-void p0 100 lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis 
>     | grep -- br-vtep-void`"])
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0],
>     [br-vtep-void], [lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>     br-vtep-void_lswitch0`"])
>     -
>     -# checks the vtep logical switch tunnel key configuration.
>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -${tunnel_key}
>     -])
>     -
>     -# now, deletes br-vtep-void.
>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis 
>     | grep -- br-vtep-void`"])
>     -# checks the vtep logical switch tunnel key configuration.
>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -${tunnel_key}
>     -])
>     -
>     -# changes the ovn-nb logical port type so that it is no longer
>     -# vtep port.
>     -AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>     Logical_Switch | grep 1`"])
>     -# now should see the tunnel key reset.
>     -AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut
>     -d ':' -f2 | tr -d ' '], [0], [dnl
>     -0
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP
>     -AT_CLEANUP
>     -
>     -
>     -# Tests vtep module 'Ucast_Macs_Remote's.
>     -AT_SETUP([ovn-controller-vtep - vtep-macs 1])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# creates a simple logical network with the vtep device and a
>     fake hv chassis
>     -# 'ch0'.
>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>     -
>     -# creates the logical switch in vtep and adds the corresponding
>     logical
>     -# port to 'br-test'.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0])
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>     [lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>     br-vtep_lswitch0`"])
>     -
>     -# adds another lswitch 'br-void' in ovn-nb database.
>     -AT_CHECK([ovn-nbctl ls-add br-void])
>     -# adds fake hv chassis 'ch1'.
>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>     -
>     -# checks Ucast_Macs_Remote creation.
>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>     _uuid`"])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' '], [0], [dnl
>     -"f0:ab:cd:ef:01:02"
>     -])
>     -
>     -# checks physical locator creation.
>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep
>     _uuid`"])
>     -AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut
>     -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
>     -"1.2.3.5"
>     -])
>     -
>     -# checks tunnel creation by ovs-vtep.
>     -OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
>     -AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 |
>     cut -d ':' -f2 | tr -d ' '], [0], [dnl
>     -{remote_ip="1.2.3.5"}
>     -])
>     -
>     -# adds another mac to logical switch port.
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02
>     f0:ab:cd:ef:01:03])
>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>     03`"])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>     -
>     -"f0:ab:cd:ef:01:02"
>     -"f0:ab:cd:ef:01:03"
>     -])
>     -
>     -# removes one mac to logical switch port.
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>     Ucast_Macs_Remote | grep 02`"])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>     -"f0:ab:cd:ef:01:03"
>     -])
>     -
>     -# migrates mac to logical switch port vif1 on 'br-void'.
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>     Ucast_Macs_Remote | grep 03`"])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP
>     -AT_CLEANUP
>     -
>     -
>     -# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
>     -AT_SETUP([ovn-controller-vtep - vtep-macs 2])
>     -OVN_CONTROLLER_VTEP_START
>     -
>     -# creates a simple logical network with the vtep device and a
>     fake hv chassis
>     -# 'ch0'.
>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>     -
>     -# creates another vif in the same logical switch with duplicate mac.
>     -AT_CHECK([ovn-nbctl lsp-add br-test vif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>     -
>     -# creates the logical switch in vtep and adds the corresponding
>     logical
>     -# port to 'br-test'.
>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>     lswitch0])
>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>     [lswitch0])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>     br-vtep_lswitch0`"])
>     -
>     -# checks Ucast_Macs_Remote creation.  Should still only be one
>     entry, since duplicate
>     -# mac in the same logical switch is not allowed.
>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>     _uuid`"])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' '], [0], [dnl
>     -"f0:ab:cd:ef:01:02"
>     -])
>     -# confirms the warning log.
>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>     ovn-controller-vtep.log | sed
>     's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
>     -|WARN|MAC address () has already been known to be on logical port
>     () in the same logical datapath, so just ignore this logical port ()
>     -])
>     -
>     -# deletes vif1.
>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>     -
>     -# adds another lswitch 'br-void' in ovn-nb database.
>     -AT_CHECK([ovn-nbctl ls-add br-void])
>     -# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])
>     -
>     -# creates another logical switch in vtep and adds the
>     corresponding logical
>     -# port to 'br-void'.
>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>     lswitch1])
>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep],
>     [lswitch1])
>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>     br-void_lswitch1`"])
>     -
>     -# checks Ucast_Macs_Remote creation.  Should see two entries
>     since it is allowed
>     -# to have duplicate macs in different logical switches.
>     -OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list
>     Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>     -
>     -"f0:ab:cd:ef:01:02"
>     -"f0:ab:cd:ef:01:02"
>     -])
>     -
>     -OVN_CONTROLLER_VTEP_STOP([/has already been known to be on
>     logical port/d])
>     -AT_CLEANUP
>     diff --git a/tests/ovn-controller.at <http://ovn-controller.at>
>     b/tests/ovn-controller.at <http://ovn-controller.at>
>     deleted file mode 100644
>     index 343c2ab..0000000
>     --- a/tests/ovn-controller.at <http://ovn-controller.at>
>     +++ /dev/null
>     @@ -1,294 +0,0 @@
>     -AT_BANNER([ovn-controller])
>     -
>     -AT_SETUP([ovn-controller - ovn-bridge-mappings])
>     -AT_KEYWORDS([ovn])
>     -ovn_init_db ovn-sb
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0 \
>     -    -- add-br br-eth1 \
>     -    -- add-br br-eth2
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -# Waits until the OVS database contains exactly the specified
>     patch ports.
>     -# Each argument should be of the form BRIDGE PORT PEER.
>     -check_patches () {
>     -    # Generate code to check that the set of patch ports is
>     exactly as
>     -    # specified.
>     -    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name
>     find Interface type=patch | sort' > query
>     -    for patch
>     -    do
>     -        echo $patch
>     -    done | cut -d' ' -f 2 | sort > expout
>     -
>     -    # Generate code to verify that the configuration of each patch
>     -    # port is correct.
>     -    for patch
>     -    do
>     -        set $patch; bridge=$1 port=$2 peer=$3
>     -        echo >>query "ovs-vsctl iface-to-br $port -- get
>     Interface $port type options"
>     -        echo >>expout "$bridge
>     -patch
>     -{peer=$peer}"
>     -    done
>     -
>     -    # Run the query until we get the expected result (or until a
>     timeout).
>     -    #
>     -    # (We use sed to drop all "s from output because ovs-vsctl
>     quotes some
>     -    # of the port names but not others.)
>     -    AT_CAPTURE_FILE([query])
>     -    AT_CAPTURE_FILE([expout])
>     -    AT_CAPTURE_FILE([stdout])
>     -    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
>     -                    diff -u stdout expout >/dev/null])
>     -}
>     -
>     -# Make sure that the configured bridge mappings in the
>     Open_vSwitch db
>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>     -check_bridge_mappings () {
>     -    local_mappings=$1
>     -    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>     -    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get
>     Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e
>     's/\"//g')])
>     -}
>     -
>     -# Initially there should be no patch ports.
>     -check_patches
>     -
>     -# Configure two ovn-bridge mappings, but no patch ports should be
>     created yet
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
>     -check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
>     -check_patches
>     -
>     -# Create a localnet port, but we should still have no patch
>     ports, as they
>     -# won't be created until there's a localnet port on a logical
>     switch with
>     -# another logical port bound to this chassis.
>     -ovn-sbctl \
>     -    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
>     -    -- create Port_Binding datapath=@dp101 logical_port=localnet1
>     tunnel_key=1 \
>     -        type=localnet options:network_name=physnet1
>     -check_patches
>     -
>     -# Create a localnet port on a logical switch with a port bound to
>     this chassis.
>     -# Now we should get some patch ports created.
>     -ovn-sbctl \
>     -    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
>     -    -- create Port_Binding datapath=@dp102 logical_port=localnet2
>     tunnel_key=1 \
>     -        type=localnet options:network_name=physnet1 \
>     -    -- create Port_Binding datapath=@dp102 logical_port=localvif2
>     tunnel_key=2
>     -ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
>     external_ids:iface-id=localvif2
>     -check_patches \
>     -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>     -
>     -# Add logical patch ports to connect new logical datapath.
>     -#
>     -# OVN no longer uses OVS patch ports to implement logical patch
>     ports, so
>     -# the set of OVS patch ports doesn't change.
>     -AT_CHECK([ovn-sbctl \
>     -    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
>     -    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
>     -    -- create Port_Binding datapath=@dp1 logical_port=foo
>     tunnel_key=1 type=patch options:peer=bar \
>     -    -- create Port_Binding datapath=@dp2 logical_port=bar
>     tunnel_key=2 type=patch options:peer=foo \
>     -    -- create Port_Binding datapath=@dp1 logical_port=dp1vif
>     tunnel_key=3 \
>     -| uuidfilt], [0], [<0>
>     -<1>
>     -<2>
>     -<3>
>     -<4>
>     -])
>     -ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif
>     external_ids:iface-id=dp1vif
>     -check_patches \
>     -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>     -
>     -# Delete the mapping and the ovn-bridge-mapping patch ports
>     should go away.
>     -AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids
>     ovn-bridge-mappings])
>     -check_bridge_mappings
>     -check_patches
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP_SBOX([hv])
>     -OVN_CLEANUP_VSWITCH([main])
>     -as ovn-sb
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -
>     -AT_CLEANUP
>     -
>     -# Checks that ovn-controller populates datapath-type and iface-types
>     -# correctly in the Chassis external-ids column.
>     -AT_SETUP([ovn-controller - Chassis external_ids])
>     -AT_KEYWORDS([ovn])
>     -ovn_init_db ovn-sb
>     -
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0 \
>     -    -- add-br br-eth1 \
>     -    -- add-br br-eth2
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>     -
>     -# Make sure that the datapath_type set in the Bridge table
>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>     -check_datapath_type () {
>     -    datapath_type=$1
>     -    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid}
>     external_ids:datapath-type | sed -e 's/"//g') #"
>     -    test "${datapath_type}" = "${chassis_datapath_type}"
>     -}
>     -
>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>     -
>     -ovs-vsctl set Bridge br-int datapath-type=foo
>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>     -
>     -# Change "ovn-bridge-mappings" value. It should not change the
>     "datapath-type".
>     -ovs-vsctl set Open_vSwitch .
>     external_ids:ovn-bridge-mappings=foo-mapping
>     -check_datapath_type foo
>     -
>     -ovs-vsctl set Bridge br-int datapath-type=bar
>     -OVS_WAIT_UNTIL([check_datapath_type bar])
>     -
>     -ovs-vsctl set Bridge br-int datapath-type=\"\"
>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>     -
>     -# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
>     -ovs-vsctl set Open_vSwitch .
>     external_ids:ovn-bridge-datapath-type=foo
>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>     -
>     -# Change the br-int's datapath type to bar.
>     -# It should be reset to foo since ovn-bridge-datapath-type is
>     configured.
>     -ovs-vsctl set Bridge br-int datapath-type=bar
>     -OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int
>     datapath-type`])
>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>     -
>     -ovs-vsctl set Open_vSwitch .
>     external_ids:ovn-bridge-datapath-type=foobar
>     -OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int
>     datapath-type`])
>     -OVS_WAIT_UNTIL([check_datapath_type foobar])
>     -
>     -expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types |
>     tr -d '[[]] ""')
>     -echo "expected_iface_types = ${expected_iface_types}"
>     -chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>     external_ids:iface-types | sed -e 's/\"//g')
>     -echo "chassis_iface_types = ${chassis_iface_types}"
>     -AT_CHECK([test "${expected_iface_types}" = "${chassis_iface_types}"])
>     -
>     -# Change the value of external_ids:iface-types using ovn-sbctl.
>     -# ovn-controller should again set it back to proper one.
>     -ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
>     -OVS_WAIT_UNTIL([
>     -    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>     external_ids:iface-types | sed -e 's/\"//g')
>     -    echo "chassis_iface_types = ${chassis_iface_types}"
>     -    test "${expected_iface_types}" = "${chassis_iface_types}"
>     -])
>     -
>     -# Change the value of external_ids:system-id and make sure it's
>     mirrored
>     -# in the Chassis record in the OVN_Southbound database.
>     -sysid=${sysid}-foo
>     -ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
>     -OVS_WAIT_UNTIL([
>     -    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
>     -    test "${sysid}" = "${chassis_id}"
>     -])
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP_SBOX([hv])
>     -OVN_CLEANUP_VSWITCH([main])
>     -as ovn-sb
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -
>     -AT_CLEANUP
>     -
>     -# Checks that ovn-controller correctly maintains the mapping from
>     the Encap
>     -# table in the Southbound database to OVS in the face of changes
>     on both sides
>     -AT_SETUP([ovn-controller - change Encap properties])
>     -AT_KEYWORDS([ovn])
>     -ovn_init_db ovn-sb
>     -
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0 \
>     -    -- add-br br-eth1 \
>     -    -- add-br br-eth2
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -check_tunnel_property () {
>     -    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
>     -}
>     -
>     -# Start off with a remote chassis supporting STT
>     -ovn-sbctl chassis-add fakechassis stt 192.168.0.2
>     -OVS_WAIT_UNTIL([check_tunnel_property type stt])
>     -
>     -# See if we switch to Geneve as the first choice when it is available
>     -# With multi-VTEP support we support tunnels with different IPs
>     to the
>     -# same chassis, and hence use the IP to annotate the tunnel
>     (along with
>     -# the chassis-id in ovn-chassis-id); if we supply a different IP here
>     -# we won't be able to co-relate this to the tunnel port that was
>     created
>     -# in the previous step and, as a result, will end up creating
>     another tunnel,
>     -# ie. we can't just lookup using "ovn-fakech-0". So, need to use
>     the same IP
>     -# as above, i.e 192.168.0.2, here.
>     -encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap --
>     --id=@encap create encap type=geneve ip="192.168.0.2")
>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>     -
>     -# Check that changes within an encap row are propagated
>     -ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
>     -OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip
>     "\"192.168.0.2\""])
>     -
>     -# Change the type on the OVS side and check than OVN fixes it
>     -ovs-vsctl set interface ovn-fakech-0 type=vxlan
>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>     -
>     -# Delete the port entirely and it should be resurrected
>     -ovs-vsctl del-port ovn-fakech-0
>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP_SBOX([hv])
>     -OVN_CLEANUP_VSWITCH([main])
>     -as ovn-sb
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -
>     -AT_CLEANUP
>     -
>     -# Check ovn-controller connection status to Southbound database
>     -AT_SETUP([ovn-controller - check sbdb connection])
>     -AT_KEYWORDS([ovn])
>     -ovn_init_db ovn-sb
>     -
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0 \
>     -    -- add-br br-eth1 \
>     -    -- add-br br-eth2
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -check_sbdb_connection () {
>     -    test "$(ovs-appctl -t ovn-controller connection-status)" = "$1"
>     -}
>     -
>     -OVS_WAIT_UNTIL([check_sbdb_connection connected])
>     -
>     -ovs-vsctl set open .
>     external_ids:ovn-remote=tcp:192.168.0.10:6642
>     <http://192.168.0.10:6642>
>     -OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
>     -
>     -# reset the remote for clean-up
>     -ovs-vsctl set open .
>     external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP_SBOX([hv])
>     -OVN_CLEANUP_VSWITCH([main])
>     -as ovn-sb
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -
>     -AT_CLEANUP
>     diff --git a/tests/ovn-macros.at <http://ovn-macros.at>
>     b/tests/ovn-macros.at <http://ovn-macros.at>
>     deleted file mode 100644
>     index 7dba42c..0000000
>     --- a/tests/ovn-macros.at <http://ovn-macros.at>
>     +++ /dev/null
>     @@ -1,180 +0,0 @@
>     -# OVN_CLEANUP_VSWITCH(sim)
>     -#
>     -# Gracefully terminate vswitch daemons in the
>     -# specified sandbox.
>     -m4_define([OVN_CLEANUP_VSWITCH],[
>     -    as $1
>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>     -    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -])
>     -
>     -# OVN_CLEANUP_SBOX(sbox)
>     -#
>     -# Gracefully terminate OVN daemons in the specified
>     -# sandbox instance. The sandbox name "vtep" is treated
>     -# as a special case, and is assumed to have ovn-controller-vtep
>     -# and ovs-vtep daemons running instead of ovn-controller.
>     -m4_define([OVN_CLEANUP_SBOX],[
>     -    as $1
>     -    if test "$1" = "vtep"; then
>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>     -        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>     -    else
>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -    fi
>     -    OVN_CLEANUP_VSWITCH([$1])
>     -])
>     -
>     -# OVN_CLEANUP(sim [, sim ...])
>     -#
>     -# Gracefully terminate all OVN daemons, including those in the
>     -# specified sandbox instances.
>     -m4_define([OVN_CLEANUP],[
>     -    m4_foreach([sbox], [$@], [
>     -        OVN_CLEANUP_SBOX([sbox])
>     -    ])
>     -    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 northd-backup
>     -    OVS_APP_EXIT_AND_WAIT([ovn-northd])
>     -
>     -    OVN_CLEANUP_VSWITCH([main])
>     -])
>     -
>     -m4_divert_push([PREPARE_TESTS])
>     -
>     -# ovn_init_db DATABASE
>     -#
>     -# Creates and initializes the given DATABASE (one of "ovn-sb" or
>     "ovn-nb"),
>     -# starts its ovsdb-server instance, and sets the appropriate
>     environment
>     -# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or
>     ovn-nbctl uses the
>     -# database by default.
>     -#
>     -# Usually invoked from ovn_start.
>     -ovn_init_db () {
>     -    echo "creating $1 database"
>     -    local d=$ovs_base/$1
>     -    mkdir "$d" || return 1
>     -    : > "$d"/.$1.db.~lock~
>     -    as $1 ovsdb-tool create "$d"/$1.db
>     "$abs_top_srcdir"/ovn/$1.ovsschema
>     -    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock
>     "$d"/$1.db
>     -    local var=`echo $1_db | tr a-z- A-Z_`
>     -    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
>     -}
>     -
>     -# ovn_start
>     -#
>     -# Creates and initializes ovn-sb and ovn-nb databases and starts
>     their
>     -# ovsdb-server instance, sets appropriate environment variables
>     so that
>     -# ovn-sbctl and ovn-nbctl use them by default, and starts
>     ovn-northd running
>     -# against them.
>     -ovn_start () {
>     -    ovn_init_db ovn-sb; ovn-sbctl init
>     -    ovn_init_db ovn-nb; ovn-nbctl init
>     -
>     -    echo "starting ovn-northd"
>     -    mkdir "$ovs_base"/northd
>     -    as northd start_daemon ovn-northd -v \
>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -
>     -    echo "starting backup ovn-northd"
>     -    mkdir "$ovs_base"/northd-backup
>     -    as northd-backup start_daemon ovn-northd -v \
>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -}
>     -
>     -# Interconnection networks.
>     -#
>     -# When multiple sandboxed Open vSwitch instances exist, one will
>     inevitably
>     -# want to connect them together.  These commands allow for that. 
>     Conceptually,
>     -# an interconnection network is a switch for which these
>     functions make it easy
>     -# to plug into other switches in other sandboxed Open vSwitch
>     instances.
>     -# Interconnection networks are implemented as bridges in a switch
>     named "main",
>     -# so to use interconnection networks please avoid working with
>     that switch
>     -# directly.
>     -
>     -# net_add NETWORK
>     -#
>     -# Creates a new interconnection network named NETWORK.
>     -net_add () {
>     -    test -d "$ovs_base"/main || sim_add main || return 1
>     -    as main ovs-vsctl add-br "$1"
>     -}
>     -
>     -# net_attach NETWORK BRIDGE
>     -#
>     -# Adds a new port to BRIDGE in the default sandbox (as set with
>     as()) and plugs
>     -# it into the NETWORK interconnection network.  NETWORK must
>     already have been
>     -# created by a previous invocation of net_add.  The default
>     sandbox must not be
>     -# "main".
>     -net_attach () {
>     -    local net=$1 bridge=$2
>     -
>     -    local port=${sandbox}_$bridge
>     -    as main ovs-vsctl \
>     -        -- add-port $net $port \
>     -        -- set Interface $port
>     options:pstream="punix:$ovs_base/main/$port.sock"
>     options:rxq_pcap="$ovs_base/main/$port-rx.pcap"
>     options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
>     -        || return 1
>     -
>     -    ovs-vsctl \
>     -        -- set Interface $bridge
>     options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap"
>     options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
>     -        -- add-port $bridge ${bridge}_$net \
>     -        -- set Interface ${bridge}_$net
>     options:stream="unix:$ovs_base/main/$port.sock"
>     options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap"
>     options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
>     -        || return 1
>     -}
>     -
>     -# ovn_attach NETWORK BRIDGE IP [MASKLEN]
>     -#
>     -# First, this command attaches BRIDGE to interconnection network
>     NETWORK, just
>     -# like "net_attach NETWORK BRIDGE".  Second, it configures
>     (simulated) IP
>     -# address IP (with network mask length MASKLEN, which defaults to
>     24) on
>     -# BRIDGE.  Finally, it configures the Open vSwitch database to
>     work with OVN
>     -# and starts ovn-controller.
>     -ovn_attach() {
>     -    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
>     -    net_attach $net $bridge || return 1
>     -
>     -    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g`
>     -    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
>     -    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen
>     >/dev/null || return 1
>     -    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null ||
>     return 1
>     -    ovs-vsctl \
>     -        -- set Open_vSwitch . external-ids:system-id=$sandbox \
>     -        -- set Open_vSwitch .
>     external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>     -        -- set Open_vSwitch .
>     external-ids:ovn-encap-type=geneve,vxlan \
>     -        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
>     -        -- add-br br-int \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true \
>     -        || return 1
>     -    start_daemon ovn-controller || return 1
>     -}
>     -
>     -# OVN_POPULATE_ARP
>     -#
>     -# This pre-populates the ARP tables of all of the OVN instances
>     that have been
>     -# started with ovn_attach().  That means that packets sent from
>     one hypervisor
>     -# to another never get dropped or delayed by ARP resolution,
>     which makes
>     -# testing easier.
>     -ovn_populate_arp__() {
>     -    for e1 in $arp_table; do
>     -        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4
>     -        for e2 in $arp_table; do
>     -            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
>     -            if test $sb1,$br1 != $sb2,$br2; then
>     -                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac ||
>     return 1
>     -            fi
>     -        done
>     -    done
>     -}
>     -m4_divert_pop([PREPARE_TESTS])
>     -
>     -m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0],
>     [ignore])])
>     diff --git a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>     b/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>     deleted file mode 100644
>     index d99d3af..0000000
>     --- a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>     +++ /dev/null
>     @@ -1,1660 +0,0 @@
>     -AT_BANNER([ovn-nbctl])
>     -
>     -OVS_START_SHELL_HELPERS
>     -# OVN_NBCTL_TEST_START
>     -m4_define([OVN_NBCTL_TEST_START],
>     -  [AT_KEYWORDS([ovn])
>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>     -   ovn_nbctl_test_start $1])
>     -ovn_nbctl_test_start() {
>     -   dnl Create ovn-nb database.
>     -   AT_CHECK([ovsdb-tool create ovn-nb.db
>     $abs_top_srcdir/ovn/ovn-nb.ovsschema])
>     -
>     -   dnl Start ovsdb-server.
>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>     --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db],
>     [0], [], [stderr])
>     -   on_exit "kill `cat ovsdb-server.pid`"
>     -   AS_CASE([$1],
>     -     [daemon],
>     -       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach
>     --no-chdir --log-file -vsocket_util:off)
>     -        on_exit "kill `cat ovn-nbctl.pid`"],
>     -     [direct], [],
>     -     [*], [AT_FAIL_IF(:)])
>     -   AT_CHECK([ovn-nbctl init])
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d
>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>     -}
>     -
>     -# OVN_NBCTL_TEST_STOP
>     -m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
>     -ovn_nbctl_test_stop() {
>     -   AT_CHECK([check_logs "$1"])
>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -}
>     -OVS_END_SHELL_HELPERS
>     -
>     -# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
>     -m4_define([OVN_NBCTL_TEST],
>     -   [OVS_START_SHELL_HELPERS
>     -    $1() {
>     -      $3
>     -    }
>     -    OVS_END_SHELL_HELPERS
>     -
>     -    AT_SETUP([ovn-nbctl - $2 - direct])
>     -    OVN_NBCTL_TEST_START direct
>     -    $1
>     -    OVN_NBCTL_TEST_STOP
>     -    AT_CLEANUP
>     -
>     -    AT_SETUP([ovn-nbctl - $2 - daemon])
>     -    OVN_NBCTL_TEST_START daemon
>     -    $1
>     -    OVN_NBCTL_TEST_STOP
>     -    AT_CLEANUP])
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>     -<0> (ls0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-add ls1])
>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>     -<0> (ls0)
>     -<1> (ls1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-del ls0])
>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>     -<0> (ls1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl show ls0])
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>     -  [switch <0> (ls0)
>     -])
>     -AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
>     -  [ovn-nbctl: ls0: a switch with this name already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>     -  [switch <0> (ls0)
>     -])
>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], [1], [],
>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>     together
>     -])
>     -AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
>     -  [ovn-nbctl: Multiple logical switches named 'ls0'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
>     -  [ovn-nbctl: ls2: switch name not found
>     -])
>     -AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
>     -
>     -AT_CHECK([ovn-nbctl ls-add])
>     -AT_CHECK([ovn-nbctl ls-add])
>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
>     -  [ovn-nbctl: --may-exist requires specifying a name
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port
>     commands], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
>     -  [ovn-nbctl: lp0: a port with this name already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>     -<0> (lp0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>     -<0> (lp0)
>     -<1> (lp1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-add ls1])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
>     -  [ovn-nbctl: lp1: a port with this name already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
>     -  [ovn-nbctl: lp1: port already exists but in switch ls0
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
>     -  [ovn-nbctl: lp1: port already exists but has no parent
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-del lp1])
>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>     -<0> (lp0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
>     -  [ovn-nbctl: lp2: port already exists with different parent lp3
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
>     -  [ovn-nbctl: lp2: port already exists with different tag_request 5
>     -])
>     -AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
>     -  [ovn-nbctl: lp2: port already exists but has no tag_request
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -
>     -AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
>     -<0> (ls0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
>     -  [ovn-nbctl: lp1: port name not found
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 unknown])
>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>     -00:11:22:33:44:55
>     -unknown
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff
>     00:11:22:33:44:55])
>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>     -00:11:22:33:44:55
>     -aa:bb:cc:dd:ee:ff
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
>     -ovn_nbctl_test_acl() {
>     -   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop])
>     -   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info
>     acl-add $1 to-lport 500 udp drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
>     -   dnl Add duplicated ACL
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1],
>     [], [stderr])
>     -   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>     -   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip
>     drop])
>     -
>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>     -from-lport   600 (udp) drop log()
>     -from-lport   400 (tcp) drop
>     -from-lport   200 (ip) drop
>     -  to-lport   500 (udp) drop log(name=test,severity=info)
>     -  to-lport   300 (tcp) drop
>     -  to-lport   100 (ip) drop
>     -])
>     -
>     -   dnl Delete in one direction.
>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>     -from-lport   600 (udp) drop log()
>     -from-lport   400 (tcp) drop
>     -from-lport   200 (ip) drop
>     -])
>     -
>     -   dnl Delete all ACLs.
>     -   AT_CHECK([ovn-nbctl $2 acl-del $1])
>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>     -])
>     -
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>     -
>     -   dnl Delete a single flow.
>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>     -from-lport   600 (udp) drop
>     -from-lport   200 (ip) drop
>     -])
>     -}
>     -
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -ovn_nbctl_test_acl ls0
>     -AT_CHECK([ovn-nbctl ls-add ls1])
>     -ovn_nbctl_test_acl ls1 --type=switch
>     -AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
>     -ovn_nbctl_test_acl pg0 --type=port-group
>     -
>     -dnl Test when port group doesn't exist
>     -AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip
>     drop], [1], [], [dnl
>     -ovn-nbctl: pg1: port group name not found
>     -])
>     -
>     -dnl Test when same name exists in logical switches and portgroups
>     -AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
>     -AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [],
>     [stderr])
>     -AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip
>     drop], [0], [ignore])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100
>     burst=1000])
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0
>     rate=300 burst=3000])
>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301
>     burst=30000])
>     -
>     -dnl Add duplicated qos
>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302
>     burst=30002], [1], [], [stderr])
>     -AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4
>     dscp=11 rate=302 burst=30002])
>     -
>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>     -from-lport   600 (tcp) dscp=63
>     -from-lport   500 (udp) rate=100 burst=1000
>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>     -  to-lport   300 (tcp) dscp=48
>     -  to-lport   200 (ip) rate=101
>     -  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
>     -])
>     -
>     -dnl Delete in one direction.
>     -AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>     -from-lport   600 (tcp) dscp=63
>     -from-lport   500 (udp) rate=100 burst=1000
>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>     -])
>     -
>     -dnl Delete all qos_rules.
>     -AT_CHECK([ovn-nbctl qos-del ls0])
>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102
>     rate=301 dscp=19])
>     -
>     -dnl Delete a single flow.
>     -AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>     -from-lport   600 (ip) rate=1000101
>     -from-lport   200 (ip) rate=301 burst=1000102 dscp=19
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>     rate=100010111111], [1], [],
>     -[ovn-nbctl: 100010111111: rate must be in the range 1...4294967295
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>     burst=100010111112 rate=100010], [1], [],
>     -[ovn-nbctl: 100010111112: burst must be in the range 1...4294967295
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], [1], [],
>     -[ovn-nbctl: -1: dscp must be in the range 0...63
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], [],
>     -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=",
>     and "burst="
>     -])
>     -
>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123],
>     [1], [],
>     -[ovn-nbctl: Either "rate" and/or "dscp" must be specified
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
>     -AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
>     -AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
>     -AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
>     -
>     -dnl Add duplicate meter name
>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [],
>     [stderr])
>     -AT_CHECK([grep 'already exists' stderr], [0], [ignore])
>     -
>     -dnl Add reserved meter name
>     -AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [],
>     [stderr])
>     -AT_CHECK([grep 'reserved' stderr], [0], [ignore])
>     -
>     -dnl Add meter with invalid rates
>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps],
>     [1], [],
>     -[ovn-nbctl: rate must be in the range 1...4294967295
>     -])
>     -
>     -dnl Add meter with invalid rates
>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], [1], [],
>     -[ovn-nbctl: rate must be in the range 1...4294967295
>     -])
>     -
>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
>     -[ovn-nbctl: rate must be in the range 1...4294967295
>     -])
>     -
>     -dnl Add meter with invalid burst
>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps],
>     [1], [],
>     -[ovn-nbctl: unit must be "kbps" or "pktps"
>     -])
>     -
>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>     -meter1: bands:
>     -  drop: 10 kbps
>     -meter2: bands:
>     -  drop: 3 kbps, 2 kb burst
>     -meter3: bands:
>     -  drop: 100 kbps, 200 kb burst
>     -meter4: bands:
>     -  drop: 10 pktps, 30 packet burst
>     -])
>     -
>     -dnl Delete a single meter.
>     -AT_CHECK([ovn-nbctl meter-del meter2])
>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>     -meter1: bands:
>     -  drop: 10 kbps
>     -meter3: bands:
>     -  drop: 100 kbps, 200 kb burst
>     -meter4: bands:
>     -  drop: 10 pktps, 30 packet burst
>     -])
>     -
>     -dnl Delete all meters.
>     -AT_CHECK([ovn-nbctl meter-del])
>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2],
>     [1], [],
>     -[ovn-nbctl: snatt: type must be one of "dnat", "snat" and
>     "dnat_and_snat".
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2],
>     [1], [],
>     -[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], [1], [],
>     -[ovn-nbctl: 30.0.0: should be an IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24
>     <http://30.0.0.2/24> 192.168.1.2], [1], [],
>     -[ovn-nbctl: 30.0.0.2/24 <http://30.0.0.2/24>: should be an IPv4
>     address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80
>     <http://30.0.0.2:80> 192.168.1.2], [1], [],
>     -[ovn-nbctl: 30.0.0.2:80 <http://30.0.0.2:80>: should be an IPv4
>     address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a],
>     [1], [],
>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], [1], [],
>     -[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80
>     <http://192.168.1.2:80>], [1], [],
>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>     IPv4 address or network.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a
>     <http://192.168.1.2/a>], [1], [],
>     -[ovn-nbctl: 192.168.1.2/a <http://192.168.1.2/a>: should be an
>     IPv4 address or network.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a],
>     [1], [],
>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], [1], [],
>     -[ovn-nbctl: 192.168.1: should be an IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80
>     <http://192.168.1.2:80>], [1], [],
>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>     IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24
>     <http://192.168.1.2/24>], [1], [],
>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>     IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>     192.168.1.2/24 <http://192.168.1.2/24>], [1], [],
>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>     IPv4 address.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>     192.168.1.2 lp0], [1], [],
>     -[ovn-nbctl: lr-nat-add with logical_port must also specify
>     external_mac.
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
>     00:00:00:01:02:03], [1], [],
>     -[ovn-nbctl: logical_port and external_mac are only valid when
>     type is "dnat_and_snat".
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
>     00:00:00:01:02:03], [1], [],
>     -[ovn-nbctl: logical_port and external_mac are only valid when
>     type is "dnat_and_snat".
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>     192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
>     -[ovn-nbctl: lp0: port name not found
>     -])
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>     192.168.1.2 lp0 00:00:00:01:02], [1], [],
>     -[ovn-nbctl: invalid mac address 00:00:00:01:02.
>     -])
>     -
>     -dnl Add snat and dnat
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>     <http://192.168.1.0/24>])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>     192.168.1.2])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>     192.168.1.3 lp0 00:00:00:01:02:03])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC     
>        LOGICAL_PORT
>     -dnat             30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.2           192.168.1.3
>      00:00:00:01:02:03    lp0
>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>     <http://192.168.1.0/24>], [1], [],
>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>     NAT with this external_ip and logical_ip already exists
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24
>     <http://192.168.1.10/24>], [1], [],
>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>     NAT with this external_ip and logical_ip already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1
>     192.168.1.0/24 <http://192.168.1.0/24>])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24
>     <http://192.168.1.0/24>], [1], [],
>     -[ovn-nbctl: a NAT with this type (snat) and logical_ip
>     (192.168.1.0/24 <http://192.168.1.0/24>) already exists
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2],
>     [1], [],
>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>     with this external_ip and logical_ip already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1
>     192.168.1.2])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3],
>     [1], [],
>     -[ovn-nbctl: a NAT with this type (dnat) and external_ip
>     (30.0.0.1) already exists
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>     192.168.1.2], [1], [],
>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>     with this external_ip and logical_ip already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>     30.0.0.1 192.168.1.2])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>     192.168.1.3], [1], [],
>     -[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
>     (30.0.0.1) already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>     30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC     
>        LOGICAL_PORT
>     -dnat             30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.2           192.168.1.3
>      00:00:00:04:05:06    lp0
>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>     30.0.0.2 192.168.1.3])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC     
>        LOGICAL_PORT
>     -dnat             30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.2           192.168.1.3
>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>     -])
>     -
>     -dnl Deletes the NATs
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
>     -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and
>     external_ip (30.0.0.3)
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
>     -[ovn-nbctl: no matching NAT with the type (dnat) and external_ip
>     (30.0.0.2)
>     -])
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24
>     <http://192.168.10.0/24>], [1], [],
>     -[ovn-nbctl: no matching NAT with the type (snat) and logical_ip
>     (192.168.10.0/24 <http://192.168.10.0/24>)
>     -])
>     -AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat
>     192.168.10.0/24 <http://192.168.10.0/24>])
>     -
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC     
>        LOGICAL_PORT
>     -dnat             30.0.0.1           192.168.1.2
>     -dnat_and_snat    30.0.0.2           192.168.1.3
>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC     
>        LOGICAL_PORT
>     -dnat_and_snat    30.0.0.2           192.168.1.3
>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
>     -dnl Add two LBs.
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp], [1], [],
>     -[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP
>     address and a port number with : as a separator).
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp], [1], [],
>     -[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP
>     address and a port number with : as a separator).
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80
>     <http://30.0.0.10:80> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20 tcp], [1], [],
>     -[ovn-nbctl: 192.168.10.20 <http://192.168.10.20>: should be an IP
>     address and a port number with : as a separator.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>], [1], [],
>     -[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address
>     and a port number with : as a separator).
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>], [1], [],
>     -[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and
>     a port number with : as a separator).
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>     192.168.10.10,192.168.10.20:80 <http://192.168.10.20:80>], [1], [],
>     -[ovn-nbctl: 192.168.10.20:80 <http://192.168.10.20:80>: should be
>     an IP address.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>     192.168.10.10:a80], [1], [],
>     -[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>     192.168.10.10:], [1], [],
>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>:: should be an
>     IP address.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>     192.168.10.1a], [1], [],
>     -[ovn-nbctl: 192.168.10.1a: should be an IP address.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 <http://30.0.0.10>:
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp], [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900
>     <http://192.168.10.10:900> tcp], [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -dnl Add ips to lb
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,,])
>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,192.168.10.20:80
>     <http://192.168.10.20:80>,,,,])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>
>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -])
>     -AT_CHECK([ovn-nbctl lb-del lb0])
>     -AT_CHECK([ovn-nbctl lb-del lb1])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>])
>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -])
>     -
>     -dnl Update the VIP of the lb1.
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>     <http://30.0.0.10:80> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>     <http://30.0.0.10:80> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080> udp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     -])
>     -
>     -dnl Config lb1 with another VIP.
>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 <http://30.0.0.20:80>
>     192.168.10.10:80 <http://192.168.10.10:80> udp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     - udp 30.0.0.20:80 <http://30.0.0.20:80> 192.168.10.10:80
>     <http://192.168.10.10:80>
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80 <http://30.0.0.20:80>])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     -])
>     -
>     -dnl Add LBs whose vip is just an IP address.
>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     -<2>    lb2                 tcp/udp    30.0.0.30  192.168.10.10
>     -<3>    lb3                 tcp/udp    30.0.0.30  192.168.10.10
>     -])
>     -AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
>     -AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp])
>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>            IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>     <http://192.168.10.20:8080>
>     -<2>    lb2                 tcp 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>     -<3>    lb2                 tcp 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>     -])
>     -
>     -dnl If there are multiple load balancers with the same name, use
>     a UUID to update/delete.
>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> tcp], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>     <http://30.0.0.10:80> 192.168.10.10:8080
>     <http://192.168.10.10:8080>,192.168.10.20:8080
>     <http://192.168.10.20:8080> udp])
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:8080
>     <http://192.168.10.10:8080>,192.168.10.20:8080
>     <http://192.168.10.20:8080> udp])
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090
>     <http://30.0.0.10:9090> 192.168.10.10:8080
>     <http://192.168.10.10:8080>,192.168.10.20:8080
>     <http://192.168.10.20:8080> udp])
>     -AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80 <http://30.0.0.10:80>])
>     -AT_CHECK([ovn-nbctl lb-del lb1])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>            IPs
>     -<0>    lb2                 tcp 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>     -<1>    lb2                 tcp 30.0.0.10:8080
>     <http://30.0.0.10:8080> 192.168.10.10:80
>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>     -])
>     -
>     -dnl Add load balancer to logical switch.
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>])
>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80> udp])
>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10
>     192.168.10.10,192.168.10.20])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<2>    lb3                 tcp/udp    30.0.0.10
>      192.168.10.10,192.168.10.20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb3                 tcp/udp    30.0.0.10
>      192.168.10.10,192.168.10.20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>     -
>     -dnl Remove all load balancers from logical switch.
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>     -
>     -dnl Add load balancer to logical router.
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<2>    lb3                 tcp/udp    30.0.0.10
>      192.168.10.10,192.168.10.20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>          IPs
>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>     <http://192.168.10.20:80>
>     -<1>    lb3                 tcp/udp    30.0.0.10
>      192.168.10.10,192.168.10.20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>     -
>     -dnl Remove all load balancers from logical router.
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>     -
>     -dnl Remove load balancers after adding them to a logical
>     router/switch.
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl lb-del lb0])
>     -AT_CHECK([ovn-nbctl lb-del lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
>     -dnl A bunch of commands that should fail
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>     -[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP
>     address and a port number with : as a separator).
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>     -[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP
>     address and a port number with : as a separator).
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80
>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>     -[ovn-nbctl: fd0f::20: should be an IP address and a port number
>     with : as a separator.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff
>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>     -[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP
>     address and a port number with : as a separator).
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>     [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
>     -[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>     fd0f::10,[[fd0f::20]]:80], [1], [],
>     -[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>     [[fd0f::10]]:a80], [1], [],
>     -[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>     [[fd0f::10]]:], [1], [],
>     -[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>     fd0f::1001a], [1], [],
>     -[ovn-nbctl: fd0f::1001a: should be an IP address.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp],
>     [1], [],
>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>     family is different from VIP ae0f::10.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>     family is different from VIP ae0f::10.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80
>     <http://192.168.10.10:80>], [1], [],
>     -[ovn-nbctl: 192.168.10.10:80 <http://192.168.10.10:80>: IP
>     address family is different from VIP [[ae0f::10]]:80.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
>     -[ovn-nbctl: ae0f::10: IP address family is different from VIP
>     30.0.0.10.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>     [[ae0f::10]]:80], [1], [],
>     -[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from
>     VIP 30.0.0.10:80 <http://30.0.0.10:80>.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
>     -AT_CHECK([ovn-nbctl lb-add lb0
>     ae0f:0000:0000:0000:0000:0000:0000:0010 fd0f::20],
>     -[1], [], [ovn-nbctl: lb0: a load balancer with this vip
>     (ae0f::10) already exists
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-del lb0])
>     -
>     -dnl Add ips to lb
>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>     ,,,[[fd0f::10]]:80,,,,,])
>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>     ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80    [[fd0f::10]]:80
>     -<1>    lb1                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -])
>     -AT_CHECK([ovn-nbctl lb-del lb0])
>     -AT_CHECK([ovn-nbctl lb-del lb1])
>     -
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -])
>     -
>     -dnl Update the VIP of the lb1.
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:8080])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     -])
>     -
>     -dnl Config lb1 with another VIP.
>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 udp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     - udp        [[ae0f::20]]:80    [[fd0f::10]]:80
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     -])
>     -
>     -dnl Add LBs whose vip is just an IP address.
>     -AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     -<2>    lb2                 tcp/udp    ae0f::30  fd0f::10
>     -<3>    lb3                 tcp/udp    ae0f::30  fd0f::10
>     -])
>     -AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
>     -AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
>     -
>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>             IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80     
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80     
>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>     -<2>    lb2                 tcp [[ae0f::10]]:8080   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<3>    lb2                 tcp [[ae0f::10]]:8080   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -])
>     -
>     -dnl If there are multiple load balancers with the same name, use
>     a UUID to update/delete.
>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080
>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090
>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>     -AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
>     -AT_CHECK([ovn-nbctl lb-del lb1])
>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>             IPs
>     -<0>    lb2                 tcp [[ae0f::10]]:8080   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb2                 tcp [[ae0f::10]]:8080   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -])
>     -
>     -dnl Add load balancer to logical switch.
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>     [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>     -
>     -dnl Remove all load balancers from logical switch.
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>     -
>     -dnl Add load balancer to logical router.
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>     -])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb0                 tcp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>     -UUID                                    LB PROTO      VIP       
>           IPs
>     -<0>    lb1                 udp [[ae0f::10]]:80   
>     [[fd0f::10]]:80,[[fd0f::20]]:80
>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>     -
>     -dnl Remove all load balancers from logical router.
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router
>     commands], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>     -<0> (lr0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-add lr1])
>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>     -<0> (lr0)
>     -<1> (lr1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-del lr0])
>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>     -<0> (lr1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl show lr0])
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>     -  [router <0> (lr0)
>     -])
>     -AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
>     -  [ovn-nbctl: lr0: a router with this name already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>     -  [router <0> (lr0)
>     -])
>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], [1], [],
>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>     together
>     -])
>     -AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
>     -  [ovn-nbctl: Multiple logical routers named 'lr0'.  Use a UUID.
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
>     -  [ovn-nbctl: lr2: router name not found
>     -])
>     -AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
>     -
>     -AT_CHECK([ovn-nbctl lr-add])
>     -AT_CHECK([ovn-nbctl lr-add])
>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
>     -  [ovn-nbctl: --may-exist requires specifying a name
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port
>     commands], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02
>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
>     -])
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04
>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24>])
>     -
>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
>     -router <0> (lr0)
>     -    port lrp0
>     -        mac: "00:00:00:01:02:03"
>     -        networks: [["192.168.1.1/24 <http://192.168.1.1/24>"]]
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp0: a port with this name already exists
>     -])
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>])
>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>     -<0> (lrp0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24> peer=lrp1-peer])
>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>     -<0> (lrp0)
>     -<1> (lrp1)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-add lr1])
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp1: a port with this name already exists
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp1: port already exists but in router lr0
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:04:05:06 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp1: port already exists with mac 00:00:00:01:02:03
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>     -  [ovn-nbctl: lrp1: port already exists with mismatching peer
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24>
>     peer=lrp1-peer], [1], [],
>     -  [ovn-nbctl: lrp1: port already exists with different network
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>     peer=lrp1-peer])
>     -
>     -AT_CHECK([ovn-nbctl lrp-del lrp1])
>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>     -<0> (lrp0)
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>     10.0.0.1/24 <http://10.0.0.1/24> peer=lrp1-peer])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>     172.16.0.1/24 <http://172.16.0.1/24> peer=lrp1-peer], [1], [],
>     -  [ovn-nbctl: lrp1: port already exists with different network
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24> 192.168.1.1/24
>     <http://192.168.1.1/24> peer=lrp1-peer])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port
>     gateway chassis], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24>])
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
>     -
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], [],
>     -[ovn-nbctl: lp0: port name not found
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
>     -[ovn-nbctl: lp0: port name not found
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], [],
>     -[ovn-nbctl: lp0: port name not found
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], [1], [],
>     -[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
>     -])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
>     -
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis1     0
>     -])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
>     -
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis1    10
>     -])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
>     -
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis1    20
>     -])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis1    20
>     -lrp0-chassis2     5
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis2     5
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
>     -
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>     -lrp0-chassis2    10
>     -lrp0-chassis3     5
>     -lrp0-chassis1     1
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port
>     enable and disable], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>     192.168.1.1/24 <http://192.168.1.1/24>])
>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
>     -  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -
>     -dnl Check IPv4 routes
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>     192.168.0.1])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24
>     <http://10.0.1.0/24> 11.0.1.1 lp0])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>     <http://10.0.0.1/24> 11.0.0.2])
>     -
>     -dnl Add overlapping route with 10.0.0.1/24 <http://10.0.0.1/24>
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>     <http://10.0.0.111/24> 11.0.0.1], [1], [],
>     -  [ovn-nbctl: duplicate prefix: 10.0.0.0/24 <http://10.0.0.0/24>
>     -])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1],
>     [1], [],
>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
>     -])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a
>     <http://10.0.0.111/24a> 11.0.0.1], [1], [],
>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
>     <http://10.0.0.111/24a>
>     -])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>     <http://10.0.0.111/24> 11.0.0.1a], [1], [],
>     -  [ovn-nbctl: bad next hop argument: 11.0.0.1a
>     -])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>     <http://10.0.0.111/24> 11.0.0.1/24 <http://11.0.0.1/24>], [1], [],
>     -  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
>     <http://11.0.0.1/24>
>     -])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>     2001:0db8:0:f103::1/64], [1], [],
>     -  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>     <http://10.0.0.111/24> 11.0.0.1])
>     -AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24
>     <http://9.16.1.0/24> 11.0.0.1])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv4 Routes
>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip
>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip lp0
>     - 9.16.1.0/24 <http://9.16.1.0/24>                 11.0.0.1 src-ip
>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>     <http://10.0.0.111/24> 11.0.0.1 lp1])
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv4 Routes
>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip lp1
>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip lp0
>     - 9.16.1.0/24 <http://9.16.1.0/24>                 11.0.0.1 src-ip
>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>     -])
>     -
>     -dnl Delete non-existent prefix
>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24
>     <http://10.0.2.1/24>], [1], [],
>     -  [ovn-nbctl: no matching prefix: 10.0.2.0/24 <http://10.0.2.0/24>
>     -])
>     -AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24
>     <http://10.0.2.1/24>])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24
>     <http://10.0.1.1/24>])
>     -AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24
>     <http://9.16.1.0/24>])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv4 Routes
>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip lp1
>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -])
>     -
>     -dnl Check IPv6 routes
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>     2001:0db8:0:f101::1])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>     2001:0db8:0:f102::1 lp0])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>     2001:0db8:0:f103::1])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv6 Routes
>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv6 Routes
>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -])
>     -
>     -dnl Check IPv4 and IPv6 routes
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>     192.168.0.1])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24
>     <http://10.0.1.1/24> 11.0.1.1 lp0])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>     <http://10.0.0.1/24> 11.0.0.1])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>     2001:0db8:0:f101::1])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>     2001:0db8:0:f102::1 lp0])
>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>     2001:0db8:0:f103::1])
>     -
>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>     -IPv4 Routes
>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip
>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip lp0
>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>     -
>     -IPv6 Routes
>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
>     -AT_CHECK([ovn-nbctl lr-add lr0])
>     -
>     -dnl Add policies with allow and drop actions
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>     <http://1.1.1.0/24>" drop])
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24
>     <http://1.1.2.0/24>" allow])
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24
>     <http://2.1.1.0/24>" allow])
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24
>     <http://2.1.2.0/24>" drop])
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64"
>     drop])
>     -
>     -dnl Add duplicated policy
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>     <http://1.1.1.0/24>" drop], [1], [],
>     -  [ovn-nbctl: Same routing policy already existed on the logical
>     router lr0.
>     -])
>     -
>     -dnl Add duplicated policy
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24
>     <http://1.1.1.0/24>" deny], [1], [],
>     -  [ovn-nbctl: deny: action must be one of "allow", "drop", and
>     "reroute"
>     -])
>     -
>     -dnl Delete by priority and match string
>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24
>     <http://1.1.1.0/24>"])
>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>     -Routing Policies
>     -       101                              ip4.src == 2.1.1.0/24
>     <http://2.1.1.0/24>           allow
>     -       101                              ip4.src == 2.1.2.0/24
>     <http://2.1.2.0/24>            drop
>     -       101                               ip6.src == 2002::/64   
>             drop
>     -       100                              ip4.src == 1.1.2.0/24
>     <http://1.1.2.0/24>           allow
>     -])
>     -
>     -dnl Delete all policies for given priority
>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>     -Routing Policies
>     -       100                              ip4.src == 1.1.2.0/24
>     <http://1.1.2.0/24>           allow
>     -])
>     -
>     -dnl Add policy with reroute action
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24
>     <http://3.1.2.0/24>" reroute 3.3.3.3])
>     -
>     -dnl Add policy with invalid reroute ip
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24
>     <http://3.1.2.0/24>" reroute 3.3.3.x], [1], [],
>     -  [ovn-nbctl: bad next hop argument: 3.3.3.x
>     -])
>     -
>     -dnl Add policy with reroute action
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64"
>     reroute 2002::5])
>     -
>     -dnl Add policy with invalid reroute ip
>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64"
>     reroute 2002::x], [1], [],
>     -  [ovn-nbctl: bad next hop argument: 2002::x
>     -])
>     -
>     -])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>     -
>     -dnl switchport type defaults to empty
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -
>     -])
>     -
>     -dnl The following are the valid entries for
>     -dnl switchport type
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -l2gateway
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -router
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -localnet
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -localport
>     -])
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -vtep
>     -])
>     -
>     -dnl All of these are valid southbound port types but
>     -dnl should be rejected for northbound logical switch
>     -dnl ports.
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
>     -ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized.
>     Not setting type.
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
>     -ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not
>     setting type.
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], [], [dnl
>     -ovn-nbctl: Logical switch port type 'chassisredirect' is
>     unrecognized. Not setting type.
>     -])
>     -
>     -dnl switch port type should still be "vtep" since previous
>     -dnl commands failed.
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -vtep
>     -])
>     -
>     -dnl Attempt a nonsense type
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
>     -ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not
>     setting type.
>     -])
>     -
>     -dnl Empty string should work too
>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>     -
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
>     -AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection
>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
>     -AT_CHECK([ovn-nbctl list connection | grep inactivity_probe],
>     [0], [dnl
>     -inactivity_probe    : 30000
>     -inactivity_probe    : 30000
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
>     -dnl Check that dry run has no permanent effect.
>     -AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt],
>     [0], [dnl
>     -<0> (ls0)
>     -])
>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>     -])
>     -
>     -dnl Check that dry-run mode is not sticky.
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>     -<0> (ls0)
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
>     -AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
>     -
>     -dnl Expect one line for one command.
>     -AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
>     -<0> (ls0)\n<1> (ls1)
>     -])
>     -
>     -dnl Expect lines for two commands.
>     -AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt],
>     [0], [dnl
>     -<0> (ls0)\n<1> (ls1)
>     -<0> (ls0)\n<1> (ls1)
>     -])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error
>     paths], [
>     -dnl FIXME: Duplicate options are allowed when passed with global
>     options.
>     -dnl        For example: ovn-nbctl --if-exists --if-exists list
>     Logical_Switch
>     -
>     -dnl Duplicate option
>     -AT_CHECK([ovn-nbctl -- --if-exists --if-exists list
>     Logical_Switch], [1], [], [stderr])
>     -AT_CHECK([grep 'option specified multiple times' stderr], [0],
>     [ignore])
>     -
>     -dnl Missing command
>     -AT_CHECK([ovn-nbctl], [1], [], [stderr])
>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl --], [1], [], [stderr])
>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>     -
>     -dnl Unknown command
>     -AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>     -
>     -dnl Unknown option
>     -AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], [stderr])
>     -AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], [stderr])
>     -AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
>     -
>     -dnl Missing option argument
>     -AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
>     -AT_CHECK([grep 'option .* requires an argument' stderr], [0],
>     [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [],
>     [stderr])
>     -AT_CHECK([grep 'missing argument to .* option' stderr], [0],
>     [ignore])
>     -
>     -dnl Unexpected option argument
>     -AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1],
>     [], [stderr])
>     -AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .*
>     requires an argument' stderr], [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1],
>     [], [stderr])
>     -AT_CHECK([grep 'option on .* does not accept an argument'
>     stderr], [0], [ignore])
>     -
>     -dnl Not enough arguments
>     -AT_CHECK([ovn-nbctl list], [1], [], [stderr])
>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>     [0], [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>     [0], [ignore])
>     -
>     -dnl Too many arguments
>     -AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>     [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>     [ignore])
>     -
>     -AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>     [ignore])
>     -
>     -AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>     [ignore])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
>     -dnl Check that port group can be looked up by name
>     -AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
>     -AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
>     -pg0
>     -])])
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
>     -dnl This test addresses a specific issue seen when running
>     ovn-nbctl in
>     -dnl daemon mode. All we have to do is ensure that each time we
>     list database
>     -dnl information, there is not an extra newline at the beginning
>     of the output.
>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>     [dnl
>     -name                : sw1
>     -])
>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>     [dnl
>     -name                : sw1
>     -])])
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
>     -dnl This test addresses a specific issue seen when running
>     ovn-nbctl in
>     -dnl daemon mode. We need to ensure that table formatting options
>     are honored
>     -dnl when listing database information.
>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch
>     sw1], [0], [dnl
>     -sw1
>     -])])
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group
>     commands], [
>     -AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],
>     -[pg1
>     -])
>     -
>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>     -
>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
>     -SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>     sw1-p1)
>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
>     -SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>     sw1-p2)
>     -
>     -AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1],
>     [0],[dnl
>     -pg1
>     -])
>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>     port_group pg1], [0], [dnl
>     -$SW1P1
>     -])
>     -
>     -AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>     port_group pg1], [0], [dnl
>     -$SW1P2
>     -])
>     -
>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>     -])
>     -
>     -AT_SETUP([ovn-nbctl - daemon retry connection])
>     -OVN_NBCTL_TEST_START daemon
>     -AT_CHECK([kill `cat ovsdb-server.pid`])
>     -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>     [stderr])
>     -AT_CHECK([ovn-nbctl show], [0], [ignore])
>     -OVN_NBCTL_TEST_STOP /Terminated/d
>     -AT_CLEANUP
>     diff --git a/tests/ovn-northd.at <http://ovn-northd.at>
>     b/tests/ovn-northd.at <http://ovn-northd.at>
>     deleted file mode 100644
>     index 62e58fd..0000000
>     --- a/tests/ovn-northd.at <http://ovn-northd.at>
>     +++ /dev/null
>     @@ -1,900 +0,0 @@
>     -AT_BANNER([OVN northd])
>     -AT_SETUP([ovn -- check   from NBDB to SBDB])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>     -
>     -# Connect alice to R1 as distributed router gateway port on hv2
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl --wait=sb \
>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>     -                                     chassis_name=gw1 \
>     -                                     priority=20 -- \
>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>     -                                     chassis_name=gw2 \
>     -                                     priority=10 -- \
>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find
>     Gateway_Chassis name="alice_gw1"`
>     -
>     -# With the new ha_chassis_group table added, there should be no
>     rows in
>     -# gateway_chassis table in SB DB.
>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>     -])
>     -
>     -# There should be one ha_chassis_group with the name "alice"
>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="alice"`
>     -
>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>     -
>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>     ha_chassis_group name=alice`
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>     port_binding \
>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>     -])
>     -
>     -# There should be one ha_chassis_group with the name "alice"
>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="alice"`
>     -
>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>     -
>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>     ha_chassis_group name=alice`
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>     port_binding \
>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>     -])
>     -
>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>     -# Trim the spaces.
>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>     -
>     -ha_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list="$ha_ch_list $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>     -
>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>     -
>     -# Delete chassis - gw2 in SB DB.
>     -# ovn-northd should not recreate ha_chassis rows
>     -# repeatedly when gw2 is deleted.
>     -ovn-sbctl chassis-del gw2
>     -
>     -ha_ch_list_1=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>     -
>     -ha_ch_list_2=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>     -
>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>     -
>     -# Add back the gw2 chassis
>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>     -
>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>     -gw_ch=`ovn-sbctl --bare --columns gateway_chassis find port_binding \
>     -logical_port="cr-alice"`
>     -AT_CHECK([test "$gw_ch" = ""])
>     -
>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>     -# Trim the spaces.
>     -echo "ha ch in grp = $ha_ch"
>     -
>     -ha_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list="$ha_ch_list $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>     -
>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>     -
>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>     -ovn-nbctl --wait=sb set Logical_Router_Port alice
>     gateway_chassis=${nb_gwc1_uuid}
>     -
>     -# There should be only 1 row in ha_chassis SB DB table.
>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>     -l], [0], [1
>     -])
>     -
>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>     -])
>     -
>     -# There should be only 1 row in ha_chassis SB DB table.
>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>     -l], [0], [1
>     -])
>     -
>     -# delete all the gateway_chassis on NBDB for alice port
>     -
>     -ovn-nbctl --wait=sb clear Logical_Router_Port alice gateway_chassis
>     -
>     -# expect that the ha_chassis doesn't exist anymore
>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>     -])
>     -
>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>     -])
>     -
>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>     -])
>     -
>     -# expect that the ha_chassis doesn't exist anymore
>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>     -])
>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to
>     SBDB backwards compatibility])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>     -
>     -ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03
>     172.16.1.1/24 <http://172.16.1.1/24> \
>     -    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
>     -
>     -
>     -# It should be converted to ha_chassis_group entries in SBDB, and
>     -# still redirect-chassis is kept for backwards compatibility
>     -
>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>     -])
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>     -l], [0], [1
>     -])
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group
>     | wc -l], [0], [1
>     -])
>     -
>     -# There should be one ha_chassis_group with the name "bob_gw1"
>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="bob_gw1"`
>     -
>     -AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
>     -
>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>     ha_chassis_group name=bob_gw1`
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>     port_binding \
>     -logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
>     -])
>     -
>     -ovn-nbctl --wait=sb remove Logical_Router_Port bob options
>     redirect-chassis
>     -
>     -# expect that the ha_chassis/ha_chassis_group doesn't exist anymore
>     -
>     -AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>     -])
>     -
>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check up state of VIF LSP])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add S1
>     -ovn-nbctl --wait=sb lsp-add S1 S1-vm1
>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
>     -
>     -ovn-sbctl chassis-add hv1 geneve 127.0.0.1
>     -ovn-sbctl lsp-bind S1-vm1 hv1
>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check up state of router LSP linked to a
>     distributed LR])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl ls-add S1
>     -ovn-nbctl lsp-add S1 S1-R1
>     -ovn-nbctl lsp-set-type S1-R1 router
>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check up state of router LSP linked to a gateway
>     LR])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>     -
>     -ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl ls-add S1
>     -ovn-nbctl lsp-add S1 S1-R1
>     -ovn-nbctl lsp-set-type S1-R1 router
>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>     -
>     -ovn-sbctl lsp-bind S1-R1 gw1
>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check up state of router LSP linked to an LRP
>     with set Gateway Chassis])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
>     -
>     -ovn-nbctl ls-add S1
>     -ovn-nbctl lsp-add S1 S1-R1
>     -ovn-nbctl lsp-set-type S1-R1 router
>     -ovn-nbctl lsp-set-addresses S1-R1 router
>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
>     -ovn_start
>     -
>     -ovn-nbctl lr-add ro
>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>     -ovn-nbctl ls-add sw
>     -ovn-nbctl lsp-add sw sw-ro
>     -ovn-nbctl lsp-set-type sw-ro router
>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:send_periodic=true
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:address_mode=slaac
>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>     ipv6_ra_configs:mtu=1280
>     -
>     -uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding
>     logical_port=ro-sw)
>     -
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_send_periodic],
>     -[0], ["true"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_address_mode],
>     -[0], [slaac
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[0], ["600"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[0], ["200"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
>     -[0], ["1280"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_src_eth],
>     -[0], ["00:00:00:00:00:01"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_src_addr],
>     -[0], ["fe80::200:ff:fe00:1"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_prefixes],
>     -[0], ["aef0::/64"
>     -])
>     -
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:max_interval=300
>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>     ipv6_ra_configs:min_interval=600
>     -
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[0], ["300"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[0], ["225"
>     -])
>     -
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:max_interval=300
>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>     ipv6_ra_configs:min_interval=250
>     -
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[0], ["300"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[0], ["225"
>     -])
>     -
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:max_interval=0
>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>     ipv6_ra_configs:min_interval=0
>     -
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[0], ["4"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[0], ["3"
>     -])
>     -
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:max_interval=3600
>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>     ipv6_ra_configs:min_interval=2400
>     -
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[0], ["1800"
>     -])
>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[0], ["1350"
>     -])
>     -
>     -ovn-nbctl --wait=sb set Logical_Router_port ro-sw
>     ipv6_ra_configs:send_periodic=false
>     -
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_send_periodic],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in
>     Port_Binding record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_max_interval],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in
>     Port_Binding record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_min_interval],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in
>     Port_Binding record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_mtu],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record
>     "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_address_mode],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in
>     Port_Binding record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_src_eth],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding
>     record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_src_addr],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding
>     record "${uuid}" column options
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>     options:ipv6_ra_prefixes],
>     -[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding
>     record "${uuid}" column options
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- test unixctl])
>     -ovn_init_db ovn-sb; ovn-sbctl init
>     -ovn_init_db ovn-nb; ovn-nbctl init
>     -
>     -# test unixctl option
>     -mkdir "$ovs_base"/northd
>     -as northd start_daemon ovn-northd
>     --unixctl="$ovs_base"/northd/ovn-northd.ctl
>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -ovn-nbctl ls-add sw
>     -ovn-nbctl --wait=sb lsp-add sw p1
>     -# northd created with unixctl option successfully created
>     port_binding entry
>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>     logical_port="p1" | wc -l], [0], [1
>     -])
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
>     -
>     -# ovs-appctl exit with unixctl option
>     -OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl],
>     ["$ovs_base"/northd/ovn-northd.pid])
>     -
>     -# Check no port_binding entry for new port as ovn-northd is not
>     running
>     -ovn-nbctl lsp-add sw p2
>     -ovn-nbctl --timeout=10 --wait=sb sync
>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>     logical_port="p2" | wc -l], [0], [0
>     -])
>     -
>     -# test default unixctl path
>     -as northd start_daemon ovn-northd
>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -ovn-nbctl --wait=sb lsp-add sw p3
>     -# northd created with default unixctl path successfully created
>     port_binding entry
>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>     logical_port="p3" | wc -l], [0], [1
>     -])
>     -
>     -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])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to
>     SBDB])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>     -
>     -# ovn-northd should not create HA chassis group and HA chassis rows
>     -# unless the HA chassis group in OVN NB DB is associated to
>     -# a logical router port or logical port of type external.
>     -AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group
>     name="hagrp1" \
>     -| wc -l], [0], [0
>     -])
>     -
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>     -
>     -# There should be no HA_Chassis rows in SB DB.
>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>     $3}' \
>     -| grep -v '-' | wc -l ], [0], [0
>     -])
>     -
>     -# Add chassis ch1.
>     -ovn-sbctl chassis-add ch1 geneve 127.0.0.2
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc
>     -l`])
>     -
>     -# There should be no HA_Chassis rows
>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>     $3}' \
>     -| grep -v '-' | wc -l ], [0], [0
>     -])
>     -
>     -# Create a logical router port and attach ha chassis group.
>     -ovn-nbctl lr-add lr0
>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13
>     172.168.0.100/24 <http://172.168.0.100/24>
>     -
>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>     ha_chassis_group name=hagrp1`
>     -ovn-nbctl set logical_router_port lr0-public
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Make sure that ovn-northd doesn't recreate the ha_chassis
>     -# records if the chassis record is missing in SB DB.
>     -
>     -ha_ch_list_1=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>     -
>     -ha_ch_list_2=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>     -
>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>     -
>     -# 2 HA chassis should be created with 'chassis' column empty because
>     -# we have not added hv1 and hv2 chassis to the SB DB.
>     -AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis |
>     awk '{print $3}' \
>     -| grep -v '-' | wc -l`])
>     -
>     -# We should have 1 ha chassis with 'chassis' column set for hv1
>     -AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | awk '{print $3}' \
>     -| grep '-' | wc -l`])
>     -
>     -# Create another logical router port and associate to the same
>     ha_chasis_group
>     -ovn-nbctl lr-add lr1
>     -ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14
>     182.168.0.100/24 <http://182.168.0.100/24>
>     -
>     -ovn-nbctl set logical_router_port lr1-public
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -# We should still have 1 HA chassis group and 3 HA chassis in SB DB.
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Change the priority of ch1 - ha chassis in NB DB. It should get
>     -# reflected in SB DB.
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority find \
>     -ha_chassis | grep 100 | wc -l`])
>     -
>     -# Delete ch1 HA chassis in NB DB.
>     -ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
>     -
>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>     chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Add back the ha chassis
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
>     -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep
>     chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Delete lr0-public. We should still have 1 HA chassis group and
>     -# 3 HA chassis in SB DB.
>     -ovn-nbctl --wait=sb lrp-del lr0-public
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Delete lr1-public. There should be no HA chassis group in SB DB.
>     -ovn-nbctl --wait=sb lrp-del lr1-public
>     -
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>     -l`])
>     -
>     -# Add lr0-public again
>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> set
>     logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Create a Gateway chassis. ovn-northd should ignore this.
>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
>     -
>     -# There should be only 1 HA chassis group in SB DB with the
>     -# name hagrp1.
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Now delete HA chassis group. ovn-northd should create HA
>     chassis group
>     -# with the Gateway chassis name
>     -ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
>     -ovn-nbctl ha-chassis-group-del hagrp1
>     -
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="lr0-public" | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>     -find ha_chassis | wc -l`])
>     -
>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="lr0-public" | wc -l`])
>     -
>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>     chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Test if 'ref_chassis' column is properly set or not in
>     -# SB DB ha_chassis_group.
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl lsp-add sw0 sw0-p1
>     -
>     -ovn-sbctl chassis-add ch2 geneve 127.0.0.3
>     -ovn-sbctl chassis-add ch3 geneve 127.0.0.4
>     -ovn-sbctl chassis-add comp1 geneve 127.0.0.5
>     -ovn-sbctl chassis-add comp2 geneve 127.0.0.6
>     -
>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
>     <http://10.0.0.1/24>
>     -ovn-nbctl lsp-add sw0 sw0-lr0
>     -ovn-nbctl lsp-set-type sw0-lr0 router
>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>     -
>     -ovn-sbctl lsp-bind sw0-p1 comp1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
>     -
>     -comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="comp1"`
>     -comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="comp2"`
>     -ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="comp1"`
>     -
>     -echo "comp1_ch_uuid = $comp1_ch_uuid"
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp1_ch_uuid" = "$ref_ch_list"])
>     -
>     -# unbind sw0-p1
>     -ovn-sbctl lsp-unbind sw0-p1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "" = "$ref_ch_list"])
>     -
>     -# Bind sw0-p1 in comp2
>     -ovn-sbctl lsp-bind sw0-p1 comp2
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>     -
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl lsp-add sw1 sw1-p1
>     -ovn-nbctl lr-add lr1
>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add sw1 sw1-lr1
>     -ovn-nbctl lsp-set-type sw1-lr1 router
>     -ovn-nbctl lsp-set-addresses sw1-lr1 router
>     -ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
>     -
>     -# Bind sw1-p1 in comp1.
>     -ovn-sbctl lsp-bind sw1-p1 comp1
>     -# Wait until sw1-p1 is up
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
>     -
>     -# sw1-p1 is not connected to lr0. So comp1 should not be in
>     'ref_chassis'
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Now attach sw0 to lr1
>     -ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
>     <http://10.0.0.10/24>
>     -ovn-nbctl lsp-add sw0 sw0-lr1
>     -ovn-nbctl lsp-set-type sw0-lr1 router
>     -ovn-nbctl lsp-set-addresses sw0-lr1 router
>     -ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
>     -
>     -# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is
>     indirectly
>     -# connected to lr0
>     -exp_ref_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>     -do
>     -    if test $i = $comp1_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    elif test $i = $comp2_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    fi
>     -done
>     -
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# Unind sw1-p1. comp2 should not be in the ref_chassis.
>     -ovn-sbctl lsp-unbind sw1-p1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Create sw2 and attach it to lr2
>     -ovn-nbctl ls-add sw2
>     -ovn-nbctl lsp-add sw2 sw2-p1
>     -ovn-nbctl lr-add lr2
>     -ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
>     <http://30.0.0.1/24>
>     -ovn-nbctl lsp-add sw2 sw2-lr2
>     -ovn-nbctl lsp-set-type sw2-lr2 router
>     -ovn-nbctl lsp-set-addresses sw2-lr2 router
>     -ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
>     -
>     -# Bind sw2-p1 to comp1
>     -ovn-sbctl lsp-bind sw2-p1 comp1
>     -# Wait until sw2-p1 is up
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
>     -
>     -# sw2-p1 is not connected to lr0. So comp1 should not be in
>     'ref_chassis'
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected
>     to lr0.
>     -ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
>     <http://20.0.0.10/24>
>     -ovn-nbctl lsp-add sw1 sw1-lr2
>     -ovn-nbctl lsp-set-type sw1-lr2 router
>     -ovn-nbctl lsp-set-addresses sw1-lr2 router
>     -ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
>     -
>     -# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2)
>     should be in
>     -# 'ref_chassis'
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# Create sw0-p2 and bind it to comp1
>     -ovn-nbctl lsp-add sw0 sw0-p2
>     -ovn-sbctl lsp-bind sw0-p2 comp1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# unbind sw0-p2
>     -ovn-sbctl lsp-unbind sw0-p2
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# Delete lr1-sw0. comp1 should be deleted from ref_chassis as
>     there is no link
>     -# from sw1 and sw2 to lr0.
>     -ovn-nbctl lrp-del lr1-sw0
>     -
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Set redirect-chassis option to lr0-public. It should be ignored.
>     -ovn-nbctl set logical_router_port lr0-public
>     options:redirect-chassis=ch1
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="lr0-public" | wc -l`])
>     -
>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>     chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Delete the gateway chassis. HA chassis group should be created
>     in SB DB
>     -# for the redirect-chassis option.
>     -ovn-nbctl clear logical_router_port lr0-public gateway_chassis
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group | wc -l`])
>     -
>     -ovn-sbctl list ha_chassis_group
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="lr0-public_ch1" | wc -l`])
>     -
>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep chassis |
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Clear the redirect-chassis option.
>     -ovn-nbctl clear logical_router_port lr0-public options
>     -
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>     -
>     -# Delete old sw0.
>     -ovn-nbctl ls-del sw0
>     -
>     -# Create external logical ports and associate ha_chassis_group
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl lsp-add sw0 sw0-pext1
>     -ovn-nbctl lsp-add sw0 sw0-pext2
>     -ovn-nbctl lsp-add sw0 sw0-p1
>     -
>     -ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 10.0.0.3"
>     -ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 10.0.0.4"
>     -ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
>     -
>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>     -
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>     -
>     -# ovn-northd should not create HA chassis group and HA chassis rows
>     -# unless the HA chassis group in OVN NB DB is associated to
>     -# a logical router port or logical port of type external.
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>     -
>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group \
>     -name=hagrp1`
>     -
>     -# The type of the lsp - sw0-pext1 is still not set to external.
>     -# So ha_chassis_group should be ignored.
>     -ovn-nbctl set logical_switch_port sw0-pext1
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>     -l`])
>     -
>     -# Set the type of sw0-pext1 to external
>     -ovn-nbctl lsp-set-type sw0-pext1 external
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>     ha_chassis_group \
>     -name=hagrp1`
>     -
>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>     -
>     -# Set the type of sw0-pext2 to external and associate
>     ha_chassis_group
>     -ovn-nbctl lsp-set-type sw0-pext2 external
>     -ovn-nbctl set logical_switch_port sw0-pext2
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
>     -grep -v chassis-name | wc -l`])
>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>     -
>     -OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare
>     --columns \
>     -ha_chassis_group find port_binding logical_port=sw0-pext2`])
>     -
>     -# sw0-p1 is a normal port. So ha_chassis_group should not be set
>     -# in port_binding.
>     -ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
>     -ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding \
>     -logical_port=sw0-p1) = x], [0], [])
>     -
>     -# Clear ha_chassis_group for sw0-pext1
>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1
>     ha_chassis_group
>     -
>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding \
>     -logical_port=sw0-pext1) = x], [0], [])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="hagrp1" | wc -l`])
>     -
>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -# Clear ha_chassis_group for sw0-pext2
>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2
>     ha_chassis_group
>     -
>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding \
>     -logical_port=sw0-pext2) = x], [0], [])
>     -
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>     -
>     -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])
>     -
>     -AT_CLEANUP
>     diff --git a/tests/ovn-performance.at <http://ovn-performance.at>
>     b/tests/ovn-performance.at <http://ovn-performance.at>
>     deleted file mode 100644
>     index a8a15f8..0000000
>     --- a/tests/ovn-performance.at <http://ovn-performance.at>
>     +++ /dev/null
>     @@ -1,424 +0,0 @@
>     -#
>     -# Tests targeting performance of OVN components.
>     -#
>     -
>     -m4_divert_push([PREPARE_TESTS])
>     -
>     -# vec_cmp VALUE_VEC OP-VALUE_VEC
>     -#
>     -# Compares each value from VALUE_VEC to the operator-value pair
>     from the
>     -# OP-VALUE_VEC.
>     -#
>     -# VALUE_VEC must be a list of values separated by a character
>     from $IFS.
>     -# OP-VALUE_VEC must be a list of operator-value expressions
>     separated by a
>     -# character from $IFS.  Operator-value expressions cannot contain
>     any characters
>     -# from $IFS like spaces. '=' is treated as an equality operator
>     ('==') for
>     -# conciseness.
>     -#
>     -# Returns the result of each comparison as a list of boolean
>     values (0 or 1)
>     -# separated by a new-line character.
>     -vec_cmp() {
>     -    local a b i j
>     -
>     -    i=0
>     -    for a in $1; do
>     -        j=0
>     -        for b in $2; do
>     -            if test $i -eq $j; then
>     -                # Replace assignment '=' with equality comparison
>     '=='
>     -                case "$b" in
>     -                =[[0-9]]*) b="=$b" ;;
>     -                esac
>     -
>     -                echo $(($a $b))
>     -                break
>     -            fi
>     -            j=$((j + 1))
>     -        done
>     -        i=$((i + 1))
>     -    done
>     -}
>     -
>     -# vec_sub VEC_A VEC_B
>     -#
>     -# Subtracts two vectors:
>     -#
>     -#     VEC_A = [a1, a2, ...]
>     -#     VEC_B = [b1, b2, ...]
>     -#     OUT = [(a1 - b1), (a2 - b2), ...]
>     -#
>     -# VEC_A and VEC_B must be lists of values separated by a
>     character from $IFS.
>     -vec_sub() {
>     -    local a b i j
>     -
>     -    i=0
>     -    for a in $1; do
>     -        j=0
>     -        for b in $2; do
>     -            if test $i -eq $j; then
>     -                echo $((a - b))
>     -                break
>     -            fi
>     -            j=$((j + 1))
>     -        done
>     -        i=$((i + 1))
>     -    done
>     -}
>     -
>     -# vec_fold VEC OP
>     -#
>     -# Reduces a vector to a single value by applying the binary
>     operator OP (i.e.,
>     -# one that requires two arguments) cumulatively to all vector
>     elements from left
>     -# to right:
>     -#
>     -#     VEC = [e1, e2, e3 ...]
>     -#     OUT = (...((e1 OP e2) OP e3) OP ...)
>     -#
>     -# VEC must be a list of values separated by a character from $IFS.
>     -vec_fold() {
>     -    local first op prod
>     -
>     -    first=1
>     -    op=$2
>     -    for a in $1; do
>     -        if test $first -eq 1; then
>     -            prod=$a
>     -            first=0
>     -        else
>     -            prod=$((prod $op a))
>     -        fi
>     -    done
>     -    echo $prod
>     -}
>     -
>     -# read_counters SANDBOXES TARGET COUNTER
>     -#
>     -# Prints out the coverage COUNTER for the TARGET in each of the
>     SANDBOXES.
>     -#
>     -# SANDBOXES must be a list of strings separated by a character
>     from $IFS.
>     -read_counters() {
>     -    local sims="$1" target="$2" counter="$3"
>     -
>     -    for sim in $sims; do
>     -        as $sim ovs-appctl -t "$target" coverage/read-counter
>     "$counter" || return 1
>     -    done
>     -}
>     -
>     -# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
>     -#
>     -# Runs the COMMAND and reports the COUNTER change registered
>     during the command
>     -# run for the given TARGET in each of the SANDBOXES.
>     -counter_delta_() {
>     -    local sims="$1" target="$2" counter="$3" cmd="$4"
>     -    local before after
>     -
>     -    before=$(read_counters "$sims" "$target" "$counter") || return 1
>     -    eval "$cmd" >/dev/null || return 1
>     -    after=$(read_counters "$sims" "$target" "$counter") || return 1
>     -
>     -    vec_sub "$after" "$before"
>     -}
>     -
>     -# counter_delta SANDBOXES TARGET COUNTER COMMAND
>     -#
>     -# Same as counter_delta_ but also prints the COUNTER values
>     together with the
>     -# COMMAND to standard error.
>     -counter_delta() {
>     -    local cmd="$4"
>     -    local v
>     -
>     -    v=$(counter_delta_ "$@") || return 1
>     -
>     -    # Dump the counters and the command for troubleshooting
>     -    echo "$v" | tr '\n' '\t' >&2
>     -    echo "$cmd" >&2
>     -
>     -    echo "$v"
>     -}
>     -
>     -# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
>     -#
>     -# Check if COUNTER change in the TARGET app in each of the
>     SANDBOXES after
>     -# running the COMMAND meets the conditions listed as
>     operator-value pairs in
>     -# CONDS.
>     -vec_cmp_counter_delta() {
>     -    local v
>     -
>     -    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
>     -    v=$(vec_cmp "$v" "$4") || return 1
>     -    v=$(vec_fold "$v" "&&") || return 1
>     -
>     -    echo "$v"
>     -}
>     -
>     -# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
>     -#
>     -# Check if COUNTER change in the TARGET app in each of the
>     SANDBOXES after
>     -# running the COMMAND meets the COND condition given as a
>     operator-value pair.
>     -cmp_counter_delta() {
>     -    local conds=""
>     -
>     -    # Use the same condition for each sandbox
>     -    for _ in $1; do
>     -        conds="$conds $4"
>     -    done
>     -
>     -    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
>     -}
>     -
>     -m4_divert_pop([PREPARE_TESTS])
>     -
>     -# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
>     -#
>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>     in all of
>     -# the SANDBOXES did not change.
>     -m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
>     -    rc=$?
>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>     -])
>     -
>     -# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER COMMAND
>     -#
>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET in
>     -# all of the SANDBOXES has changed.
>     -m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
>     -    rc=$?
>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>     -])
>     -
>     -# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
>     -#
>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>     in all of the
>     -# SANDBOXES satisfies the conditions listed in CONDS.
>     -m4_define([CHECK_COUNTER_DELTA_COND],[
>     -    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
>     -    rc=$?
>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>     -])
>     -
>     -# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
>     -#
>     -# Checks if the COUNTER value has changed for any of the
>     ovn-controller
>     -# processes in the SANDBOXES when the COMMAND was run.
>     -m4_define([OVN_CONTROLLER_EXPECT_HIT],[
>     -    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2],
>     [$3])
>     -])
>     -
>     -# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
>     -#
>     -# Checks if the COUNTER value has not changed for any of the
>     ovn-controller
>     -# processes in the SANDBOXES when the COMMAND was run.
>     -m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
>     -    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], [$3])
>     -])
>     -
>     -# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
>     -#
>     -# Checks if the change of the COUNTER value, when the COMMAND was
>     run, of the
>     -# ovn-controller process in each of the SANDBOXES meets the
>     conditions in
>     -# CONDS. CONDS must be a list of operator-value pairs, for
>     example "[>0 =0]",
>     -# following the same order as SANDBOXES.
>     -m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
>     -    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3],
>     [$4])
>     -])
>     -
>     -AT_SETUP([ovn -- ovn-controller incremental processing])
>     -# Check which operations the trigger full logical flow processing.
>     -#
>     -# Create and destroy logical routers, switches, ports, address
>     sets and ACLs
>     -# while counting calls to lflow_run() in ovn-controller.
>     -
>     -ovn_start
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -done
>     -
>     -# Add router lr1
>     -OVN_CONTROLLER_EXPECT_HIT(
>     -    [hv1 hv2], [lflow_run],
>     -    [ovn-nbctl --wait=hv lr-add lr1]
>     -)
>     -
>     -for i in 1 2; do
>     -    ls=ls$i
>     -    lsp=$ls-lr1
>     -    lrp=lr1-$ls
>     -
>     -    # Add switch $ls
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv ls-add $ls]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config
>     subnet=10.0.$i.0/24]
>     -    )
>     -
>     -    # Add router port to $ls
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01
>     10.0.$i.1/24]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-set-options $lsp router-port=$lrp]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
>     -    )
>     -done
>     -
>     -get_lsp_uuid () {
>     -    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
>     -}
>     -
>     -pg_ports=
>     -
>     -for i in 1 2; do
>     -    j=$((i%2 + 1))
>     -    as=as$i
>     -    ls=ls$i
>     -    lp=lp$i
>     -    vif=vif$i
>     -
>     -    # Add port $lp
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-add $ls $lp]
>     -    )
>     -
>     -    pg_ports="$pg_port `get_lsp_uuid $lp`"
>     -
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl wait-until Logical_Switch_Port $lp
>     dynamic_addresses!=[[]] &&
>     -         ovn-nbctl --wait=hv sync]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl get Logical_Switch_Port $lp dynamic_addresses &&
>     -         ovn-nbctl --wait=hv sync]
>     -    )
>     -
>     -    # Add address set $as
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv create Address_Set name="$as"]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv add Address_Set "$as" addresses
>     "10.0.$i.10"]
>     -    )
>     -
>     -    # Add ACLs for port $lp
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport
>     == \"$lp\" && ip4.src == \$$as' allow]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport
>     == \"$lp\"' drop]
>     -    )
>     -
>     -    # Bind port $lp and wait for it to come up
>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>     -        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface
>     $vif external-ids:iface-id=$lp &&
>     -         ovn-nbctl wait-until Logical_Switch_Port $lp 'up=true' &&
>     -         ovn-nbctl --wait=hv sync]
>     -    )
>     -done
>     -
>     -for i in 1 2; do
>     -    j=$((i%2 + 1))
>     -    as=as$i
>     -    ls=ls$i
>     -    lp=lp$i
>     -
>     -    # Delete ACLs for port $lp
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport
>     == \"$lp\" && ip4.src == \$$as']
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport
>     == \"$lp\"']
>     -    )
>     -
>     -    # Delete address set $as
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses
>     "10.0.$i.10"]
>     -    )
>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
>     -    )
>     -done
>     -
>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>     -    [hv1 hv2], [lflow_run],
>     -    [ovn-nbctl --wait=hv create Port_Group name=pg1
>     ports=\"$pg_ports\"]
>     -)
>     -
>     -# Add ACLs for port group pg1
>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>     -    [hv1 hv2], [lflow_run],
>     -    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport ==
>     @pg1 && ip4.src == $pg1_ip4' allow]
>     -)
>     -
>     -for i in 1 2; do
>     -    j=$((i%2 + 1))
>     -    lp=lp$i
>     -
>     -    # Delete port $lp
>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>     -        [ovn-nbctl --wait=hv lsp-del $lp]
>     -    )
>     -done
>     -
>     -# Delete port group pg1
>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>     -    [hv1 hv2], [lflow_run],
>     -    [ovn-nbctl --wait=hv destroy Port_Group pg1]
>     -)
>     -
>     -for i in 1 2; do
>     -    ls=ls$i
>     -
>     -    # Delete switch $ls
>     -    OVN_CONTROLLER_EXPECT_HIT(
>     -        [hv1 hv2], [lflow_run],
>     -        [ovn-nbctl --wait=hv ls-del $ls]
>     -    )
>     -done
>     -
>     -# Delete router lr1
>     -OVN_CONTROLLER_EXPECT_HIT(
>     -    [hv1 hv2], [lflow_run],
>     -    [ovn-nbctl --wait=hv lr-del lr1]
>     -)
>     -
>     -OVN_CLEANUP([hv1], [hv2])
>     -
>     -AT_CLEANUP
>     diff --git a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>     b/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>     deleted file mode 100644
>     index 650e357..0000000
>     --- a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>     +++ /dev/null
>     @@ -1,150 +0,0 @@
>     -AT_BANNER([ovn-sbctl])
>     -
>     -# OVN_SBCTL_TEST_START
>     -m4_define([OVN_SBCTL_TEST_START],
>     -  [dnl Create databases (ovn-nb, ovn-sb).
>     -   AT_KEYWORDS([ovn])
>     -   for daemon in ovn-nb ovn-sb; do
>     -      AT_CHECK([ovsdb-tool create $daemon.db
>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>     -   done
>     -
>     -   dnl Start ovsdb-servers.
>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>     --pidfile=ovnnb_db.pid --unixctl=$OVS_RUNDIR/ovnnb_db.ctl
>     --log-file=ovsdb_nb.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock
>     ovn-nb.db ], [0], [], [stderr])
>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>     --pidfile=ovnsb_db.pid --unixctl=$OVS_RUNDIR/ovnsb_db.ctl
>     --log-file=ovsdb_sb.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock
>     ovn-sb.db], [0], [], [stderr])
>     -   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d
>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>     -
>     -   dnl Start ovn-northd.
>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file
>     --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock
>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>     -   on_exit "kill `cat ovn-northd.pid`"
>     -   AT_CHECK([[sed < stderr '
>     -/vlog|INFO|opened log file/d']])
>     -   AT_CAPTURE_FILE([ovn-northd.log])
>     -])
>     -
>     -# OVN_SBCTL_TEST_STOP
>     -m4_define([OVN_SBCTL_TEST_STOP],
>     -  [AT_CHECK([check_logs "$1"])
>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl],
>     [$OVS_RUNDIR/ovnnb_db.pid])
>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl],
>     [$OVS_RUNDIR/ovnsb_db.pid])])
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -AT_SETUP([ovn-sbctl - chassis commands])
>     -OVN_SBCTL_TEST_START
>     -ovn_init_db ovn-sb
>     -
>     -AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>     ip,type list encap | sort],
>     -         [0], [dnl
>     -1.2.3.4,geneve
>     -])
>     -
>     -AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>     ip,type list encap | sort],
>     -         [0], [dnl
>     -1.2.3.4,geneve
>     -1.2.3.5,geneve
>     -1.2.3.5,stt
>     -1.2.3.5,vxlan
>     -])
>     -
>     -AT_CHECK([ovn-sbctl chassis-del ch0])
>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>     ip,type list encap | sort],
>     -         [0], [dnl
>     -1.2.3.5,geneve
>     -1.2.3.5,stt
>     -1.2.3.5,vxlan
>     -])
>     -
>     -OVN_SBCTL_TEST_STOP
>     -as ovn-sb
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -AT_CLEANUP
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -AT_SETUP([ovn-sbctl])
>     -OVN_SBCTL_TEST_START
>     -
>     -AT_CHECK([ovn-nbctl ls-add br-test])
>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>     -AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>     -
>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>     -Chassis ch0
>     -    Encap stt
>     -        ip: "1.2.3.5"
>     -        options: {csum="true"}
>     -    Port_Binding vif0
>     -])
>     -
>     -# adds another 'vif1'
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>     -
>     -AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
>     -Chassis ch0
>     -    Encap stt
>     -        ip: "1.2.3.5"
>     -        options: {csum="true"}
>     -    Port_Binding vif
>     -    Port_Binding vif
>     -])
>     -
>     -# deletes 'vif1'
>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>     -
>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>     -Chassis ch0
>     -    Encap stt
>     -        ip: "1.2.3.5"
>     -        options: {csum="true"}
>     -    Port_Binding vif0
>     -])
>     -
>     -uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':'
>     -f2 | tr -d ' ')
>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis
>     list Port_Binding], [0], [dnl
>     -logical_port        : vif0
>     -mac                 : [["f0:ab:cd:ef:01:02"]]
>     -chassis             : ${uuid}
>     -])
>     -
>     -# test the passing down of logical port type and options.
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
>     -AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
>     -AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0
>     vtep_logical_switch=l0])
>     -
>     -AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0
>     options!={}])
>     -AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list
>     Port_Binding vtep0], [0], [dnl
>     -logical_port        : vtep0
>     -mac                 : [[]]
>     -type                : vtep
>     -options             : {vtep_logical_switch=l0,
>     vtep_physical_switch=p0}
>     -])
>     -
>     -OVN_SBCTL_TEST_STOP
>     -AT_CLEANUP
>     -
>     -dnl
>     ---------------------------------------------------------------------
>     -
>     -AT_SETUP([ovn-sbctl - connection])
>     -OVN_SBCTL_TEST_START
>     -
>     -AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection
>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
>     -AT_CHECK([ovn-sbctl list connection | grep inactivity_probe],
>     [0], [dnl
>     -inactivity_probe    : 30000
>     -inactivity_probe    : 30000
>     -])
>     -
>     -OVN_SBCTL_TEST_STOP
>     -AT_CLEANUP
>     diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at
>     <http://ovn.at>
>     deleted file mode 100644
>     index cb380d2..0000000
>     --- a/tests/ovn.at <http://ovn.at>
>     +++ /dev/null
>     @@ -1,14702 +0,0 @@
>     -# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
>     -#
>     -# This compares packets read from PCAP, in pcap format, to those read
>     -# from EXPECTED, which is a text file containing packets as hex
>     -# strings, one per line.  If PCAP contains fewer packets than
>     -# EXPECTED, it waits up to 10 seconds for more packets to appear.
>     -#
>     -# The implementation is an m4 macro that is mostly implemented in
>     -# terms of a shell function.  This reduces the size of the generated
>     -# testsuite file since the shell function is only emitted once even
>     -# when this macro is invoked many times.
>     -m4_divert_text([PREPARE_TESTS],
>     -  [ovn_check_packets__ () {
>     -     echo
>     -     echo "checking packets in $1 against $2:"
>     -     rcv_pcap=$1
>     -     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
>     -     exp_text=$2
>     -     exp_n=`wc -l < "$exp_text"`
>     -     OVS_WAIT_UNTIL(
>     -       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $rcv_pcap > $rcv_text
>     -        rcv_n=`wc -l < "$rcv_text"`
>     -        echo "rcv_n=$rcv_n exp_n=$exp_n"
>     -        test $rcv_n -ge $exp_n])
>     -     sort $exp_text > expout
>     -   }
>     -])
>     -m4_define([OVN_CHECK_PACKETS],
>     -  [ovn_check_packets__ "$1" "$2"
>     -   AT_CHECK([sort $rcv_text], [0], [expout])])
>     -
>     -AT_BANNER([OVN components])
>     -
>     -AT_SETUP([ovn -- lexer])
>     -dnl For lines without =>, input and expected output are identical.
>     -dnl For lines with =>, input precedes => and expected output
>     follows =>.
>     -AT_DATA([test-cases.txt], [dnl
>     -foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
>     -"abc\u0020def" => "abc def"
>     -" => error("Input ends inside quoted string.")dnl "
>     -
>     -$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
>     -$1 => error("`$' must be followed by a valid identifier.") 1
>     -
>     -a/*b*/c => a c
>     -a//b c => a
>     -a/**/b => a b
>     -a/*/b => a error("`/*' without matching `*/'.")
>     -a/*/**/b => a b
>     -a/b => a error("`/' is only valid as part of `//' or `/*'.") b
>     -
>     -0 1 12345 18446744073709551615
>     -18446744073709551616 => error("Decimal constants must be less
>     than 2**64.")
>     -9999999999999999999999 => error("Decimal constants must be less
>     than 2**64.")
>     -01 => error("Decimal constants must not have leading zeros.")
>     -
>     -0/0
>     -0/1
>     -1/0 => error("Value contains unmasked 1-bits.")
>     -1/1
>     -128/384
>     -1/3
>     -1/ => error("Integer constant expected.")
>     -
>     -1/0x123 => error("Value and mask have incompatible formats.")
>     -
>     -0x1234
>     -0x01234 => 0x1234
>     -0x0 => 0
>     -0x000 => 0
>     -0xfedcba9876543210
>     -0XFEDCBA9876543210 => 0xfedcba9876543210
>     -0xfedcba9876543210fedcba9876543210
>     -0x0000fedcba9876543210fedcba9876543210 =>
>     0xfedcba9876543210fedcba9876543210
>     -0x => error("Hex digits expected following 0x.")
>     -0X => error("Hex digits expected following 0X.")
>     -0x0/0x0 => 0/0
>     -0x0/0x1 => 0/0x1
>     -0x1/0x0 => error("Value contains unmasked 1-bits.")
>     -0xffff/0x1ffff
>     -0x. => error("Invalid syntax in hexadecimal constant.")
>     -
>     -192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
>     -256.1.2.3 => error("Invalid numeric constant.")
>     -192.168.0.0/16 <http://192.168.0.0/16>
>     -192.168.0.0/255.255.0.0 <http://192.168.0.0/255.255.0.0> =>
>     192.168.0.0/16 <http://192.168.0.0/16>
>     -192.168.0.0/255.255.255.0 <http://192.168.0.0/255.255.255.0> =>
>     192.168.0.0/24 <http://192.168.0.0/24>
>     -192.168.0.0/255.255.0.255 <http://192.168.0.0/255.255.0.255>
>     -192.168.0.0/255.0.0.0 <http://192.168.0.0/255.0.0.0> =>
>     error("Value contains unmasked 1-bits.")
>     -192.168.0.0/32 <http://192.168.0.0/32>
>     -192.168.0.0/255.255.255.255 <http://192.168.0.0/255.255.255.255>
>     => 192.168.0.0/32 <http://192.168.0.0/32>
>     -1.2.3.4:5 <http://1.2.3.4:5> => 1.2.3.4 : 5
>     -
>     -::
>     -::1
>     -ff00::1234 => ff00::1234
>     -2001:db8:85a3::8a2e:370:7334
>     -2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
>     -2001:0db8:85a3:0000:0000:8a2e:0370:7334 =>
>     2001:db8:85a3::8a2e:370:7334
>     -::ffff:192.0.2.128
>     -::ffff:c000:0280 => ::ffff:192.0.2.128
>     -::1/::1
>     -::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
>     -::1/128
>     -ff00::/8
>     -ff00::/ff00:: => ff00::/8
>     -
>     -01:23:45:67:ab:cd
>     -01:23:45:67:AB:CD => 01:23:45:67:ab:cd
>     -fe:dc:ba:98:76:54
>     -FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
>     -01:00:00:00:00:00/01:00:00:00:00:00
>     -ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>     -fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>     -ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains
>     unmasked 1-bits.")
>     -fe:x => error("Invalid numeric constant.")
>     -00:01:02:03:04:x => error("Invalid numeric constant.")
>     -
>     -# Test that operators are tokenized as expected, even without
>     white space.
>     -(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= >
>     >= ! && || .. , ; = <-> -- :
>     -& => error("`&' is only valid as part of `&&'.")
>     -| => error("`|' is only valid as part of `||'.")
>     -- => error("`-' is only valid as part of `--'.")
>     -
>     -^ => error("Invalid character `^' in input.")
>     -])
>     -AT_CAPTURE_FILE([input.txt])
>     -sed 's/ =>.*//' test-cases.txt > input.txt
>     -sed 's/.* => //' test-cases.txt > expout
>     -AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
>     -AT_CLEANUP
>     -
>     -dnl The OVN expression parser needs to know what fields overlap
>     with one
>     -dnl another.  This test therefore verifies that all the smaller
>     registers
>     -dnl are defined as terms of subfields of the larger ones.
>     -dnl
>     -dnl When we add or remove registers this test needs to be
>     updated, of course.
>     -AT_SETUP([ovn -- registers])
>     -AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
>     -[[reg0 = xxreg0[96..127]
>     -reg1 = xxreg0[64..95]
>     -reg2 = xxreg0[32..63]
>     -reg3 = xxreg0[0..31]
>     -reg4 = xxreg1[96..127]
>     -reg5 = xxreg1[64..95]
>     -reg6 = xxreg1[32..63]
>     -reg7 = xxreg1[0..31]
>     -reg8 = xreg4[32..63]
>     -reg9 = xreg4[0..31]
>     -xreg0 = xxreg0[64..127]
>     -xreg1 = xxreg0[0..63]
>     -xreg2 = xxreg1[64..127]
>     -xreg3 = xxreg1[0..63]
>     -xreg4 = OXM_OF_PKT_REG4
>     -xxreg0 = NXM_NX_XXREG0
>     -xxreg1 = NXM_NX_XXREG1
>     -]])
>     -AT_CLEANUP
>     -
>     -dnl Check that the OVN conntrack field definitions are correct.
>     -AT_SETUP([ovn -- conntrack fields])
>     -AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
>     -[[ct.dnat = ct_state[7]
>     -ct.est = ct_state[1]
>     -ct.inv = ct_state[4]
>     -ct.new = ct_state[0]
>     -ct.rel = ct_state[2]
>     -ct.rpl = ct_state[3]
>     -ct.snat = ct_state[6]
>     -ct.trk = ct_state[5]
>     -ct_label = NXM_NX_CT_LABEL
>     -ct_label.blocked = ct_label[0]
>     -ct_mark = NXM_NX_CT_MARK
>     -ct_state = NXM_NX_CT_STATE
>     -]])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- composition])
>     -AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- expression parser])
>     -dnl For lines without =>, input and expected output are identical.
>     -dnl For lines with =>, input precedes => and expected output
>     follows =>.
>     -AT_DATA([test-cases.txt], [[
>     -eth.type == 0x800
>     -eth.type==0x800 => eth.type == 0x800
>     -eth.type[0..15] == 0x800 => eth.type == 0x800
>     -
>     -vlan.present
>     -vlan.present == 1 => vlan.present
>     -!(vlan.present == 0) => vlan.present
>     -!(vlan.present != 1) => vlan.present
>     -!vlan.present
>     -vlan.present == 0 => !vlan.present
>     -vlan.present != 1 => !vlan.present
>     -!(vlan.present == 1) => !vlan.present
>     -!(vlan.present != 0) => !vlan.present
>     -
>     -eth.dst[0]
>     -eth.dst[0] == 1 => eth.dst[0]
>     -eth.dst[0] != 0 => eth.dst[0]
>     -!(eth.dst[0] == 0) => eth.dst[0]
>     -!(eth.dst[0] != 1) => eth.dst[0]
>     -
>     -!eth.dst[0]
>     -eth.dst[0] == 0 => !eth.dst[0]
>     -eth.dst[0] != 1 => !eth.dst[0]
>     -!(eth.dst[0] == 1) => !eth.dst[0]
>     -!(eth.dst[0] != 0) => !eth.dst[0]
>     -
>     -vlan.tci[12..15] == 0x3
>     -vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
>     -vlan.tci[12..15] != 0x3
>     -vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
>     -
>     -!vlan.pcp => vlan.pcp == 0
>     -!(vlan.pcp) => vlan.pcp == 0
>     -vlan.pcp == 0x4
>     -vlan.pcp != 0x4
>     -vlan.pcp > 0x4
>     -vlan.pcp >= 0x4
>     -vlan.pcp < 0x4
>     -vlan.pcp <= 0x4
>     -!(vlan.pcp != 0x4) => vlan.pcp == 0x4
>     -!(vlan.pcp == 0x4) => vlan.pcp != 0x4
>     -!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
>     -!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
>     -!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
>     -!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
>     -0x4 == vlan.pcp => vlan.pcp == 0x4
>     -0x4 != vlan.pcp => vlan.pcp != 0x4
>     -0x4 < vlan.pcp => vlan.pcp > 0x4
>     -0x4 <= vlan.pcp => vlan.pcp >= 0x4
>     -0x4 > vlan.pcp => vlan.pcp < 0x4
>     -0x4 >= vlan.pcp => vlan.pcp <= 0x4
>     -!(0x4 != vlan.pcp) => vlan.pcp == 0x4
>     -!(0x4 == vlan.pcp) => vlan.pcp != 0x4
>     -!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
>     -!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
>     -!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
>     -!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
>     -
>     -1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>     -1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
>     -1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>     -4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
>     -4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
>     -4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
>     -4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
>     -!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>     -!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
>     -!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>     -!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
>     -!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
>     -!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
>     -!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
>     -
>     -vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 ||
>     vlan.pcp == 0x3 || vlan.pcp == 0x4
>     -vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp ==
>     4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 ||
>     vlan.pcp == 0x4
>     -
>     -vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 &&
>     vlan.pcp != 0x3 && vlan.pcp != 0x4
>     -vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp ==
>     4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 &&
>     vlan.pcp == 0x4
>     -
>     -vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 ||
>     vlan.pcp != 0x4)
>     -vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3)
>     && vlan.pcp == 0x4
>     -vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>     == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3)
>     || vlan.pcp != 0x4)
>     -
>     -ip4.src == {10.0.0.0/8 <http://10.0.0.0/8>, 192.168.0.0/16
>     <http://192.168.0.0/16>, 172.16.20.0/24 <http://172.16.20.0/24>,
>     8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 ||
>     ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
>     -ip6.src == ::1 => ip6.src == 0x1
>     -
>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304
>     -ip4.src == ::1.2.3.4/::ffff:ffff <http://1.2.3.4/::ffff:ffff> =>
>     ip4.src == 0x1020304
>     -ip6.src == ::1 => ip6.src == 0x1
>     -
>     -1
>     -0
>     -!1 => 0
>     -!0 => 1
>     -
>     -inport == "eth0"
>     -!(inport != "eth0") => inport == "eth0"
>     -
>     -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
>     => 0
>     -
>     -ip4.src == "eth0" => Integer field ip4.src is not compatible with
>     string constant.
>     -inport == 1 => String field inport is not compatible with integer
>     constant.
>     -ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational
>     operator.
>     -
>     -ip4.src > {1, 2, 3} => Only == and != operators may be used with
>     value sets.
>     -eth.type > 0x800 => Only == and != operators may be used with
>     nominal field eth.type.
>     -vlan.present > 0 => Only == and != operators may be used with
>     Boolean field vlan.present.
>     -
>     -inport != "eth0" => Nominal field inport may only be tested for
>     equality (taking enclosing `!' operators into account).
>     -!(inport == "eth0") => Nominal field inport may only be tested
>     for equality (taking enclosing `!' operators into account).
>     -eth.type != 0x800 => Nominal field eth.type may only be tested
>     for equality (taking enclosing `!' operators into account).
>     -!(eth.type == 0x800) => Nominal field eth.type may only be tested
>     for equality (taking enclosing `!' operators into account).
>     -inport = "eth0" => Syntax error at `=' expecting relational operator.
>     -
>     -123 == 123 => Syntax error at `123' expecting field name.
>     -
>     -$name => Syntax error at `$name' expecting address set name.
>     -@name => Syntax error at `@name' expecting port group name.
>     -
>     -123 == xyzzy => Syntax error at `xyzzy' expecting field name.
>     -xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
>     -
>     -inport[1] == 1 => Cannot select subfield of string field inport.
>     -
>     -eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
>     -eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
>     -eth.type[18446744073709551615] == 1 => Syntax error at
>     `18446744073709551615' expecting small integer.
>     -
>     -eth.type[5!] => Syntax error at `!' expecting `@:>@'.
>     -
>     -eth.type[5..1] => Invalid bit range 5 to 1.
>     -
>     -eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field
>     eth.type.
>     -
>     -eth.type[10] == 1 => Cannot select subfield of nominal field
>     eth.type.
>     -
>     -eth.type => Explicit `!= 0' is required for inequality test of
>     multibit field against 0.
>     -
>     -!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test
>     of multibit field against 0.
>     -
>     -123 => Syntax error at end of input expecting relational operator.
>     -
>     -123 x => Syntax error at `x' expecting relational operator.
>     -
>     -{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
>     -
>     -eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
>     -
>     -(1 x) => Syntax error at `x' expecting `)'.
>     -
>     -!0x800 != eth.type => Missing parentheses around operand of !.
>     -
>     -eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => &&
>     and || must be parenthesized when used together.
>     -
>     -eth.dst == {} => Syntax error at `}' expecting constant.
>     -
>     -eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and !=
>     operators may be used with masked constants. Consider using
>     subfields instead (e.g. eth.src[0..15] > 0x1111 in place of
>     eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
>     -
>     -ip4.src == ::1 => 128-bit constant is not compatible with 32-bit
>     field ip4.src.
>     -
>     -1 == eth.type == 2 => Range expressions must have the form `x <
>     field < y' or `x > field > y', with each `<' optionally replaced
>     by `<=' or `>' by `>=').
>     -
>     -eth.dst[40] x => Syntax error at `x' expecting end of input.
>     -
>     -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at
>     `$unknownset' expecting address set name.
>     -eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at
>     `badmac' expecting constant.
>     -
>     -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
>     => Parentheses nested too deeply.
>     -
>     -ct_label > $set4 => Only == and != operators may be used to
>     compare a field against an empty value set.
>     -]])
>     -sed 's/ =>.*//' test-cases.txt > input.txt
>     -sed 's/.* => //' test-cases.txt > expout
>     -AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- expression annotation])
>     -dnl Input precedes =>, expected output follows =>.
>     -dnl Empty lines and lines starting with # are ignored.
>     -AT_DATA([test-cases.txt], [[
>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
>     -ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
>     -ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 ||
>     eth.type == 0x86dd)
>     -ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea)
>     && (eth.type == 0x800 || eth.type == 0x86dd)
>     -ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304
>     && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
>     -
>     -# Nested expressions over a single symbol should be annotated
>     with symbol's
>     -# prerequisites only once, at the top level.
>     -tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1
>     || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 &&
>     (eth.type == 0x800 || eth.type == 0x86dd)
>     -
>     -ip => eth.type == 0x800 || eth.type == 0x86dd
>     -ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
>     -ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
>     -ip > 0 => Only == and != operators may be used with nominal field ip.
>     -!ip => Nominal predicate ip may only be tested positively, e.g.
>     `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>     -ip == 0 => Nominal predicate ip may only be tested positively,
>     e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>     -
>     -vlan.present => vlan.tci[12]
>     -!vlan.present => !vlan.tci[12]
>     -
>     -!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
>     -vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 &&
>     vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
>     -!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 &&
>     xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
>     -
>     -ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type ==
>     0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
>     -!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type
>     != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type ==
>     0x86dd))
>     -ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type ==
>     0x86dd)
>     -
>     -bad_prereq != 0 => Error parsing expression `xyzzy' encountered
>     as prerequisite or predicate of initial expression: Syntax error
>     at `xyzzy' expecting field name.
>     -self_recurse != 0 => Error parsing expression `self_recurse != 0'
>     encountered as prerequisite or predicate of initial expression:
>     Recursive expansion of symbol `self_recurse'.
>     -mutual_recurse_1 != 0 => Error parsing expression
>     `mutual_recurse_2 != 0' encountered as prerequisite or predicate
>     of initial expression: Error parsing expression `mutual_recurse_1
>     != 0' encountered as prerequisite or predicate of initial
>     expression: Recursive expansion of symbol `mutual_recurse_1'.
>     -mutual_recurse_2 != 0 => Error parsing expression
>     `mutual_recurse_1 != 0' encountered as prerequisite or predicate
>     of initial expression: Error parsing expression `mutual_recurse_2
>     != 0' encountered as prerequisite or predicate of initial
>     expression: Recursive expansion of symbol `mutual_recurse_2'.
>     -]])
>     -sed 's/ =>.*//' test-cases.txt > input.txt
>     -sed 's/.* => //' test-cases.txt > expout
>     -AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 1-term expression conversion])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
>     -  [Tested converting all 1-terminal expressions with 2 numeric
>     vars (each 3 bits) in terms of operators == != < <= > >= and 2
>     string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2-term expression conversion])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
>     -  [Tested converting 578 expressions of 2 terminals with 2
>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>     and 2 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 3-term expression conversion])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert
>     --bits=2 3], [0],
>     -  [Tested converting 67410 expressions of 3 terminals with 2
>     numeric vars (each 2 bits) in terms of operators == != < <= > >=
>     and 2 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 3-term numeric expression simplification])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>     --nvars=2 --svars=0 3], [0],
>     -  [Tested simplifying 490770 expressions of 3 terminals with 2
>     numeric vars (each 3 bits) in terms of operators == != < <= > >=.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term string expression simplification])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>     --nvars=0 --svars=4 4], [0],
>     -  [Tested simplifying 21978 expressions of 4 terminals with 4
>     string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 3-term mixed expression simplification])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>     --nvars=1 --svars=1 3], [0],
>     -  [Tested simplifying 127890 expressions of 3 terminals with 1
>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>     and 1 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- simplification special cases])
>     -simplify() {
>     -    echo "$1" | ovstest test-ovn simplify-expr
>     -}
>     -AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
>     -])
>     -AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
>     -])
>     -AT_CHECK([simplify 'tcp.dst >= 0'], [0],
>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>     -])
>     -AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>     -])
>     -AT_CHECK([simplify 'tcp.dst > 0'], [0],
>     -    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] ||
>     tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8]
>     || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] ||
>     tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 &&
>     (eth.type == 0x800 || eth.type == 0x86dd)
>     -]])
>     -AT_CHECK([simplify 'tcp.dst < 65535'], [0],
>     -    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3]
>     || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] ||
>     !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] ||
>     !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) &&
>     ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>     -]])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- is_chassis_resident simplification])
>     -simplify() {
>     -    echo "$1" | ovstest test-ovn simplify-expr
>     -}
>     -AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
>     -])
>     -AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
>     -])
>     -AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
>     -])
>     -AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term numeric expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=3 --svars=0 --bits=1 4], [0],
>     -  [Tested normalizing 1874026 expressions of 4 terminals with 3
>     numeric vars (each 1 bits) in terms of operators == != < <= > >=.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term string expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=0 --svars=3 --bits=1 4], [0],
>     -  [Tested normalizing 11242 expressions of 4 terminals with 3
>     string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term mixed expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=1 --bits=1 --svars=2 4], [0],
>     -  [Tested normalizing 175978 expressions of 4 terminals with 1
>     numeric vars (each 1 bits) in terms of operators == != < <= > >=
>     and 2 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 5-term numeric expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
>     -  [Tested normalizing 1317600 expressions of 5 terminals with 3
>     numeric vars (each 1 bits) in terms of operators ==.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 5-term string expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
>     -  [Tested normalizing 368550 expressions of 5 terminals with 3
>     string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 5-term mixed expression normalization])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>     --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
>     -  [Tested normalizing 216000 expressions of 5 terminals with 1
>     numeric vars (each 1 bits) in terms of operators == and 1 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term numeric expressions to flows])
>     -AT_KEYWORDS([expression])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2
>     --svars=0 --bits=2 --relops='==' 4], [0],
>     -  [Tested converting to flows 175978 expressions of 4 terminals
>     with 2 numeric vars (each 2 bits) in terms of operators ==.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term string expressions to flows])
>     -AT_KEYWORDS([expression])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0
>     --svars=4 4], [0],
>     -  [Tested converting to flows 21978 expressions of 4 terminals
>     with 4 string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4-term mixed expressions to flows])
>     -AT_KEYWORDS([expression])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1
>     --bits=2 --svars=1 --relops='==' 4], [0],
>     -  [Tested converting to flows 48312 expressions of 4 terminals
>     with 1 numeric vars (each 2 bits) in terms of operators == and 1
>     string vars.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 3-term numeric expressions to flows])
>     -AT_KEYWORDS([expression])
>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3
>     --svars=0 --bits=3 --relops='==' 3], [0],
>     -  [Tested converting to flows 41328 expressions of 3 terminals
>     with 3 numeric vars (each 3 bits) in terms of operators ==.
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- converting expressions to flows -- string fields])
>     -AT_KEYWORDS([expression])
>     -expr_to_flow () {
>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>     -}
>     -AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
>     -ip,reg14=0x5
>     -ipv6,reg14=0x5
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
>     -ip,reg14=0x6
>     -ipv6,reg14=0x6
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
>     -])
>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2",
>     "LOCAL"}'], [0],
>     -[reg14=0x5
>     -reg14=0x6
>     -reg14=0xfffe
>     -])
>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} &&
>     ip'], [0], [dnl
>     -ip,reg14=0x5
>     -ip,reg14=0x6
>     -ipv6,reg14=0x5
>     -ipv6,reg14=0x6
>     -])
>     -AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'],
>     [0], [dnl
>     -(no flows)
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- converting expressions to flows -- address sets])
>     -AT_KEYWORDS([expression])
>     -expr_to_flow () {
>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>     -}
>     -AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2,
>     10.0.0.3}'], [0], [dnl
>     -ip,nw_src=10.0.0.1
>     -ip,nw_src=10.0.0.2
>     -ip,nw_src=10.0.0.3
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
>     -ip,nw_src=10.0.0.1
>     -ip,nw_src=10.0.0.2
>     -ip,nw_src=10.0.0.3
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
>     -ip,nw_src=1.2.3.4
>     -ip,nw_src=10.0.0.1
>     -ip,nw_src=10.0.0.2
>     -ip,nw_src=10.0.0.3
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20
>     <http://1.2.0.0/20>, 5.5.5.0/24 <http://5.5.5.0/24>, $set1}'],
>     [0], [dnl
>     -ip,nw_src=1.2.0.0/20 <http://1.2.0.0/20>
>     -ip,nw_src=10.0.0.1
>     -ip,nw_src=10.0.0.2
>     -ip,nw_src=10.0.0.3
>     -ip,nw_src=5.5.5.0/24 <http://5.5.5.0/24>
>     -])
>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
>     -ipv6,ipv6_src=::1
>     -ipv6,ipv6_src=::2
>     -ipv6,ipv6_src=::3
>     -])
>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
>     -ipv6,ipv6_src=::1
>     -ipv6,ipv6_src=::2
>     -ipv6,ipv6_src=::3
>     -ipv6,ipv6_src=::4
>     -])
>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01,
>     00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
>     -dl_src=00:00:00:00:00:01
>     -dl_src=00:00:00:00:00:02
>     -dl_src=00:00:00:00:00:03
>     -])
>     -AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
>     -dl_src=00:00:00:00:00:01
>     -dl_src=00:00:00:00:00:02
>     -dl_src=00:00:00:00:00:03
>     -])
>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3,
>     ba:be:be:ef:de:ad, $set3}'], [0], [dnl
>     -dl_src=00:00:00:00:00:01
>     -dl_src=00:00:00:00:00:02
>     -dl_src=00:00:00:00:00:03
>     -dl_src=ba:be:be:ef:de:ad
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
>     -(no flows)
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
>     -ip,nw_src=1.2.3.4
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src ==
>     {$set4}'], [0], [dnl
>     -ip,nw_src=1.2.3.4
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
>     -
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8 <http://1.0.0.0/8>,
>     $set4}'], [0], [dnl
>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>     -])
>     -AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 <http://1.0.0.0/8>
>     && ip4.src != {$set4}'], [0], [dnl
>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- converting expressions to flows -- port groups])
>     -AT_KEYWORDS([expression])
>     -expr_to_flow () {
>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>     -}
>     -AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
>     -reg15=0x11
>     -reg15=0x12
>     -reg15=0x13
>     -])
>     -AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
>     -(no flows)
>     -])
>     -AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], [dnl
>     -reg15=0x11
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- converting expressions to flows -- conjunction])
>     -AT_KEYWORDS([conjunction])
>     -expr_to_flow () {
>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>     -}
>     -
>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>     -conj_id=1,ip
>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>     -ip,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/2)
>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>     -])
>     -
>     -lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>     -ct_state=+est+trk,ct_label=0x1/0x1,ip
>     -ct_state=+est+trk,ct_label=0x1/0x1,ipv6
>     -ct_state=-est+trk,ip
>     -ct_state=-est+trk,ipv6
>     -])
>     -
>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>     -ip4.dst == {20.0.0.1, 20.0.0.2}"
>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>     -conj_id=1,ip
>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>     -])
>     -
>     -lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
>     -tcp.dst >= 1000 && tcp.dst <= 1010"
>     -
>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>     -conj_id=1,tcp
>     -tcp,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/3)
>     -tcp,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/3)
>     -tcp,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/3)
>     -tcp,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/3)
>     -tcp,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/3)
>     -tcp,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/3)
>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
>     -tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
>     -tcp,tp_dst=1000: conjunction(1, 2/3)
>     -tcp,tp_dst=1001: conjunction(1, 2/3)
>     -tcp,tp_dst=1010: conjunction(1, 2/3)
>     -])
>     -
>     -lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
>     -((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 && \
>     -tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
>     -|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
>     -
>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>     -conj_id=1,tcp
>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
>     -tcp,nw_dst=20.0.0.4 <http://20.0.0.4>: conjunction(1, 0/4)
>     -tcp,nw_dst=20.0.0.7 <http://20.0.0.7>: conjunction(1, 0/4)
>     -tcp,nw_dst=20.0.0.8 <http://20.0.0.8>: conjunction(1, 0/4)
>     -tcp,nw_src=10.0.0.4 <http://10.0.0.4>: conjunction(1, 1/4)
>     -tcp,nw_src=10.0.0.5 <http://10.0.0.5>: conjunction(1, 1/4)
>     -tcp,nw_src=10.0.0.6 <http://10.0.0.6>: conjunction(1, 1/4)
>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
>     -tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
>     -tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
>     -tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
>     -tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
>     -tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
>     -tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
>     -tcp,tp_dst=1000: conjunction(1, 2/4)
>     -tcp,tp_dst=1001: conjunction(1, 2/4)
>     -tcp,tp_dst=2000: conjunction(1, 2/4)
>     -tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
>     -tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
>     -tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
>     -tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
>     -tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
>     -tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
>     -tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
>     -tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
>     -tcp,tp_src=1000: conjunction(1, 3/4)
>     -tcp,tp_src=1001: conjunction(1, 3/4)
>     -tcp,tp_src=2000: conjunction(1, 3/4)
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- action parsing])
>     -dnl Unindented text is input (a set of OVN logical actions).
>     -dnl Indented text is expected output.
>     -AT_DATA([test-cases.txt],
>     -[[# drop
>     -drop;
>     -    encodes as drop
>     -drop; next;
>     -    Syntax error at `next' expecting end of input.
>     -next; drop;
>     -    Syntax error at `drop' expecting action.
>     -
>     -# output
>     -output;
>     -    encodes as resubmit(,64)
>     -
>     -# next
>     -next;
>     -    encodes as resubmit(,19)
>     -next(11);
>     -    formats as next;
>     -    encodes as resubmit(,19)
>     -next(0);
>     -    encodes as resubmit(,8)
>     -next(23);
>     -    encodes as resubmit(,31)
>     -
>     -next();
>     -    Syntax error at `)' expecting "pipeline" or "table".
>     -next(10;
>     -    Syntax error at `;' expecting `)'.
>     -next(24);
>     -    "next" action cannot advance beyond table 23.
>     -
>     -next(table=11);
>     -    formats as next;
>     -    encodes as resubmit(,19)
>     -next(pipeline=ingress);
>     -    formats as next;
>     -    encodes as resubmit(,19)
>     -next(table=11, pipeline=ingress);
>     -    formats as next;
>     -    encodes as resubmit(,19)
>     -next(pipeline=ingress, table=11);
>     -    formats as next;
>     -    encodes as resubmit(,19)
>     -
>     -next(pipeline=egress);
>     -    "next" action cannot advance from ingress to egress pipeline
>     (use "output" action instead)
>     -
>     -next(table=10);
>     -    formats as next(10);
>     -    encodes as resubmit(,18)
>     -
>     -# Loading a constant value.
>     -tcp.dst=80;
>     -    formats as tcp.dst = 80;
>     -    encodes as set_field:80->tcp_dst
>     -    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type
>     == 0x86dd)
>     -eth.dst[40] = 1;
>     -    encodes as set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
>     -vlan.pcp = 2;
>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>     -    has prereqs vlan.tci[12]
>     -vlan.tci[13..15] = 2;
>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>     -inport = "";
>     -    encodes as set_field:0->reg14
>     -ip.ttl=4;
>     -    formats as ip.ttl = 4;
>     -    encodes as set_field:4->nw_ttl
>     -    has prereqs eth.type == 0x800 || eth.type == 0x86dd
>     -outport="eth0"; next; outport="LOCAL"; next;
>     -    formats as outport = "eth0"; next; outport = "LOCAL"; next;
>     -    encodes as
>     set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
>     -
>     -inport[1] = 1;
>     -    Cannot select subfield of string field inport.
>     -ip.proto[1] = 1;
>     -    Cannot select subfield of nominal field ip.proto.
>     -eth.dst[40] == 1;
>     -    Syntax error at `==' expecting `=' or `<->'.
>     -ip = 1;
>     -    Predicate symbol ip used where lvalue required.
>     -ip.proto = 6;
>     -    Field ip.proto is not modifiable.
>     -inport = {"a", "b"};
>     -    Syntax error at `{' expecting constant.
>     -inport = {};
>     -    Syntax error at `{' expecting constant.
>     -bad_prereq = 123;
>     -    Error parsing expression `xyzzy' encountered as prerequisite
>     or predicate of initial expression: Syntax error at `xyzzy'
>     expecting field name.
>     -self_recurse = 123;
>     -    Error parsing expression `self_recurse != 0' encountered as
>     prerequisite or predicate of initial expression: Error parsing
>     expression `self_recurse != 0' encountered as prerequisite or
>     predicate of initial expression: Recursive expansion of symbol
>     `self_recurse'.
>     -vlan.present = 0;
>     -    Predicate symbol vlan.present used where lvalue required.
>     -
>     -# Moving one field into another.
>     -reg0=reg1;
>     -    formats as reg0 = reg1;
>     -    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
>     -vlan.pcp = reg0[0..2];
>     -    encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
>     -    has prereqs vlan.tci[12]
>     -reg0[10] = vlan.pcp[1];
>     -    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
>     -    has prereqs vlan.tci[12]
>     -outport = inport;
>     -    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
>     -
>     -reg0[0] = vlan.present;
>     -    Predicate symbol vlan.present used where lvalue required.
>     -reg0 = reg1[0..10];
>     -    Can't assign 11-bit value to 32-bit destination.
>     -inport = reg0;
>     -    Can't assign integer field (reg0) to string field (inport).
>     -inport = big_string;
>     -    String fields inport and big_string are incompatible for
>     assignment.
>     -ip.proto = reg0[0..7];
>     -    Field ip.proto is not modifiable.
>     -
>     -# Exchanging fields.
>     -reg0 <-> reg1;
>     -    encodes as
>     push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127]
>     -vlan.pcp <-> reg0[0..2];
>     -    encodes as
>     push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15]
>     -    has prereqs vlan.tci[12]
>     -reg0[10] <-> vlan.pcp[1];
>     -    encodes as
>     push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106]
>     -    has prereqs vlan.tci[12]
>     -outport <-> inport;
>     -    encodes as
>     push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[]
>     -
>     -reg0[0] <-> vlan.present;
>     -    Predicate symbol vlan.present used where lvalue required.
>     -reg0 <-> reg1[0..10];
>     -    Can't exchange 32-bit field with 11-bit field.
>     -inport <-> reg0;
>     -    Can't exchange string field (inport) with integer field (reg0).
>     -inport <-> big_string;
>     -    String fields inport and big_string are incompatible for
>     exchange.
>     -ip.proto <-> reg0[0..7];
>     -    Field ip.proto is not modifiable.
>     -reg0[0..7] <-> ip.proto;
>     -    Field ip.proto is not modifiable.
>     -
>     -# TTL decrement.
>     -ip.ttl--;
>     -    encodes as dec_ttl
>     -    has prereqs ip
>     -ip.ttl
>     -    Syntax error at end of input expecting `--'.
>     -
>     -# load balancing.
>     -ct_lb;
>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>     -    has prereqs ip
>     -ct_lb();
>     -    formats as ct_lb;
>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>     -    has prereqs ip
>     -ct_lb(192.168.1.2:80 <http://192.168.1.2:80>, 192.168.1.3:80
>     <http://192.168.1.3:80>);
>     -    encodes as group:1
>     -    has prereqs ip
>     -ct_lb(192.168.1.2, 192.168.1.3, );
>     -    formats as ct_lb(192.168.1.2, 192.168.1.3);
>     -    encodes as group:2
>     -    has prereqs ip
>     -ct_lb(fd0f::2, fd0f::3, );
>     -    formats as ct_lb(fd0f::2, fd0f::3);
>     -    encodes as group:3
>     -    has prereqs ip
>     -
>     -ct_lb(192.168.1.2:);
>     -    Syntax error at `)' expecting port number.
>     -ct_lb(192.168.1.2:123456 <http://192.168.1.2:123456>);
>     -    Syntax error at `123456' expecting port number.
>     -ct_lb(foo);
>     -    Syntax error at `foo' expecting IP address.
>     -ct_lb([192.168.1.2]);
>     -    Syntax error at `192.168.1.2' expecting IPv6 address.
>     -
>     -# ct_next
>     -ct_next;
>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
>     -    has prereqs ip
>     -
>     -# ct_commit
>     -ct_commit;
>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>     -    has prereqs ip
>     -ct_commit();
>     -    formats as ct_commit;
>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>     -    has prereqs ip
>     -ct_commit(ct_mark=1);
>     -    formats as ct_commit(ct_mark=0x1);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
>     -    has prereqs ip
>     -ct_commit(ct_mark=1/1);
>     -    formats as ct_commit(ct_mark=0x1/0x1);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
>     -    has prereqs ip
>     -ct_commit(ct_label=1);
>     -    formats as ct_commit(ct_label=0x1);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_label=1/1);
>     -    formats as ct_commit(ct_label=0x1/0x1);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_mark=1, ct_label=2);
>     -    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label))
>     -    has prereqs ip
>     -
>     -ct_commit(ct_label=0x01020304050607080910111213141516);
>     -    formats as ct_commit(ct_label=0x1020304050607080910111213141516);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_label=0x181716151413121110090807060504030201);
>     -    formats as
>     ct_commit(ct_label=0x16151413121110090807060504030201);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_label=18446744073709551615);
>     -    formats as ct_commit(ct_label=0xffffffffffffffff);
>     -    encodes as
>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label))
>     -    has prereqs ip
>     -ct_commit(ct_label=18446744073709551616);
>     -    Decimal constants must be less than 2**64.
>     -
>     -# ct_dnat
>     -ct_dnat;
>     -    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
>     -    has prereqs ip
>     -ct_dnat(192.168.1.2);
>     -    encodes as
>     ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
>     -    has prereqs ip
>     -
>     -ct_dnat(192.168.1.2, 192.168.1.3);
>     -    Syntax error at `,' expecting `)'.
>     -ct_dnat(foo);
>     -    Syntax error at `foo' expecting IPv4 address.
>     -ct_dnat(foo, bar);
>     -    Syntax error at `foo' expecting IPv4 address.
>     -ct_dnat();
>     -    Syntax error at `)' expecting IPv4 address.
>     -
>     -# ct_snat
>     -ct_snat;
>     -    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
>     -    has prereqs ip
>     -ct_snat(192.168.1.2);
>     -    encodes as
>     ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
>     -    has prereqs ip
>     -
>     -ct_snat(192.168.1.2, 192.168.1.3);
>     -    Syntax error at `,' expecting `)'.
>     -ct_snat(foo);
>     -    Syntax error at `foo' expecting IPv4 address.
>     -ct_snat(foo, bar);
>     -    Syntax error at `foo' expecting IPv4 address.
>     -ct_snat();
>     -    Syntax error at `)' expecting IPv4 address.
>     -
>     -# ct_clear
>     -ct_clear;
>     -    encodes as ct_clear
>     -
>     -# clone
>     -clone { ip4.dst = 255.255.255.255; output; }; next;
>     -    encodes as
>     clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
>     -    has prereqs eth.type == 0x800
>     -
>     -# arp
>     -arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip4
>     -arp { };
>     -    formats as arp { drop; };
>     -    encodes as controller(userdata=00.00.00.00.00.00.00.00)
>     -    has prereqs ip4
>     -
>     -# get_arp
>     -get_arp(outport, ip4.dst);
>     -    encodes as
>     push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[]
>     -    has prereqs eth.type == 0x800
>     -get_arp(inport, reg0);
>     -    encodes as
>     push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[]
>     -
>     -get_arp;
>     -    Syntax error at `;' expecting `('.
>     -get_arp();
>     -    Syntax error at `)' expecting field name.
>     -get_arp(inport);
>     -    Syntax error at `)' expecting `,'.
>     -get_arp(inport ip4.dst);
>     -    Syntax error at `ip4.dst' expecting `,'.
>     -get_arp(inport, ip4.dst;
>     -    Syntax error at `;' expecting `)'.
>     -get_arp(inport, eth.dst);
>     -    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is
>     required.
>     -get_arp(inport, outport);
>     -    Cannot use string field outport where numeric field is required.
>     -get_arp(reg0, ip4.dst);
>     -    Cannot use numeric field reg0 where string field is required.
>     -
>     -# put_arp
>     -put_arp(inport, arp.spa, arp.sha);
>     -    encodes as
>     push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[]
>     -    has prereqs eth.type == 0x806 && eth.type == 0x806
>     -
>     -# put_dhcp_opts
>     -reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>     -    encodes as
>     controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
>     -reg2[5] =
>     put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org
>     <http://ovn.org>",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot");
>     -    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router
>     = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name =
>     "ovn.org <http://ovn.org>", wpad = "https://example.org",
>     bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix =
>     "/tftpboot");
>     -    encodes as
>     controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause)
>     -reg0[15] =
>     put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1
>     <http://30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1>},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5});
>     -    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4,
>     router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400,
>     ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8,
>     7.7.7.7}, classless_static_route = {30.0.0.0/24
>     <http://30.0.0.0/24>, 10.0.0.4, 40.0.0.0/16 <http://40.0.0.0/16>,
>     10.0.0.6, 0.0.0.0/0 <http://0.0.0.0/0>, 10.0.0.1}, ethernet_encap
>     = 1, router_discovery = 0, tftp_server_address = {10.0.0.4,
>     10.0.0.5});
>     -    encodes as
>     controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause)
>     -
>     -reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>     -    Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
>     -reg1[0] = put_dhcp_opts();
>     -    put_dhcp_opts requires offerip to be specified.
>     -reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
>     -    Syntax error at `x' expecting DHCPv4 option name.
>     -reg1[0] = put_dhcp_opts(router = 10.0.0.1);
>     -    put_dhcp_opts requires offerip to be specified.
>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
>     -    Syntax error at `"hi"'.
>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
>     -    Syntax error at `xyzzy' expecting DHCPv4 option name.
>     -reg1[0] = put_dhcp_opts(offerip="xyzzy");
>     -    DHCPv4 option offerip requires numeric value.
>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>     -    DHCPv4 option domain_name requires string value.
>     -
>     -# nd_ns
>     -nd_ns { nd.target = xxreg0; output; };
>     -    encodes as
>     controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
>     -    has prereqs ip6
>     -
>     -nd_ns { };
>     -    formats as nd_ns { drop; };
>     -    encodes as controller(userdata=00.00.00.09.00.00.00.00)
>     -    has prereqs ip6
>     -
>     -# nd_na
>     -nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc;
>     outport = inport; inport = ""; /* Allow sending out inport. */
>     output; };
>     -    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll =
>     12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>     -    encodes as
>     controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
>     -    has prereqs nd_ns
>     -# nd_na_router
>     -nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll =
>     12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending
>     out inport. */ output; };
>     -    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll
>     = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>     -    encodes as
>     controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
>     -    has prereqs nd_ns
>     -
>     -# get_nd
>     -get_nd(outport, ip6.dst);
>     -    encodes as
>     push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[]
>     -    has prereqs eth.type == 0x86dd
>     -get_nd(inport, xxreg0);
>     -    encodes as
>     push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[]
>     -get_nd;
>     -    Syntax error at `;' expecting `('.
>     -get_nd();
>     -    Syntax error at `)' expecting field name.
>     -get_nd(inport);
>     -    Syntax error at `)' expecting `,'.
>     -get_nd(inport ip6.dst);
>     -    Syntax error at `ip6.dst' expecting `,'.
>     -get_nd(inport, ip6.dst;
>     -    Syntax error at `;' expecting `)'.
>     -get_nd(inport, eth.dst);
>     -    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is
>     required.
>     -get_nd(inport, outport);
>     -    Cannot use string field outport where numeric field is required.
>     -get_nd(xxreg0, ip6.dst);
>     -    Cannot use numeric field xxreg0 where string field is required.
>     -
>     -# put_nd
>     -put_nd(inport, nd.target, nd.sll);
>     -    encodes as
>     push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[]
>     -    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) &&
>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>     eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd &&
>     ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) &&
>     ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) &&
>     icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a &&
>     (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 &&
>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>     eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 ||
>     eth.type == 0x86dd)
>     -
>     -# put_dhcpv6_opts
>     -reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
>     00:00:00:00:10:02);
>     -    encodes as
>     controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
>     -reg1[0] = put_dhcpv6_opts();
>     -    encodes as
>     controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
>     -reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
>     -    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1,
>     ae70::2});
>     -    encodes as
>     controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
>     -reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc,
>     dns_server={ae70::1,ae89::2});
>     -    formats as reg1[0] = put_dhcpv6_opts(server_id =
>     12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
>     -    encodes as
>     controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
>     -reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org
>     <http://ovn.org>");
>     -    encodes as
>     controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause)
>     -reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
>     -    Syntax error at `x' expecting DHCPv6 option name.
>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
>     -    Syntax error at `"hi"'.
>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
>     -    Syntax error at `xyzzy' expecting DHCPv6 option name.
>     -reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
>     -    DHCPv6 option ia_addr requires numeric value.
>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
>     -    DHCPv6 option domain_search requires string value.
>     -
>     -# set_queue
>     -set_queue(0);
>     -    encodes as set_queue:0
>     -set_queue(61440);
>     -    encodes as set_queue:61440
>     -set_queue(65535);
>     -    Queue ID 65535 for set_queue is not in valid range 0 to 61440.
>     -
>     -# dns_lookup
>     -reg1[0] = dns_lookup();
>     -    encodes as
>     controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause)
>     -    has prereqs udp
>     -reg1[0] = dns_lookup("foo");
>     -    dns_lookup doesn't take any parameters
>     -
>     -# set_meter
>     -set_meter(0);
>     -    Rate 0 for set_meter is not in valid.
>     -set_meter(1);
>     -    encodes as meter:1
>     -set_meter(100, 1000);
>     -    encodes as meter:2
>     -set_meter(100, 1000, );
>     -    Syntax error at `,' expecting `)'.
>     -set_meter(4294967295, 4294967295);
>     -    encodes as meter:3
>     -
>     -# log
>     -log(verdict=allow, severity=warning);
>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
>     -log(name="test1", verdict=drop, severity=info);
>     -    encodes as
>     controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
>     -log(verdict=drop, severity=info, meter="meter1");
>     -    encodes as
>     controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
>     -log(name="test1", verdict=drop, severity=info, meter="meter1");
>     -    encodes as
>     controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4)
>     -log(verdict=drop);
>     -    formats as log(verdict=drop, severity=info);
>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
>     -log(verdict=bad_verdict, severity=info);
>     -    Syntax error at `bad_verdict' unknown verdict.
>     -log(verdict=drop, severity=bad_severity);
>     -    Syntax error at `bad_severity' unknown severity.
>     -log(severity=notice);
>     -    Syntax error at `;' expecting verdict.
>     -
>     -# put_nd_ra_opts
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>     = aef0::/64, slla = ae:01:02:03:04:05);
>     -    encodes as
>     controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
>     -    has prereqs ip6
>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla =
>     ae:01:02:03:04:10, mtu = 1450);
>     -    encodes as
>     controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause)
>     -    has prereqs ip6
>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>     ae:01:02:03:04:06, prefix = aef0::/64);
>     -    encodes as
>     controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
>     -    has prereqs ip6
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>     = aef0::/64);
>     -    slla option not present
>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>     ae:01:02:03:04:10);
>     -    encodes as
>     controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
>     -    has prereqs ip6
>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>     ae:01:02:03:04:10);
>     -    encodes as
>     controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
>     -    has prereqs ip6
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla =
>     ae:01:02:03:04:10);
>     -    prefix option needs to be set when address mode is
>     slaac/dhcpv6_stateless.
>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>     ae:01:02:03:04:10);
>     -    prefix option needs to be set when address mode is
>     slaac/dhcpv6_stateless.
>     -reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix =
>     aef0::/64, slla = ae:01:02:03:04:10);
>     -    Syntax error at `dhcpv6_stateless' expecting constant.
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>     = aef0::, slla = ae:01:02:03:04:10);
>     -    Invalid value for "prefix" option
>     -reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla =
>     ae:01:02:03:04:10);
>     -    Invalid value for "addr_mode" option
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla
>     = ae:01:02:03:04:10);
>     -    IPv6 ND RA option mtu requires numeric value.
>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4,
>     slla = ae:01:02:03:04:10);
>     -    Invalid value for "mtu" option
>     -
>     -# icmp4
>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip4
>     -
>     -icmp4 { };
>     -    formats as icmp4 { drop; };
>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>     -    has prereqs ip4
>     -
>     -# icmp4 with icmp4.frag_mtu
>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>     output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip4
>     -
>     -# icmp4_error
>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip4
>     -
>     -icmp4_error { };
>     -    formats as icmp4_error { drop; };
>     -    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
>     -    has prereqs ip4
>     -
>     -# icmp4_error with icmp4.frag_mtu
>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>     output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip4
>     -
>     -icmp4.frag_mtu = 1500;
>     -    encodes as
>     controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
>     -
>     -# icmp6
>     -icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs ip6
>     -
>     -icmp6 { };
>     -    formats as icmp6 { drop; };
>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>     -    has prereqs ip6
>     -
>     -# tcp_reset
>     -tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     -    encodes as
>     controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     -    has prereqs tcp
>     -
>     -tcp_reset { };
>     -    formats as tcp_reset { drop; };
>     -    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
>     -    has prereqs tcp
>     -
>     -# trigger_event
>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer =
>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>     -    encodes as
>     controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
>     -
>     -# Testing invalid vip results in extra error messages from
>     socket-util.c
>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>     <http://10.0.0.1:80>", protocol = "sctp", load_balancer =
>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>     -    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer = "bacon");
>     -    Load balancer 'bacon' is not a UUID
>     -
>     -# IGMP
>     -igmp;
>     -    encodes as controller(userdata=00.00.00.10.00.00.00.00)
>     -
>     -# Contradictionary prerequisites (allowed but not useful):
>     -ip4.src = ip6.src[0..31];
>     -    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>     -ip4.src <-> ip6.src[0..31];
>     -    encodes as
>     push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>     -
>     -# check_pkt_larger
>     -reg0[0] = check_pkt_larger(1500);
>     -    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
>     -
>     -reg0 = check_pkt_larger(1500);
>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>     required.
>     -
>     -reg0 = check_pkt_larger(foo);
>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>     required.
>     -
>     -reg0[0] = check_pkt_larger(foo);
>     -    Syntax error at `foo' expecting `;'.
>     -
>     -# Miscellaneous negative tests.
>     -;
>     -    Syntax error at `;'.
>     -xyzzy;
>     -    Syntax error at `xyzzy' expecting action.
>     -next; 123;
>     -    Syntax error at `123'.
>     -next; xyzzy;
>     -    Syntax error at `xyzzy' expecting action.
>     -next
>     -    Syntax error at end of input expecting `;'.
>     -]])
>     -sed '/^[[      ]]/d' test-cases.txt > input.txt
>     -cp test-cases.txt expout
>     -AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout])
>     -AT_CLEANUP
>     -
>     -AT_BANNER([OVN end-to-end tests])
>     -
>     -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
>     -AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
>     -AT_KEYWORDS([ovnarp])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Create hypervisors hv[123].
>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>     -# Add all of the vifs to a single logical switch lsw0.
>     -# Turn on port security on all the vifs except vif[123]1.
>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2 3; do
>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>     vif$i$j external-ids:iface-id=lp$i$j
>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>     -        if test $j = 1; then
>     -            ovn-nbctl lsp-set-addresses lp$i$j
>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>     -        else
>     -            if test $j = 3; then
>     -                ip_addrs="192.168.0.$i$j
>     fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
>     -            else
>     -                ip_addrs="192.168.0.$i$j"
>     -            fi
>     -            ovn-nbctl lsp-set-addresses lp$i$j
>     "f0:00:00:00:00:$i$j $ip_addrs"
>     -            ovn-nbctl lsp-set-port-security lp$i$j
>     f0:00:00:00:00:$i$j
>     -        fi
>     -    done
>     -done
>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>     inport == "lp11"' drop
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>     outport == "lp33"' drop
>     -ovn-nbctl create Address_Set name=set1
>     addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>     eth.src == $set1 && outport == "lp33"' drop
>     -
>     -get_lsp_uuid () {
>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>     -}
>     -
>     -ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid
>     lp22`,`get_lsp_uuid lp33`
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 &&
>     outport == @pg1' drop
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Make sure there is no attempt to adding duplicated flows by
>     ovn-controller
>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv${1%?}
>     -}
>     -
>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>     for vif11.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -test_packet() {
>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>     -    local
>     request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -    hv=`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>     -
>     -    if test X$reply_ha = X; then
>     -        # Expect to receive the broadcast ARP on the other
>     logical switch ports
>     -        # if no reply is expected.
>     -        local i j
>     -        for i in 1 2 3; do
>     -            for j in 1 2 3; do
>     -                if test $i$j != $inport; then
>     -                    echo $request >> $i$j.expected
>     -                fi
>     -            done
>     -        done
>     -    else
>     -        # Expect to receive the reply, if any.
>     -        local
>     reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>     -        echo $reply >> $inport.expected
>     -    fi
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast packets are delivered to exactly one logical switch port
>     -#    (except that packets destined to their input ports are dropped).
>     -#
>     -# 2. Broadcast and multicast are delivered to all logical switch
>     ports
>     -#    except the input port.
>     -#
>     -# 3. When port security is turned on, the switch drops packets
>     from the wrong
>     -#    MAC address.
>     -#
>     -# 4. The switch drops all packets with a VLAN tag.
>     -#
>     -# 5. The switch drops all packets with a multicast source
>     address.  (This only
>     -#    affects behavior when port security is turned off, since
>     otherwise port
>     -#    security would drop the packet anyway.)
>     -#
>     -# 6. The switch delivers packets with an unknown destination to
>     logical
>     -#    switch ports with "unknown" among their MAC addresses (and port
>     -#    security disabled).
>     -#
>     -# 7. The switch drops unicast packets that violate an ACL.
>     -#
>     -# 8. The switch drops multicast and broadcast packets that
>     violate an ACL.
>     -#
>     -# 9. OVN generates responses to ARP requests for known IPs,
>     except for
>     -#    requests from a port for the port's own IP.
>     -#
>     -# 10. No response to ARP requests for unknown IPs.
>     -
>     -for is in 1 2 3; do
>     -    for js in 1 2 3; do
>     -        s=$is$js
>     -        bcast=
>     -        unknown=
>     -        bacl2=
>     -        bacl3=
>     -        for id in 1 2 3; do
>     -            for jd in 1 2 3; do
>     -                d=$id$jd
>     -
>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>     -                test_packet $s f000000000$d f000000000$s $s$d
>     $unicast     #1
>     -
>     -                if test $d != $s && test $js = 1; then
>     -                    impersonate=$d
>     -                else
>     -                    impersonate=
>     -                fi
>     -                test_packet $s f000000000$d f00000000055 55$d
>     $impersonate #3
>     -
>     -                if test $d != $s && test $s != 11; then acl2=$d;
>     else acl2=; fi
>     -                if test $d != $s && test $d != 33; then acl3=$d;
>     else acl3=; fi
>     -                if test $d = $s || (test $js = 1 && test $d =
>     33); then
>     -                    # Source of 11, 21, or 31 and dest of 33
>     should be dropped
>     -                    # due to the 4th ACL that uses address_set(set1).
>     -                    acl4=
>     -                else
>     -                    acl4=$d
>     -                fi
>     -                if test $d = $s || test $d = 22 || test $d = 33; then
>     -                    # dest of 22 and 33 should be dropped
>     -                    # due to the 5th ACL that uses port_group(pg1).
>     -                    acl5=
>     -                else
>     -                    acl5=$d
>     -                fi
>     -                test_packet $s f000000000$d f000000000$s 1234   
>         #7, acl1
>     -                test_packet $s f000000000$d f000000000$s 1235
>     $acl2  #7, acl2
>     -                test_packet $s f000000000$d f000000000$s 1236
>     $acl3  #7, acl3
>     -                test_packet $s f000000000$d f000000000$s 1237
>     $acl4  #7, acl4
>     -                test_packet $s f000000000$d f000000000$s 1238
>     $acl5  #7, acl5
>     -
>     -                test_packet $s f000000000$d f00000000055
>     810000091234      #4
>     -                test_packet $s f000000000$d 0100000000$s $s$d   
>               #5
>     -
>     -                if test $d != $s && test $jd = 1; then
>     -                    unknown="$unknown $d"
>     -                fi
>     -                bcast="$bcast $unicast"
>     -                bacl2="$bacl2 $acl2"
>     -                bacl3="$bacl3 $acl3"
>     -
>     -                sip=`ip_to_hex 192 168 0 $is$js`
>     -                tip=`ip_to_hex 192 168 0 $id$jd`
>     -                tip_unknown=`ip_to_hex 11 11 11 11`
>     -                if test $d != $s; then
>     -                    reply_ha=f000000000$d
>     -                else
>     -                    reply_ha=
>     -                fi
>     -                test_arp $s f000000000$s $sip $tip $reply_ha     
>              #9
>     -                test_arp $s f000000000$s $sip $tip_unknown      
>              #10
>     -
>     -                if test $jd = 3; then
>     -                    # lsp[123]3 has an additional ip
>     192.169.0.[123]3.
>     -                    tip=`ip_to_hex 192 169 0 $id$jd`
>     -                    test_arp $s f000000000$s $sip $tip $reply_ha 
>              #9
>     -                fi
>     -            done
>     -        done
>     -
>     -        # Broadcast and multicast.
>     -        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast   
>              #2
>     -        test_packet $s 010000000000 f000000000$s ${s}ff $bcast   
>              #2
>     -        if test $js = 1; then
>     -            bcast_impersonate=$bcast
>     -        else
>     -            bcast_impersonate=
>     -        fi
>     -        test_packet $s 010000000000 f00000000044 44ff
>     $bcast_impersonate   #3
>     -
>     -        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown 
>              #6
>     -
>     -        test_packet $s ffffffffffff f000000000$s 1234          
>     #8, acl1
>     -        test_packet $s ffffffffffff f000000000$s 1235 $bacl2     
>        #8, acl2
>     -        test_packet $s ffffffffffff f000000000$s 1236 $bacl3     
>        #8, acl3
>     -        test_packet $s 010000000000 f000000000$s 1234          
>     #8, acl1
>     -        test_packet $s 010000000000 f000000000$s 1235 $bacl2     
>        #8, acl2
>     -        test_packet $s 010000000000 f000000000$s 1236 $bacl3     
>        #8, acl3
>     -    done
>     -done
>     -
>     -# set address for lp13 with invalid characters.
>     -# lp13 should be configured with only 192.168.0.13.
>     -ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13
>     invalid 192.169.0.13"
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -sip=`ip_to_hex 192 168 0 11`
>     -tip=`ip_to_hex 192 168 0 13`
>     -test_arp 11 f00000000011  $sip $tip f00000000013
>     -
>     -tip=`ip_to_hex 192 169 0 13`
>     -#arp request for 192.169.0.13 should be flooded
>     -test_arp 11 f00000000011  $sip $tip
>     -
>     -# dump information and flows with counters
>     -ovn-sbctl dump-flows -- list multicast_group
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv3 dump ------"
>     -as hv3 ovs-vsctl show
>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>     -    done
>     -done
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -# 2 hypervisors, one logical switch, 2 logical ports per hypervisor
>     -# logical ports bound to chassis encap-ip.
>     -AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
>     -AT_KEYWORDS([ovnarp])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Create hypervisors hv[12].
>     -# Add vif1[12] to hv1, vif2[12] to hv2
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2; do
>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>     vif$i$j external-ids:iface-id=lp$i$j
>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>     -        ip_addrs="192.168.0.$i$j"
>     -        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
>     $ip_addrs"
>     -        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j
>     f0:00:00:00:00:$i$j
>     -    done
>     -done
>     -
>     -get_lsp_uuid () {
>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>     -}
>     -
>     -# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just
>     do it
>     -# explictly
>     -
>     -# For Chassis hv1
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp11], [0], [dnl
>     -encap               : [[]]
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp12], [0], [dnl
>     -encap               : [[]]
>     -])
>     -
>     -# For Chassis hv2
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp21], [0], [dnl
>     -encap               : [[]]
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp22], [0], [dnl
>     -encap               : [[]]
>     -])
>     -
>     -# Bind the ports to the encap-ip
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        as hv$i
>     -        ovs-vsctl set Interface vif$i$j
>     external-ids:encap-ip=192.168.0.$i
>     -    done
>     -done
>     -
>     -sleep 1
>     -
>     -# dump port bindings; since we have vxlan and geneve tunnels, we
>     expect the
>     -# ports to be bound to geneve tunnels.
>     -
>     -# For Chassis 1
>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>     encap chassis_name=hv1 type=geneve ip=192.168.0.1`
>     -
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp11], [0], [dnl
>     -encap               : ${encap_rec}
>     -])
>     -
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp12], [0], [dnl
>     -encap               : ${encap_rec}
>     -])
>     -
>     -# For Chassis 2
>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>     encap chassis_name=hv2 type=geneve ip=192.168.0.2`
>     -
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp21], [0], [dnl
>     -encap               : ${encap_rec}
>     -])
>     -
>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>     lp22], [0], [dnl
>     -encap               : ${encap_rec}
>     -])
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Make sure there is no attempt to adding duplicated flows by
>     ovn-controller
>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv${1%?}
>     -}
>     -
>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>     for vif11.
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -test_packet() {
>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast packets are delivered to exactly one logical switch port
>     -#    (except that packets destined to their input ports are dropped).
>     -
>     -for is in 1 2; do
>     -    for js in 1 2; do
>     -        s=$is$js
>     -        bcast=
>     -        unknown=
>     -        bacl2=
>     -        bacl3=
>     -        for id in 1 2 3; do
>     -            for jd in 1 2 3; do
>     -                d=$id$jd
>     -
>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>     -                test_packet $s f000000000$d f000000000$s $s$d
>     $unicast     #1
>     -            done
>     -        done
>     -
>     -    done
>     -done
>     -
>     -# dump information and flows with counters
>     -ovn-sbctl dump-flows -- list multicast_group
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv3 dump ------"
>     -as hv3 ovs-vsctl show
>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>     -    done
>     -done
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Create a logical switch and some logical ports.
>     -# Turn on port security on all lports except ls1.
>     -# Make ls1 a destination for unknown MACs.
>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>     -ovn-nbctl ls-add lsw0
>     -ovn-sbctl chassis-add hv0 geneve 127.0.0.1
>     -for i in 1 2 3; do
>     -    ovn-nbctl lsp-add lsw0 lp$i
>     -done
>     -ovn-nbctl --wait=sb sync
>     -for i in 1 2 3; do
>     -    ovn-sbctl lsp-bind lp$i hv0
>     -    if test $i = 1; then
>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>     192.168.0.$i" unknown
>     -    else
>     -        if test $i = 3; then
>     -           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64
>     192.169.0.$i"
>     -        else
>     -           ip_addrs="192.168.0.$i"
>     -        fi
>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>     $ip_addrs"
>     -        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
>     -    fi
>     -done
>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>     inport == "lp1"' drop
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>     outport == "lp3"' drop
>     -ovn-nbctl create Address_Set name=set1
>     addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>     eth.src == $set1 && outport == "lp3"' drop
>     -
>     -ovn-nbctl --wait=sb sync
>     -on_exit 'kill `cat ovn-trace.pid`'
>     -ovn-trace --detach --pidfile --no-chdir
>     -
>     -# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>     for vif11.
>     -test_packet() {
>     -    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
>     -    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst &&
>     eth.src==$eth_src"
>     -    while :; do
>     -        case $1 in # (
>     -            -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; # (
>     -            -eth) uflow="$uflow && eth.type == 0x$2"; shift;
>     shift ;; # (
>     -            *) break ;;
>     -        esac
>     -    done
>     -    for outport; do
>     -        echo "output(\"lp$outport\");"
>     -    done > expout
>     -
>     -    AT_CAPTURE_FILE([trace])
>     -    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" |
>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>     -}
>     -
>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>     -
>     -    local request="inport == \"lp$inport\"
>     -                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src == $sha
>     -                   && arp.op == 1 && arp.sha == $sha && arp.spa
>     == $spa
>     -                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa ==
>     $tpa"
>     -
>     -    if test -z "$reply_ha"; then
>     -        reply=
>     -        local i
>     -        for i in 1 2 3; do
>     -            if test $i != $inport; then
>     -                reply="${reply}output(\"lp$i\");
>     -"
>     -            fi
>     -        done
>     -    else
>     -        reply="\
>     -eth.dst = $sha;
>     -eth.src = $reply_ha;
>     -arp.op = 2;
>     -arp.tha = $sha;
>     -arp.sha = $reply_ha;
>     -arp.tpa = $spa;
>     -arp.spa = $tpa;
>     -output(\"lp$inport\");
>     -"
>     -    fi
>     -
>     -    AT_CAPTURE_FILE([trace])
>     -    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0
>     "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
>     -}
>     -
>     -# Send packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast packets are delivered to exactly one logical switch port
>     -#    (except that packets destined to their input ports are dropped).
>     -#
>     -# 2. Broadcast and multicast are delivered to all logical switch
>     ports
>     -#    except the input port.
>     -#
>     -# 3. When port security is turned on, the switch drops packets
>     from the wrong
>     -#    MAC address.
>     -#
>     -# 4. The switch drops all packets with a VLAN tag.
>     -#
>     -# 5. The switch drops all packets with a multicast source
>     address.  (This only
>     -#    affects behavior when port security is turned off, since
>     otherwise port
>     -#    security would drop the packet anyway.)
>     -#
>     -# 6. The switch delivers packets with an unknown destination to
>     logical
>     -#    switch ports with "unknown" among their MAC addresses (and port
>     -#    security disabled).
>     -#
>     -# 7. The switch drops unicast packets that violate an ACL.
>     -#
>     -# 8. The switch drops multicast and broadcast packets that
>     violate an ACL.
>     -#
>     -# 9. OVN generates responses to ARP requests for known IPs,
>     except for
>     -#    requests from a port for the port's own IP.
>     -#
>     -# 10. No response to ARP requests for unknown IPs.
>     -
>     -for s in 1 2 3; do
>     -    bcast=
>     -    unknown=
>     -    bacl2=
>     -    bacl3=
>     -    for d in 1 2 3; do
>     -        echo
>     -        echo "lp$s -> lp$d"
>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s
>     $unicast      #1
>     -
>     -        if test $d != $s && test $s = 1; then
>     -            impersonate=$d
>     -        else
>     -            impersonate=
>     -        fi
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>     $impersonate   #3
>     -
>     -        if test $d != $s && test $s != 1; then acl2=$d; else
>     acl2=; fi
>     -        if test $d != $s && test $d != 3; then acl3=$d; else
>     acl3=; fi
>     -        if test $d = $s || ( (test $s = 1 || test $s = 2) && test
>     $d = 3); then
>     -            # Source of 1 or 2 and dest of 3 should be dropped
>     -            # due to the 4th ACL that uses address_set(set1).
>     -            acl4=
>     -        else
>     -            acl4=$d
>     -        fi
>     -
>     -        #7, acl1 to acl4:
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>     1234
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>     1235 $acl2
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>     1236 $acl3
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>     1237 $acl4
>     -
>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>     -vlan          #4
>     -        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s     
>              #5
>     -
>     -        if test $d != $s && test $d = 1; then
>     -            unknown="$unknown $d"
>     -        fi
>     -        bcast="$bcast $unicast"
>     -        bacl2="$bacl2 $acl2"
>     -        bacl3="$bacl3 $acl3"
>     -
>     -        sip=192.168.0.$s
>     -        tip=192.168.0.$d
>     -        tip_unknown=11.11.11.11
>     -        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else
>     reply_ha=; fi
>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha      
>              #9
>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown        
>            #10
>     -
>     -        if test $d = 3; then
>     -            # lp3 has an additional ip 192.169.0.[123]3.
>     -            tip=192.169.0.$d
>     -            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha   
>              #9
>     -        fi
>     -    done
>     -
>     -    # Broadcast and multicast.
>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast   
>              #2
>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast   
>              #2
>     -    if test $s = 1; then
>     -       bcast_impersonate=$bcast
>     -    else
>     -       bcast_impersonate=
>     -    fi
>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44
>     $bcast_impersonate  #3
>     -
>     -    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown 
>              #6
>     -
>     -    #8, acl1 to acl3:
>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235
>     $bacl2
>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236
>     $bacl3
>     -
>     -    #8, acl1 to acl3:
>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235
>     $bacl2
>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236
>     $bacl3
>     -done
>     -
>     -AT_CLEANUP
>     -
>     -# 2 hypervisors, 4 logical ports per HV
>     -# 2 locally attached networks (one flat, one vlan tagged over
>     same device)
>     -# 2 ports per HV on each network
>     -AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# In this test cases we create 3 switches, all connected to same
>     -# physical network (through br-phys on each HV). Each switch has
>     -# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>     -# lp23 means VIF 3 on hv2.
>     -#
>     -# Each switch's VLAN tag and their logical switch ports are:
>     -#   - ls1:
>     -#       - untagged
>     -#       - ports: lp11, lp12, lp21, lp22
>     -#
>     -#   - ls2:
>     -#       - tagged with VLAN 101
>     -#       - ports: lp13, lp14, lp23, lp24
>     -#   - ls3:
>     -#       - untagged
>     -#       - ports: lp15, lp25
>     -#
>     -# Note: a localnet port is created for each switch to connect to
>     -# physical network.
>     -
>     -for i in 1 2 3; do
>     -    ls_name=ls$i
>     -    ovn-nbctl ls-add $ls_name
>     -    ln_port_name=ln$i
>     -    if test $i -eq 2; then
>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>     -    else
>     -        ovn-nbctl lsp-add $ls_name $ln_port_name
>     -    fi
>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>     -done
>     -
>     -# lsp_to_ls LSP
>     -#
>     -# Prints the name of the logical switch that contains LSP.
>     -lsp_to_ls () {
>     -    case $1 in dnl (
>     -        lp?[[12]]) echo ls1 ;; dnl (
>     -        lp?[[34]]) echo ls2 ;; dnl (
>     -        lp?5) echo ls3 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2 3 4 5; do
>     -        ovs-vsctl add-port br-int vif$i$j -- \
>     -            set Interface vif$i$j external-ids:iface-id=lp$i$j \
>     - options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>     - options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>     -                                  ofport-request=$i$j
>     -
>     -        lsp_name=lp$i$j
>     -        ls_name=$(lsp_to_ls $lsp_name)
>     -
>     -        ovn-nbctl lsp-add $ls_name $lsp_name
>     -        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
>     -        ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$j
>     -
>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` =
>     xup])
>     -    done
>     -done
>     -ovn-nbctl --wait=sb sync
>     -ovn-sbctl dump-flows
>     -
>     -OVN_POPULATE_ARP
>     -
>     -# XXX This is now the 3rd copy of these functions in this file ...
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv${1%?}
>     -}
>     -#
>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is
>     specified as
>     -# logical switch port numbers, e.g. 11 for vif11.
>     -#
>     -# EOUT is the end-to-end output port, that is, where the packet
>     will end up
>     -# after possibly bouncing through one or more localnet ports. 
>     LOUT is the
>     -# logical output port, which might be a localnet port, as seen by
>     ovn-trace
>     -# (which doesn't know what localnet ports are connected to and
>     therefore can't
>     -# figure out the end-to-end answer).
>     -for i in 1 2; do
>     -    for j in 1 2 3 4 5; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -test_packet() {
>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
>     -    echo "$@"
>     -
>     -    # First try tracing the packet.
>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>     eth.src==$src && eth.type==0x$eth"
>     -    if test $lout != drop; then
>     -        echo "output(\"$lout\");"
>     -    fi > expout
>     -    AT_CAPTURE_FILE([trace])
>     -    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" |
>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>     -
>     -    # Then actually send a packet, for an end-to-end test.
>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>     -    hv=`vif_to_hv $inport`
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    if test $eout != drop; then
>     -        echo $packet >> ${eout#lp}.expected
>     -    fi
>     -}
>     -
>     -# lp11 and lp21 are on the same network (phys, untagged)
>     -# and on different hypervisors
>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>     -
>     -# lp11 and lp12 are on the same network (phys, untagged)
>     -# and on the same hypervisor
>     -test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
>     -test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
>     -
>     -# lp13 and lp23 are on the same network (phys, VLAN 101)
>     -# and on different hypervisors
>     -test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
>     -test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
>     -
>     -# lp13 and lp14 are on the same network (phys, VLAN 101)
>     -# and on the same hypervisor
>     -test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
>     -test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
>     -
>     -# lp11 and lp15 are on the same network (phys, untagged),
>     -# same hypervisor, and on different switches
>     -test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
>     -test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
>     -
>     -# lp11 and lp25 are on the same network (phys, untagged),
>     -# different hypervisors, and on different switches
>     -test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
>     -test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
>     -
>     -# Ports that should not be able to communicate
>     -test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
>     -test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
>     -test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
>     -test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
>     -test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
>     -test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
>     -test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
>     -test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
>     -
>     -# Dump a bunch of info helpful for debugging if there's a failure.
>     -
>     -echo "------ OVN dump ------"
>     -ovn-nbctl show
>     -ovn-sbctl show
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2; do
>     -    for j in 1 2 3 4 5; do
>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>     -    done
>     -done
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
>     -AT_KEYWORDS([vtep])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Configure the Northbound database
>     -ovn-nbctl ls-add lsw0
>     -
>     -ovn-nbctl lsp-add lsw0 lp1
>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>     -
>     -ovn-nbctl lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>     -
>     -ovn-nbctl lsp-add lsw0 lp-vtep
>     -ovn-nbctl lsp-set-type lp-vtep vtep
>     -ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep
>     vtep-logical-switch=lsw0
>     -ovn-nbctl lsp-set-addresses lp-vtep unknown
>     -
>     -# lpr, lr and lrp1 are used for the ARP request handling test only.
>     -ovn-nbctl lsp-add lsw0 lpr
>     -ovn-nbctl lr-add lr
>     -ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl set Logical_Switch_Port lpr type=router \
>     -                             options:router-port=lrp1 \
>     -    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
>     -
>     -
>     -net_add n1               # Network to connect hv1, hv2, and vtep
>     -net_add n2               # Network to connect vtep and hv3
>     -
>     -# Create hypervisor hv1 connected to n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>     -
>     -# Create hypervisor hv2 connected to n1
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>     -
>     -
>     -# Start the vtep emulator with a leg in both networks
>     -sim_add vtep
>     -as vtep
>     -
>     -ovsdb-tool create "$ovs_base"/vtep/vtep.db
>     "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
>     -ovs-appctl -t ovsdb-server ovsdb-server/add-db
>     "$ovs_base"/vtep/vtep.db
>     -
>     -ovs-vsctl add-br br-phys
>     -net_attach n1 br-phys
>     -
>     -mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
>     -arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
>     -ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24
>     <http://192.168.0.3/24> >/dev/null || return 1
>     -ovs-appctl ovs/route/add 192.168.0.3/24 <http://192.168.0.3/24>
>     br-phys >/dev/null || return 1
>     -
>     -ovs-vsctl add-br br-vtep
>     -net_attach n2 br-vtep
>     -
>     -vtep-ctl add-ps br-vtep
>     -vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
>     -vtep-ctl add-ls lsw0
>     -
>     -start_daemon ovs-vtep br-vtep
>     -start_daemon ovn-controller-vtep
>     --vtep-db=unix:"$ovs_base"/vtep/db.sock
>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -
>     -OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
>     -
>     -OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode
>     lsw0 |
>     -               grep -- source`"])
>     -# It takes more time for the update to be processed by ovs-vtep.
>     -sleep 1
>     -
>     -# Add hv3 on the other side of the vtep
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -net_attach n2 br-phys
>     -
>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>     ofport-request=1
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 1
>     for vif1.
>     -for i in 1 2 3; do
>     -    : > $i.expected
>     -done
>     -test_packet() {
>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>     -    hv=hv$inport
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -# Send packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast packets are delivered to exactly one logical switch port
>     -#    (except that packets destined to their input ports are dropped).
>     -#
>     -# 2. Broadcast and multicast are delivered to all logical switch
>     ports
>     -#    except the input port.
>     -#
>     -# 3. The switch delivers packets with an unknown destination to
>     logical
>     -#    switch ports with "unknown" among their MAC addresses (and port
>     -#    security disabled).
>     -for s in 1 2 3; do
>     -    bcast=
>     -    unknown=
>     -    for d in 1 2 3; do
>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>     $unicast       #1
>     -
>     -        # The vtep (vif3) is the only one configured for "unknown"
>     -        if test $d != $s && test $d = 3; then
>     -            unknown="$unknown $d"
>     -        fi
>     -        bcast="$bcast $unicast"
>     -    done
>     -
>     -    # Broadcast and multicast.
>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast     
>            #2
>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast     
>            #2
>     -
>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown   
>            #3
>     -done
>     -
>     -# ARP request should not be responded to by logical switch router
>     -# type arp responder on HV1 and HV2 and should reach directly to
>     -# vif1 and vif2
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -sha=f00000000003
>     -spa=`ip_to_hex 192 168 1 2`
>     -tpa=`ip_to_hex 192 168 1 1`
>     -request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -as hv3 ovs-appctl netdev-dummy/receive vif3 $request
>     -echo $request >> 1.expected
>     -echo $request >> 2.expected
>     -
>     -# dump information with counters
>     -echo "------ OVN dump ------"
>     -ovn-nbctl show
>     -ovn-sbctl show
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv3 dump ------"
>     -as hv3 ovs-vsctl show
>     -# note: hv3 has no logical port bind, thus it should not have br-int
>     -AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
>     -[ovs-ofctl: br-int is not a bridge or a socket
>     -])
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>     -done
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1],[hv2],[vtep])
>     -OVN_CLEANUP_VSWITCH([hv3])
>     -
>     -AT_CLEANUP
>     -
>     -# Similar test to "hardware GW"
>     -AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Configure the Northbound database
>     -ovn-nbctl ls-add lsw0
>     -
>     -ovn-nbctl lsp-add lsw0 lp1
>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>     -
>     -ovn-nbctl lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>     -
>     -ovn-nbctl lsp-add lsw0 lp-gw
>     -ovn-nbctl lsp-set-type lp-gw l2gateway
>     -ovn-nbctl lsp-set-options lp-gw network_name=physnet1
>     l2gateway-chassis=hv_gw
>     -ovn-nbctl lsp-set-addresses lp-gw unknown
>     -
>     -net_add n1               # Network to connect hv1, hv2, and gw
>     -net_add n2               # Network to connect gw and hv3
>     -
>     -# Create hypervisor hv1 connected to n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>     -
>     -# Create hypervisor hv2 connected to n1
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>     -
>     -# Create hypervisor hv_gw connected to n1 and n2
>     -# connect br-phys bridge to n1; connect hv-gw bridge to n2
>     -sim_add hv_gw
>     -as hv_gw
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl add-br br-phys2
>     -net_attach n2 br-phys2
>     -ovs-vsctl set open .
>     external_ids:ovn-bridge-mappings="physnet1:br-phys2"
>     -
>     -# Add hv3 on the other side of the GW
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -net_attach n2 br-phys
>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>     ofport-request=1
>     -
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
>     -for i in 1 2 3; do
>     -    : > $i.expected
>     -done
>     -test_packet() {
>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>     -    hv=hv$inport
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -# Send packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast packets are delivered to exactly one lport (except
>     that packets
>     -#    destined to their input ports are dropped).
>     -#
>     -# 2. Broadcast and multicast are delivered to all lports except
>     the input port.
>     -#
>     -# 3. The lswitch delivers packets with an unknown destination to
>     lports with
>     -#    "unknown" among their MAC addresses (and port security
>     disabled).
>     -for s in 1 2 3 ; do
>     -    bcast=
>     -    unknown=
>     -    for d in 1 2 3 ; do
>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>     $unicast       #1
>     -
>     -        # The vtep (vif3) is the only one configured for "unknown"
>     -        if test $d != $s && test $d = 3; then
>     -            unknown="$unknown $d"
>     -        fi
>     -        bcast="$bcast $unicast"
>     -    done
>     -
>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast     
>            #2
>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast     
>            #3
>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown   
>            #4
>     -done
>     -
>     -echo "------ ovn-nbctl show ------"
>     -ovn-nbctl show
>     -echo "------ ovn-sbctl show ------"
>     -ovn-sbctl show
>     -
>     -echo "------ hv1 ------"
>     -as hv1 ovs-vsctl show
>     -echo "------ hv1 br-int ------"
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -echo "------ hv1 br-phys ------"
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>     -
>     -echo "------ hv2 ------"
>     -as hv2 ovs-vsctl show
>     -echo "------ hv2 br-int ------"
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -echo "------ hv2 br-phys ------"
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>     -
>     -echo "------ hv_gw ------"
>     -as hv_gw ovs-vsctl show
>     -echo "------ hv_gw br-phys ------"
>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
>     -echo "------ hv_gw br-phys2 ------"
>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
>     -
>     -echo "------ hv3 ------"
>     -as hv3 ovs-vsctl show
>     -echo "------ hv3 br-phys ------"
>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>     -done
>     -AT_CLEANUP
>     -
>     -# 3 hypervisors, 3 logical switches with 3 logical ports each, 1
>     logical router
>     -AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -#
>     -# Three logical switches ls1, ls2, ls3.
>     -# One logical router lr0 connected to ls[123],
>     -# with nine subnets, three per logical switch:
>     -#
>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 <http://192.168.11.0/24>
>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 <http://192.168.12.0/24>
>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 <http://192.168.13.0/24>
>     -#    ...
>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 <http://192.168.33.0/24>
>     -#
>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>     first two
>     -# digits are the subnet and the last digit distinguishes the VIF.
>     -for i in 1 2 3; do
>     -    ovn-nbctl ls-add ls$i
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            # Add "unknown" to MAC addresses for lp?11, so
>     packets for
>     -            # MAC-IP bindings discovered via ARP later have
>     somewhere to go.
>     -            if test $j$k = 11; then unknown=unknown; else
>     unknown=; fi
>     -
>     -            ovn-nbctl \
>     -                -- lsp-add ls$i lp$i$j$k \
>     -                -- lsp-set-addresses lp$i$j$k \
>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
>     -        done
>     -    done
>     -done
>     -
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>     192.168.$i$j.254/24
>     -        ovn-nbctl \
>     -            -- lsp-add ls$i lrp$i$j-attachment \
>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>     type=router \
>     -                             options:router-port=lrp$i$j \
>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>     -    done
>     -done
>     -
>     -ovn-nbctl set Logical_Switch_Port lrp33-attachment \
>     -    addresses='"00:00:00:00:ff:33 192.168.33.254"'
>     -
>     -# Physical network:
>     -#
>     -# Three hypervisors hv[123].
>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>     lp?13 on hv3.
>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>     on hv3.
>     -# lp?3[123] all on hv3.
>     -
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    case $1 in dnl (
>     -        ?11) echo 1 ;; dnl (
>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>     -        ?13 | ?23 | ?3?) echo 3 ;;
>     -    esac
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its
>     logical router
>     -# port, e.g. "vif_to_lrp 123" yields 12.
>     -vif_to_lrp() {
>     -    echo ${1%?}
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its logical
>     -# switch, e.g. "vif_to_ls 123" yields 1.
>     -vif_to_ls() {
>     -    echo ${1%??}
>     -}
>     -
>     -net_add n1
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -done
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            hv=`vif_to_hv $i$j$k`
>     -                as hv$hv ovs-vsctl \
>     -                -- add-port br-int vif$i$j$k \
>     -                -- set Interface vif$i$j$k \
>     -                    external-ids:iface-id=lp$i$j$k \
>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>     -                    ofport-request=$i$j$k
>     -        done
>     -    done
>     -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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>     for vif123.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            : > $i$j$k.expected
>     -        done
>     -    done
>     -done
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    in_ls=`vif_to_ls $inport`
>     -    in_lrp=`vif_to_lrp $inport`
>     -    for outport; do
>     -        out_ls=`vif_to_ls $outport`
>     -        if test $in_ls = $out_ls; then
>     -            # Ports on the same logical switch receive exactly
>     the same packet.
>     -            echo $packet
>     -        else
>     -            # Routing decrements TTL and updates source and dest MAC
>     -            # (and checksum).
>     -            out_lrp=`vif_to_lrp $outport`
>     -            echo
>     f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
>     -        fi >> $outport.expected
>     -    done
>     -}
>     -
>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>     -    local
>     request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>     -    as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
>     -
>     -    # Expect to receive the broadcast ARP on the other logical
>     switch ports if
>     -    # IP address is not configured to the switch patch port.
>     -    local i=`vif_to_ls $inport`
>     -    local j k
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            # 192.168.33.254 is configured to the switch patch
>     port for lrp33,
>     -            # so no ARP flooding expected for it.
>     -            if test $i$j$k != $inport && test $tpa != `ip_to_hex
>     192 168 33 254`; then
>     -                echo $request >> $i$j$k.expected
>     -            fi
>     -        done
>     -    done
>     -
>     -    # Expect to receive the reply, if any.
>     -    if test X$reply_ha != X; then
>     -        lrp=`vif_to_lrp $inport`
>     -        local
>     reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>     -        echo $reply >> $inport.expected
>     -    fi
>     -}
>     -
>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>     -as hv1 ovn-sbctl list port_binding
>     -as hv1 ovn-sbctl list datapath_binding
>     -as hv1 ovn-sbctl dump-flows
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Send IP packets between all pairs of source and destination ports:
>     -#
>     -# 1. Unicast IP packets are delivered to exactly one logical
>     switch port
>     -#    (except that packets destined to their input ports are dropped).
>     -#
>     -# 2. Broadcast IP packets are delivered to all logical switch ports
>     -#    except the input port.
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -for is in 1 2 3; do
>     -  for js in 1 2 3; do
>     -    for ks in 1 2 3; do
>     -      bcast=
>     -      s=$is$js$ks
>     -      smac=f00000000$s
>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>     -      for id in 1 2 3; do
>     -          for jd in 1 2 3; do
>     -              for kd in 1 2 3; do
>     -                d=$id$jd$kd
>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>     -                if test $is = $id; then dmac=f00000000$d; else
>     dmac=00000000ff$is$js; fi
>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>     -
>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>     -
>     -                if test $id = $is && test $d != $s; then
>     bcast="$bcast $d"; fi
>     -              done
>     -          done
>     -        done
>     -      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
>     -      done
>     -  done
>     -done
>     -
>     -: > mac_bindings.expected
>     -
>     -# 3. Send an IP packet from every logical port to every other subnet,
>     -#    to an IP address that does not have a static IP-MAC binding.
>     -#    This should generate a broadcast ARP request for the destination
>     -#    IP address in the destination subnet.
>     -#    Moreover generate an ARP reply for each of the IP addresses
>     ARPed
>     -for is in 1 2 3; do
>     -  for js in 1 2 3; do
>     -    for ks in 1 2 3; do
>     -      s=$is$js$ks
>     -      smac=f00000000$s
>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>     -      for id in 1 2 3; do
>     -        for jd in 1 2 3; do
>     -          if test $is$js = $id$jd; then
>     -            continue
>     -          fi
>     -
>     -          # Send the packet.
>     -          dmac=00000000ff$is$js
>     -          # Calculate a 4th octet for the destination that is
>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
>     -          # that have static MAC bindings, and fits in the range
>     -          # 0-255.
>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>     -          test_ip $s $smac $dmac $sip $dip
>     -
>     -          # Every LP on the destination subnet's lswitch should
>     -          # receive the ARP request.
>     -          lrmac=00000000ff$id$jd
>     -          lrip=`ip_to_hex 192 168 $id$jd 254`
>     -
>     arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip}
>     -          for jd2 in 1 2 3; do
>     -            for kd in 1 2 3; do
>     -              echo $arp >> $id$jd2$kd.expected
>     -            done
>     -          done
>     -
>     -          hmac=8000000000$o4
>     -          rmac=00000000ff$id$jd
>     -          echo
>     ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000
>     >> ${id}11.expected
>     -
>     -          host_mac=8000000000$o4
>     -          lrmac=00000000ff$id$jd
>     -
>     -
>     arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip}
>     -
>     -          hv=hv`vif_to_hv ${id}${jd}1`
>     -          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1
>     $arp_reply
>     -
>     -          host_ip_pretty=192.168.$id$jd.$o4
>     -          host_mac_pretty=80:00:00:00:00:$o4
>     -          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >>
>     mac_bindings.expected
>     -        done
>     -      done
>     -    done
>     -  done
>     -done
>     -
>     -# Test router replies to ARP requests from all source ports:
>     -#
>     -# 4. Router replies to query for its MAC address from port's own
>     IP address.
>     -#
>     -# 5. Router replies to query for its MAC address from any random
>     IP address
>     -#    in its subnet.
>     -#
>     -# 6. No reply to query for IP address other than router IP.
>     -#
>     -# 7. No reply to query from another subnet.
>     -for i in 1 2 3; do
>     -  for j in 1 2 3; do
>     -    for k in 1 2 3; do
>     -      smac=f00000000$i$j$k               # Source MAC
>     -      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
>     -      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
>     -      rmac=00000000ff$i$j                # Router MAC
>     -      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in subnet
>     -      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in
>     subnet
>     -
>     -      test_arp $i$j$k $smac $sip        $rip        $rmac     #4
>     -      test_arp $i$j$k $smac $otherip    $rip        $rmac     #5
>     -      test_arp $i$j$k $smac $sip        $otherip    #6
>     -
>     -      # When rip is 192.168.33.254, ARP request from externalip
>     won't be
>     -      # filtered, because 192.168.33.254 is configured to switch
>     peer port
>     -      # for lrp33.
>     -      lrp33_rsp=
>     -      if test $i = 3 && test $j = 3; then
>     -        lrp33_rsp=$rmac
>     -      fi
>     -      test_arp $i$j$k $smac $externalip $rip $lrp33_rsp #7
>     -
>     -      # MAC binding should be learned from ARP request.
>     -      host_mac_pretty=f0:00:00:00:0$i:$j$k
>     -
>     -      host_ip_pretty=192.168.$i$j.$k
>     -      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>     mac_bindings.expected
>     -
>     -      # mac_binding is learned and overwritten so only the last
>     one remains.
>     -      if test $k = 3; then
>     -          # lrp33 will not learn from ARP request, because
>     192.168.33.254 is
>     -          # configured to switch peer port for lrp33.
>     -          if test $i != 3 || test $j != 3; then
>     -              host_ip_pretty=192.168.$i$j.55
>     -              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>     mac_bindings.expected
>     -          fi
>     -      fi
>     -
>     -    done
>     -  done
>     -done
>     -
>     -
>     -# Allow some time for packet forwarding.
>     -# XXX This can be improved.
>     -sleep 1
>     -
>     -# 8. Send an IP packet from every logical port to every other
>     subnet.  These
>     -#    are the same packets already sent as #3, but now the
>     destinations' IP-MAC
>     -#    bindings have been discovered via ARP, so instead of
>     provoking an ARP
>     -#    request, these packets now get routed to their destinations
>     (which don't
>     -#    have static MAC bindings, so they go to the port we've
>     designated as
>     -#    accepting "unknown" MACs.)
>     -for is in 1 2 3; do
>     -  for js in 1 2 3; do
>     -    for ks in 1 2 3; do
>     -      s=$is$js$ks
>     -      smac=f00000000$s
>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>     -      for id in 1 2 3; do
>     -        for jd in 1 2 3; do
>     -          if test $is$js = $id$jd; then
>     -            continue
>     -          fi
>     -
>     -          # Send the packet.
>     -          dmac=00000000ff$is$js
>     -          # Calculate a 4th octet for the destination that is
>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
>     -          # that have static MAC bindings, and fits in the range
>     -          # 0-255.
>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>     -          test_ip $s $smac $dmac $sip $dip
>     -
>     -          # Expect the packet egress.
>     -          host_mac=8000000000$o4
>     -          outport=${id}11
>     -          out_lrp=$id$jd
>     -          echo
>     ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000
>     >> $outport.expected
>     -        done
>     -      done
>     -    done
>     -  done
>     -done
>     -
>     -ovn-sbctl -f csv -d bare --no-heading \
>     -    -- --columns=logical_port,ip,mac list mac_binding > mac_bindings
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>     $i$j$k`/vif$i$j$k-tx.pcap],
>     -                              [$i$j$k.expected])
>     -        done
>     -    done
>     -done
>     -
>     -# Check the MAC bindings against those expected.
>     -AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort <
>     mac_bindings.expected`
>     -])
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IP relocation using GARP request])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -#
>     -# Two logical switches ls1, ls2.
>     -# One logical router lr0 connected to ls[12],
>     -# with 2 subnets, 1 per logical switch:
>     -#
>     -#    lrp1 on ls1 for subnet 192.168.1.1/24 <http://192.168.1.1/24>
>     -#    lrp2 on ls2 for subnet 192.168.2.1/24 <http://192.168.2.1/24>
>     -#
>     -# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
>     -# VIFs' fixed IP addresses are 192.168.[12].1[12].
>     -#
>     -# There is a secondary IP 192.168.1.100 that is unknown in NB and
>     learned
>     -# through ARP only, and it can move between lp11 and lp12.
>     -#
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2 ; do
>     -    ovn-nbctl ls-add ls$i
>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
>     -    ovn-nbctl \
>     -        -- lsp-add ls$i lrp$i-attachment \
>     -        -- set Logical_Switch_Port lrp$i-attachment type=router \
>     -                         options:router-port=lrp$i \
>     -                         addresses=router
>     -    for j in 1 2; do
>     -        ovn-nbctl \
>     -            -- lsp-add ls$i lp$i$j \
>     -            -- lsp-set-addresses lp$i$j \
>     -               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
>     -    done
>     -done
>     -
>     -# Physical network:
>     -# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located, e.g. "vif_to_hv 12" yields 2.
>     -vif_to_hv() {
>     -    echo ${1#?}
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its
>     logical router
>     -# port, e.g. "vif_to_lrp 12" yields 1.
>     -vif_to_lrp() {
>     -    echo ${1%?}
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its logical
>     -# switch, e.g. "vif_to_ls 12" yields 1.
>     -vif_to_ls() {
>     -    echo ${1%?}
>     -}
>     -
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -done
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        hv=`vif_to_hv $i$j`
>     -            as hv$hv ovs-vsctl \
>     -                -- add-port br-int vif$i$j \
>     -                -- set Interface vif$i$j \
>     -                    external-ids:iface-id=lp$i$j \
>     -                    options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
>     -                    options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
>     -                    ofport-request=$i$j
>     -    done
>     -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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 12
>     for vif12.
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    in_ls=`vif_to_ls $inport`
>     -    in_lrp=`vif_to_lrp $inport`
>     -    for outport; do
>     -        out_ls=`vif_to_ls $outport`
>     -        if test $in_ls = $out_ls; then
>     -            # Ports on the same logical switch receive exactly
>     the same packet.
>     -            echo $packet
>     -        else
>     -            # Routing decrements TTL and updates source and dest MAC
>     -            # (and checksum).
>     -            out_lrp=`vif_to_lrp $outport`
>     -            echo
>     f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
>     -        fi >> $outport.expected
>     -    done
>     -}
>     -
>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>     -    local
>     request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>     -
>     -    # Expect to receive the broadcast ARP on the other logical
>     switch ports if
>     -    # IP address is not configured to the switch patch port.
>     -    local i=`vif_to_ls $inport`
>     -    local j
>     -    for j in 1 2; do
>     -        if test $i$j != $inport; then
>     -            echo $request >> $i$j$k.expected
>     -        fi
>     -    done
>     -
>     -    # Expect to receive the reply, if any.
>     -    if test X$reply_ha != X; then
>     -        lrp=`vif_to_lrp $inport`
>     -        local
>     reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>     -        echo $reply >> $inport.expected
>     -    fi
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# lp11 send GARP request to announce ownership of 192.168.1.100.
>     -
>     -sha=f00000000011
>     -spa=`ip_to_hex 192 168 1 100`
>     -tpa=$spa
>     -test_arp 11 $sha $spa $tpa
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>     ip="192.168.1.100" | wc -l` -gt 0])
>     -ovn-nbctl --wait=hv sync
>     -
>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>     to lp11.
>     -
>     -smac=f00000000021
>     -dmac=00000000ff02
>     -sip=`ip_to_hex 192 168 2 11`
>     -dip=`ip_to_hex 192 168 1 100`
>     -test_ip 21 $smac $dmac $sip $dip 11
>     -
>     -# lp12 send GARP request to announce ownership of 192.168.1.100.
>     -
>     -sha=f00000000012
>     -test_arp 12 $sha $spa $tpa
>     -OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" |
>     grep f0:00:00:00:00:12])
>     -ovn-nbctl --wait=hv sync
>     -# give to the hv the time to send queued ip packets
>     -sleep 1
>     -
>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>     to lp12.
>     -
>     -test_ip 21 $smac $dmac $sip $dip 12
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2; do
>     -    for j in 1 2; do
>     -        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
>     -                          [$i$j.expected])
>     -    done
>     -done
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1], [hv2])
>     -
>     -AT_CLEANUP
>     -
>     -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
>     -AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Create hypervisors hv[123].
>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>     -# Add all of the vifs to a single logical switch lsw0.
>     -# Turn off port security on vifs vif[123]1
>     -# Turn on l2 port security on vifs vif[123]2
>     -# Turn of l2 and l3 port security on vifs vif[123]3
>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2 3; do
>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>     vif$i$j external-ids:iface-id=lp$i$j
>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>     -        if test $j = 1; then
>     -            ovn-nbctl lsp-set-addresses lp$i$j
>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>     -        elif test $j = 2; then
>     -            ovn-nbctl lsp-set-addresses lp$i$j
>     "f0:00:00:00:00:$i$j 192.168.0.$i$j"
>     -            ovn-nbctl lsp-set-port-security lp$i$j
>     f0:00:00:00:00:$i$j
>     -        else
>     -            extra_addr="f0:00:00:00:0$i:$i$j
>     fe80::ea2a:eaff:fe28:$i$j"
>     -            ovn-nbctl lsp-set-addresses lp$i$j
>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>     -            ovn-nbctl lsp-set-port-security lp$i$j
>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>     -        fi
>     -    done
>     -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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv${1%?}
>     -}
>     -
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -
>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -#
>     -# This shell function causes an ip packet to be received on INPORT.
>     -# The packet's content has Ethernet destination DST and source SRC
>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>     digits).
>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>     should
>     -# be received.  INPORT and the OUTPORTs are specified as logical
>     switch
>     -# port numbers, e.g. 11 for vif11.
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 reply_ha=$7
>     -    local
>     request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -    hv=`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
>     -    if test $drop != 1; then
>     -        if test X$reply_ha = X; then
>     -            # Expect to receive the broadcast ARP on the other
>     logical switch ports
>     -            # if no reply is expected.
>     -            local i j
>     -            for i in 1 2 3; do
>     -                for j in 1 2 3; do
>     -                    if test $i$j != $inport; then
>     -                        echo $request >> $i$j.expected
>     -                    fi
>     -                done
>     -            done
>     -        else
>     -            # Expect to receive the reply, if any.
>     -            local
>     reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>     -            echo $reply >> $inport.expected
>     -        fi
>     -    fi
>     -}
>     -
>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -# This function is similar to test_ip() except that it sends
>     -# ipv6 packet
>     -test_ipv6() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000
>     -    shift; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE
>     OUTPORT...
>     -# This function is similar to test_ipv6() except it specifies the
>     ICMPv6 type
>     -# of the test packet
>     -test_icmpv6() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     icmp_type=$6
>     -    local
>     packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000
>     -    shift; shift; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# no port security
>     -sip=`ip_to_hex 192 168 0 12`
>     -tip=`ip_to_hex 192 168 0 13`
>     -# the arp packet should be allowed even if lp[123]1 is
>     -# not configured with mac f00000000023 and ip 192.168.0.12
>     -for i in 1 2 3; do
>     -    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 f00000000013
>     -    for j in 1 2 3; do
>     -        if test $i != $j; then
>     -            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip
>     $tip ${j}1
>     -        fi
>     -    done
>     -done
>     -
>     -# l2 port security
>     -sip=`ip_to_hex 192 168 0 12`
>     -tip=`ip_to_hex 192 168 0 13`
>     -
>     -# arp packet should be allowed since lp22 is configured with
>     -# mac f00000000022
>     -test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
>     -
>     -# arp packet should not be allowed since lp32 is not configured with
>     -# mac f00000000021
>     -test_arp 32 f00000000021 f00000000021 $sip $tip 1
>     -
>     -# arp packet with sha set to f00000000021 should not be allowed
>     -# for lp12
>     -test_arp 12 f00000000012 f00000000021 $sip $tip 1
>     -
>     -# ip packets should be allowed and received since lp[123]2 do not
>     -# have l3 port security
>     -sip=`ip_to_hex 192 168 0 55`
>     -tip=`ip_to_hex 192 168 0 66`
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        if test $i != $j; then
>     -            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip
>     $tip ${j}2
>     -        fi
>     -    done
>     -done
>     -
>     -# ipv6 packets should be received by lp[123]2
>     -# lp[123]1 can send ipv6 traffic as there is no port security
>     -sip=fe800000000000000000000000000000
>     -tip=ff020000000000000000000000000000
>     -
>     -for i in 1 2 3; do
>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip ${i}2
>     -done
>     -
>     -
>     -# l2 and l3 port security
>     -sip=`ip_to_hex 192 168 0 13`
>     -tip=`ip_to_hex 192 168 0 22`
>     -# arp packet should be allowed since lp13 is configured with
>     -# f00000000013 and 192.168.0.13
>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>     -
>     -# the arp packet should be dropped because lp23 is not configured
>     -# with mac f00000000022
>     -sip=`ip_to_hex 192 168 0 13`
>     -tip=`ip_to_hex 192 168 0 22`
>     -test_arp 23 f00000000022 f00000000022 $sip $tip 1
>     -
>     -# the arp packet should be dropped because lp33 is not configured
>     -# with ip 192.168.0.55
>     -spa=`ip_to_hex 192 168 0 55`
>     -tpa=`ip_to_hex 192 168 0 22`
>     -test_arp 33 f00000000031 f00000000031 $spa $tpa 1
>     -
>     -# ip packets should not be received by lp[123]3 since
>     -# l3 port security is enabled
>     -sip=`ip_to_hex 192 168 0 55`
>     -tip=`ip_to_hex 192 168 0 66`
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
>     -    done
>     -done
>     -
>     -# ipv6 packets should be dropped for lp[123]3 since
>     -# it is configured with only ipv4 address
>     -sip=fe800000000000000000000000000000
>     -tip=ff020000000000000000000000000000
>     -
>     -for i in 1 2 3; do
>     -    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
>     -done
>     -
>     -# ipv6 packets should not be received by lp[123]3 with mac
>     f000000000$[123]3
>     -# lp[123]1 can send ipv6 traffic as there is no port security
>     -for i in 1 2 3; do
>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
>     -done
>     -
>     -# lp13 has extra port security with mac f0000000113 and ipv6 addr
>     -# fe80::ea2a:eaff:fe28:0012
>     -
>     -# ipv4 packet should be dropped for lp13 with mac f0000000113
>     -sip=`ip_to_hex 192 168 0 13`
>     -tip=`ip_to_hex 192 168 0 23`
>     -test_ip 13 f00000000113 f00000000023 $sip $tip
>     -
>     -# ipv6 packet should be received by lp[123]3 with mac
>     f00000000${i}${i}3
>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
>     -# lp11 can send ipv6 traffic as there is no port security
>     -sip=ee800000000000000000000000000000
>     -for i in 1 2 3; do
>     -    tip=fe80000000000000ea2aeafffe2800${i}3
>     -    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
>     -done
>     -
>     -
>     -# ipv6 packet should not be received by lp33 with mac f0000000333
>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
>     -# configured with fe80::ea2a:eaff:fe28:0033
>     -# lp11 can send ipv6 traffic as there is no port security
>     -
>     -sip=ee800000000000000000000000000000
>     -tip=fe80000000000000ea2aeafffe280023
>     -test_ipv6 11 f00000000011 f00000000333 $sip $tip
>     -
>     -# ipv6 packet should be allowed for lp[123]3 with mac
>     f0000000${i}${i}3
>     -# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
>     -# and should be dropped for any other ip6.src
>     -# lp21 can receive ipv6 traffic as there is no port security
>     -
>     -tip=ee800000000000000000000000000000
>     -for i in 1 2 3; do
>     -    sip=fe80000000000000ea2aeafffe2800${i}3
>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
>     -
>     -    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
>     -    sip=00000000000000000000000000000000
>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>     ff020000000000000000000000160000 83 21
>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>     ff020000000000000000000000160000 8f 21
>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>     ff0200000000000000ea2aeafffe2800 87 21
>     -    # Traffic to non-multicast traffic should be dropped
>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
>     -    # Traffic of other ICMPv6 types should be dropped
>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>     ff020000000000000000000000160000 80
>     -
>     -    # should be dropped
>     -    sip=ae80000000000000ea2aeafffe2800aa
>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
>     -done
>     -
>     -# configure lsp13 to send and received IPv4 packets with an
>     address range
>     -ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13
>     192.168.0.13 20.0.0.4/24 <http://20.0.0.4/24> 10.0.0.0/24
>     <http://10.0.0.0/24>"
>     -
>     -sleep 2
>     -
>     -sip=`ip_to_hex 10 0 0 13`
>     -tip=`ip_to_hex 192 168 0 22`
>     -# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>     -
>     -sip=`ip_to_hex 10 0 0 14`
>     -tip=`ip_to_hex 192 168 0 23`
>     -# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
>     -# with dst ip 192.168.0.23 should be allowed
>     -test_ip 13 f00000000013 f00000000023 $sip $tip 23
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 10 0 0 15`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 10.0.0.15 should be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 20 0 0 4`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 20.0.0.4 should be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 20 0 0 5`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 20.0.0.5 should not be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 20 0 0 255`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 20.0.0.255 should be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 192 168 0 255`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 192.168.0.255 should not be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>     -
>     -sip=`ip_to_hex 192 168 0 33`
>     -tip=`ip_to_hex 224 0 0 4`
>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>     -# with dst ip 224.0.0.4  should be received by lsp13
>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>     -
>     -#dump information including flow counters
>     -ovn-nbctl show
>     -ovn-sbctl dump-flows -- list multicast_group
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -echo "------ hv3 dump ------"
>     -as hv3 ovs-vsctl show
>     -as hv3 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>     -    done
>     -done
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other as peers
>     in 20.0.0.0/24 <http://20.0.0.0/24>
>     -# network. R1 has a switchs ls1 (191.168.1.0/24
>     <http://191.168.1.0/24>) connected to it.
>     -# R2 has ls2 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>     -
>     -ls1_lp1_mac="f0:00:00:01:02:03"
>     -rp_ls1_mac="00:00:00:01:02:03"
>     -rp_ls2_mac="00:00:00:01:02:04"
>     -ls2_lp1_mac="f0:00:00:01:02:04"
>     -
>     -ls1_lp1_ip="192.168.1.2"
>     -ls2_lp1_ip="172.16.1.2"
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lr-add R2
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -
>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>     type=router \
>     -  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
>     -
>     -# Connect ls2 to R2
>     -ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>     type=router \
>     -  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
>     -
>     -# Connect R1 to R2
>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>     <http://20.0.0.1/24> peer=R2_R1
>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>     <http://20.0.0.2/24> peer=R1_R2
>     -
>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.2
>     -ovn-nbctl lr-route-add R2 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.1
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
>     -
>     -# Create logical port ls2-lp1 in ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Packet to send.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>     eth.dst==$rp_ls1_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>     ip4.dst==$ls2_lp1_ip &&
>     -        udp && udp.src==53 && udp.dst==4369"
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -
>     -# Packet to Expect
>     -# The TTL should be decremented by 2.
>     -packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
>     -        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip &&
>     ip4.dst==$ls2_lp1_ip &&
>     -        udp && udp.src==53 && udp.dst==4369"
>     -echo $packet | ovstest test-ovn expr-to-packets > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [1
>     -])
>     -
>     -# Disable the ls2-lp1 port.
>     -ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
>     -
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [0
>     -])
>     -
>     -# Generate the packet destined for ls2-lp1 and it should not be
>     delivered.
>     -# Packet to send.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>     eth.dst==$rp_ls1_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>     ip4.dst==$ls2_lp1_ip &&
>     -        udp && udp.src==53 && udp.dst==4369"
>     -
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -# The 2nd packet sent shound not be received.
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -
>     -AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
>     -AT_KEYWORDS([router-admin-state])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR - R1 has switch ls1 with two subnets attached to it
>     (191.168.1.0/24 <http://191.168.1.0/24>
>     -# and 172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24> 172.16.1.1/24
>     -ovn-nbctl <http://172.16.1.1/24-ovn-nbctl> lsp-add ls1 rp-ls1 --
>     set Logical_Switch_Port rp-ls1 type=router \
>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     -          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03
>     192.168.1.2"
>     -
>     -# Create logical port ls1-lp2 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>     -          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create one hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int vif1 -- \
>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif2 -- \
>     -    set interface vif2 external-ids:iface-id=ls1-lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Send ip packets between the two ports.
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Packet to send.
>     -src_mac="f00000010203"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>     -
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -
>     -#Disable router R1
>     -ovn-nbctl set Logical_Router R1 enabled=false
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>     -
>     -# Packet to Expect
>     -expect_src_mac="000000010203"
>     -expect_dst_mac="f00000010204"
>     -echo
>     "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -
>     -AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
>     -AT_KEYWORDS([router-admin-state])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>     <http://191.168.1.0/24>) connected to it,
>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>     type=router \
>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>     -
>     -# Connect ls2 to R1
>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>     type=router \
>     -          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port ls2-lp1 in ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create one hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int vif1 -- \
>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif2 -- \
>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Send ip packets between the two ports.
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Packet to send.
>     -src_mac="f00000010203"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>     -
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -#Disable router R1
>     -ovn-nbctl set Logical_Router R1 enabled=false
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Allow some time for the disabling of logical router R1 to
>     propagate.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>     -
>     -# Packet to Expect
>     -expect_src_mac="000000010204"
>     -expect_dst_mac="f00000010204"
>     -echo
>     "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static routes])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other as peers
>     in 20.0.0.0/24 <http://20.0.0.0/24>
>     -# network. R1 has switchess foo (192.168.1.0/24
>     <http://192.168.1.0/24>)
>     -# connected to it.
>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and bob
>     (172.16.2.0/24 <http://172.16.2.0/24>) connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lr-add R2
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add bob
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -          type=router options:router-port=alice
>     addresses=\"00:00:00:01:02:04\"
>     -
>     -# Connect bob to R2
>     -ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
>     <http://172.16.2.1/24>
>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob
>     type=router \
>     -          options:router-port=bob addresses=\"00:00:00:01:02:05\"
>     -
>     -# Connect R1 to R2
>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>     <http://20.0.0.1/24> peer=R2_R1
>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>     <http://20.0.0.2/24> peer=R1_R2
>     -
>     -#install static routes
>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -ovn-nbctl lr-route-add R2 172.16.2.0/24 <http://172.16.2.0/24>
>     20.0.0.2 R1_R2
>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>     20.0.0.1
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create logical port bob1 in bob
>     -ovn-nbctl lsp-add bob bob1 \
>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="f00000010203"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -# Send ip packets between foo1 and bob1
>     -src_mac="f00000010203"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 2 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump ----------"
>     -as hv2 ovs-ofctl dump-flows br-int
>     -
>     -# Packet to Expect at bob1
>     -src_mac="000000010205"
>     -dst_mac="f00000010205"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 2 2`
>     -echo
>     "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Packet to Expect at alice1
>     -src_mac="000000010204"
>     -dst_mac="f00000010204"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -echo
>     "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send gratuitous arp on localnet])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0
>     -
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>     snoopvif options:tx_pcap=hv/snoopvif-tx.pcap
>     options:rxq_pcap=hv/snoopvif-rx.pcap])
>     -
>     -# Create a vif.
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>     "f0:00:00:00:00:01 192.168.1.2"])
>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>     "f0:00:00:00:00:01"])
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>     -
>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>     localvif1 external_ids:iface-id=localvif1])
>     -
>     -# Wait for packet to be received.
>     -echo
>     "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102"
>     > expected
>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>     -
>     -# Check GARP packet when restart openflow connection.
>     -as hv
>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>     -
>     -OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect"
>     hv/ovn-controller.log])
>     -
>     -as hv
>     -start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>     -vofproto_dpif -vunixctl
>     -
>     -# Wait for packet to be received.
>     -echo
>     "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102"
>     > expected
>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>     -
>     -# Delete the localnet ports.
>     -AT_CHECK([ovs-vsctl del-port localvif1])
>     -AT_CHECK([ovn-nbctl lsp-del ln_port])
>     -
>     -OVN_CLEANUP([hv])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>     LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>     -# connected to it. R2 has alice (172.16.1.0/24
>     <http://172.16.1.0/24>) and R3 has bob (10.32.1.0/24
>     <http://10.32.1.0/24>)
>     -# connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lr-add R2
>     -ovn-nbctl lr-add R3
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add bob
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect bob to R3
>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
>     <http://10.32.1.1/24>
>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>     -    type=router options:router-port=bob
>     addresses=\"00:00:03:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Connect R3 to join
>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>     <http://20.0.0.3/24>
>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>     -    type=router options:router-port=R3_join
>     addresses='"00:00:04:01:02:05"'
>     -
>     -#install static routes
>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -ovn-nbctl lr-route-add R1 10.32.1.0/24 <http://10.32.1.0/24> 20.0.0.3
>     -
>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>     20.0.0.1
>     -ovn-nbctl lr-route-add R2 10.32.1.0/24 <http://10.32.1.0/24> 20.0.0.3
>     -
>     -ovn-nbctl lr-route-add R3 192.168.1.0/24 <http://192.168.1.0/24>
>     20.0.0.1
>     -ovn-nbctl lr-route-add R3 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create logical port bob1 in bob
>     -ovn-nbctl lsp-add bob bob1 \
>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>     -
>     -# Send ip packets between foo1 and bob1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 10 32 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -echo "----------------------------"
>     -
>     -# Packet to Expect at bob1
>     -src_mac="000003010203"
>     -dst_mac="f00000010205"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 10 32 1 2`
>     -echo
>     "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Packet to Expect at alice1
>     -src_mac="000002010203"
>     -dst_mac="f00000010204"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -echo
>     "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>     10.0.0.6 20.0.0.4"
>     -
>     -ovn-nbctl ls-add ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03
>     30.0.0.6 40.0.0.4"
>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>     -
>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>     <http://10.0.0.0/24> \
>     -options="\"server_id\"=\"10.0.0.1\"
>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>     -
>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
>     -
>     -d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24
>     <http://30.0.0.0/24> \
>     -options="\"server_id\"=\"30.0.0.1\"
>     \"server_mac\"=\"ff:10:00:00:00:02\" \
>     -\"lease_time\"=\"3600\"")"
>     -
>     -ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
>     -
>     -net_add n1
>     -sim_add hv1
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>     -    ofport-request=3
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>     -    ofport-request=4
>     -
>     -OVN_POPULATE_ARP
>     -
>     -sleep 2
>     -
>     -as hv1 ovs-vsctl show
>     -
>     -# This shell function sends a DHCP request packet
>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
>     -test_dhcp() {
>     -    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5
>     request_ip=$6 use_ip=$7
>     -    shift; shift; shift; shift; shift; shift; shift;
>     -    if test $use_ip != 0; then
>     -        src_ip=$1
>     -        dst_ip=$2
>     -        shift; shift;
>     -    else
>     -        src_ip=`ip_to_hex 0 0 0 0`
>     -        dst_ip=`ip_to_hex 255 255 255 255`
>     -    fi
>     -    if test $request_ip != 0; then
>     -        ip_len=0120
>     -        udp_len=010b
>     -    else
>     -        ip_len=011a
>     -        udp_len=0106
>     -    fi
>     -    local
>     request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip}
>     -    # udp header and dhcp header
>     -    request=${request}00440043${udp_len}0000
>     -
>     request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac}
>     -    # client hardware padding
>     -    request=${request}00000000000000000000
>     -    # server hostname
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -    # boot file name
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -    # dhcp magic cookie
>     -    request=${request}63825363
>     -    # dhcp message type
>     -    request=${request}3501${dhcp_type}
>     -    # dhcp unknown option
>     -    request=${request}d70701020304050607
>     -    # dhcp pad option
>     -    request=${request}00
>     -    if test $request_ip != 0; then
>     -        # dhcp requested ip
>     -        request=${request}3204${request_ip}
>     -    fi
>     -    # dhcp end option
>     -    request=${request}ff
>     -
>     -    for port in $inport "$@"; do
>     -        : >> $port.expected
>     -    done
>     -    if test $offer_ip != 0; then
>     -        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3
>     expected_dhcp_opts=$4
>     -        # total IP length will be the IP length of the request packet
>     -        # (which is 272 in our case) + 8 (padding bytes) +
>     (expected_dhcp_opts / 2)
>     -        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>     -        udp_len=`expr $ip_len - 20`
>     -        ip_len=$(printf "%x" $ip_len)
>     -        udp_len=$(printf "%x" $udp_len)
>     -        # $ip_len var will be in 3 digits i.e 134. So adding a
>     '0' before $ip_len
>     -        local
>     reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
>     -        # udp header and dhcp header.
>     -        # $udp_len var will be in 3 digits. So adding a '0'
>     before $udp_len
>     -
>     reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
>     -        # your ip address; 0 for NAK
>     -        if test $dhcp_reply_type = 06; then
>     -            reply=${reply}00000000
>     -        else
>     -            reply=${reply}${offer_ip}
>     -        fi
>     -        # next server ip address, relay agent ip address, client
>     mac address
>     -        reply=${reply}0000000000000000${src_mac}
>     -        # client hardware padding
>     -        reply=${reply}00000000000000000000
>     -        # server hostname
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -        # boot file name
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -        # dhcp magic cookie
>     -        reply=${reply}63825363
>     -
>     reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
>     -        echo $reply >> $inport.expected
>     -    else
>     -        for outport; do
>     -            echo $request >> $outport.expected
>     -        done
>     -    fi
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Send DHCPDISCOVER.
>     -offer_ip=`ip_to_hex 10 0 0 4`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -request_ip=0
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0
>     ff1000000001 $server_ip 02 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 1.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap > 1.packets
>     -cat 1.expected | cut -c -48 > expout
>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 1.expected | cut -c 53- > expout
>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>     -
>     -# ovs-ofctl also resumes the packets and this causes other ports
>     to receive
>     -# the DHCP request packet. So reset the pcap files so that its
>     easier to test.
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the
>     offered IP
>     -# address in the Requested IP Address option.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -request_ip=$offer_ip
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>     ff1000000001 $server_ip 05 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a
>     mismatched IP in
>     -# the Requested IP Address option, expect a DHCPNAK.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -request_ip=`ip_to_hex 10 0 0 7`
>     -expected_dhcp_opts=""
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>     ff1000000001 $server_ip 06 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 3.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by
>     ovn-controller
>     -# but should be resumed without the reply.
>     -# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet
>     twice,
>     -# one from ovn-controller and the other from "ovs-ofctl resume."
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -offer_ip=0
>     -request_ip=0
>     -test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
>     -
>     -# NXT_RESUMEs should be 4.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -# vif1-tx.pcap should have received the DHCPv4 (invalid) request
>     packet
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4
>     options defined.
>     -# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet
>     once.
>     -
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
>     -
>     -# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not
>     defined for
>     -# this lport.
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
>     -
>     -# NXT_RESUMEs should be 4.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
>     -#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
>     -
>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>     set to 10.0.0.6
>     -# and ip4.dst set to 10.0.0.1.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=$offer_ip
>     -request_ip=0
>     -src_ip=$offer_ip
>     -dst_ip=$server_ip
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 5.
>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>     set to 10.0.0.6
>     -# and ip4.dst set to 255.255.255.255.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=$offer_ip
>     -request_ip=0
>     -src_ip=$offer_ip
>     -dst_ip=`ip_to_hex 255 255 255 255`
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 6.
>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with a
>     mismatched IP in the
>     -# ciaddr, expect a DHCPNAK.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=`ip_to_hex 10 0 0 7`
>     -request_ip=0
>     -src_ip=$offer_ip
>     -dst_ip=`ip_to_hex 255 255 255 255`
>     -expected_dhcp_opts=""
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 7.
>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST in the RENEWING/REBINDING state without a
>     specifyied ciaddr,
>     -# expect a DHCPNAK.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -request_ip=0
>     -src_ip=$offer_ip
>     -dst_ip=`ip_to_hex 255 255 255 255`
>     -expected_dhcp_opts=""
>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 8.
>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set
>     to 10.0.0.4.
>     -# The packet should not be received by ovn-controller.
>     -ciaddr=`ip_to_hex 0 0 0 0`
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 4`
>     -test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
>     -
>     -# NXT_RESUMEs should be 8.
>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -# vif1-tx.pcap should have received the DHCPv4 request packet
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>     10.0.0.4 ae70::4"
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp3 \
>     --- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>     -
>     -d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>     -
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
>     -
>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>     -options="\"dhcpv6_stateless\"=\"true\"
>     \"server_id\"=\"00:00:00:10:00:01\"")"
>     -
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
>     -
>     -ovn-nbctl ls-add ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 be70::3"
>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 be70::4"
>     -
>     -net_add n1
>     -sim_add hv1
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>     -    ofport-request=3
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>     -    ofport-request=4
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif5 -- \
>     -    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
>     -    options:tx_pcap=hv1/vif5-tx.pcap \
>     -    options:rxq_pcap=hv1/vif5-rx.pcap \
>     -    ofport-request=5
>     -
>     -OVN_POPULATE_ARP
>     -
>     -sleep 2
>     -
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -# This shell function sends a DHCPv6 request packet
>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>     OUTPORT...
>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>     DHCPv6
>     -# packet should be received twice (one from ovn-controller and
>     the other
>     -# from the "ovs-ofctl monitor br-int resume"
>     -test_dhcpv6() {
>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>     -    if test $msg_code != 0b; then
>     -        req_len=2a
>     -    else
>     -        req_len=1a
>     -    fi
>     -    local
>     request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
>     -    # dst ip ff02::1:2
>     -    request=${request}ff020000000000000000000000010002
>     -    # udp header and dhcpv6 header
>     - request=${request}0222022300${req_len}ffff${msg_code}010203
>     -    # Client identifier
>     -    request=${request}0001000a00030001${src_mac}
>     -    # Add IA-NA (Identity Association for Non Temporary Address)
>     if msg_code
>     -    # is not 11 (information request packet)
>     -    if test $msg_code != 0b; then
>     -        request=${request}0003000c0102030400000e1000001518
>     -    fi
>     -    shift; shift; shift; shift; shift;
>     -    if test $offer_ip != 0; then
>     -        local server_mac=000000100001
>     -        local server_lla=fe80000000000000020000fffe100001
>     -        local reply_code=07
>     -        if test $msg_code = 01; then
>     -            reply_code=02
>     -        fi
>     -        local msg_len=54
>     -        if test $offer_ip = 1; then
>     -            msg_len=28
>     -        fi
>     -        local
>     reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla}
>     -        # udp header and dhcpv6 header
>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>     -        # Client identifier
>     -        reply=${reply}0001000a00030001${src_mac}
>     -        # IA-NA
>     -        if test $offer_ip != 1; then
>     -
>     reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
>     -        fi
>     -        # Server identifier
>     -        reply=${reply}0002000a00030001${server_mac}
>     -        echo $reply | trim_zeros >> $inport.expected
>     -    else
>     -        for outport; do
>     -            echo $request | trim_zeros >> $outport.expected
>     -        done
>     -    fi
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -src_mac=f00000000001
>     -src_lla=fe80000000000000f20000fffe000001
>     -offer_ip=ae700000000000000000000000000004
>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>     -
>     -# NXT_RESUMEs should be 1.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>     -# cat 1.expected | trim_zeros > expout
>     -cat 1.expected | cut -c -120 > expout
>     -AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
>     -# Skipping the UDP checksum
>     -cat 1.expected | cut -c 125- > expout
>     -AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
>     -
>     -rm  1.expected
>     -
>     -# Send invalid packet on ls1-lp2. ovn-controller should resume
>     the packet
>     -# without any modifications and the packet should be received by
>     ls1-lp1.
>     -# ls1-lp1 will receive the packet twice, one from the
>     ovn-controller after the
>     -# resume and the other from ovs-ofctl monitor resume.
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -
>     -src_mac=f00000000002
>     -src_lla=fe80000000000000f20000fffe000002
>     -offer_ip=ae700000000000000000000000000005
>     -# Set invalid msg_type
>     -
>     -test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
>     -
>     -# NXT_RESUMEs should be 2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -# vif2-tx.pcap should not have received the DHCPv6 reply packet
>     -rm 2.packets
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap | trim_zeros > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [])
>     -
>     -# vif1-tx.pcap should have received the DHCPv6 (invalid) request
>     packet
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>     -cat 1.expected > expout
>     -AT_CHECK([cat 1.packets], [0], [expout])
>     -
>     -# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on
>     this port.
>     -# There should be no DHCPv6 reply from ovn-controller and the
>     request packet
>     -# should be received by ls2-lp2.
>     -
>     -src_mac=f00000000003
>     -src_lla=fe80000000000000f20000fffe000003
>     -test_dhcpv6 3 $src_mac $src_lla 01 0 4
>     -
>     -# NXT_RESUMEs should be 2 only.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -# vif3-tx.pcap should not have received the DHCPv6 reply packet
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif3-tx.pcap | trim_zeros > 3.packets
>     -AT_CHECK([cat 3.packets], [0], [])
>     -
>     -# vif4-tx.pcap should have received the DHCPv6 request packet
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif4-tx.pcap | trim_zeros > 4.packets
>     -cat 4.expected > expout
>     -AT_CHECK([cat 4.packets], [0], [expout])
>     -
>     -# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless
>     mode for this port.
>     -# The DHCPv6 reply shouldn't contain offer_ip.
>     -src_mac=f00000000022
>     -src_lla=fe80000000000000f20000fffe000022
>     -reset_pcap_file hv1-vif5 hv1/vif5
>     -test_dhcpv6 5 $src_mac $src_lla 01 1 5
>     -
>     -# NXT_RESUMEs should be 3.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif5-tx.pcap | trim_zeros > 5.packets
>     -# Skipping the UDP checksum
>     -cat 5.expected | cut -c 1-120,125- > expout
>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>     -
>     -# Send DHCPv6 information request (code 11) on ls1-lp3. The
>     DHCPv6 reply
>     -# shouldn't contain offer_ip
>     -src_mac=f00000000022
>     -src_lla=fe80000000000000f20000fffe000022
>     -reset_pcap_file hv1-vif5 hv1/vif5
>     -rm -f 5.expected
>     -test_dhcpv6 5 $src_mac $src_lla 0b 1 5
>     -
>     -# NXT_RESUMEs should be 4.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif5-tx.pcap |
>     -trim_zeros > 5.packets
>     -# Skipping the UDP checksum
>     -cat 5.expected | cut -c 1-120,125- > expout
>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>     -# connected to it. R2 has alice (172.16.1.0/24
>     <http://172.16.1.0/24>) connected to it.
>     -# R2 is a gateway router.
>     -
>     -
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -# 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
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -
>     -#install static routes
>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>     -ip_prefix=172.16.1.0/24 <http://172.16.1.0/24> nexthop=20.0.0.2
>     -- add Logical_Router \
>     -R1 static_routes @lrt
>     -
>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>     -- add Logical_Router \
>     -R2 static_routes @lrt
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 2
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -ovn-sbctl list chassis
>     -ovn-sbctl list encap
>     -echo "---------------------"
>     -
>     -# Packet to Expect at alice1
>     -src_mac="000002010203"
>     -dst_mac="f00000010204"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
>     -
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>     -
>     -echo "------ hv1 dump after packet 1 ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump after packet 1 ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -echo "----------------------------"
>     -
>     -echo $expected > expected
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Delete the router and re-create it. Things should work as before.
>     -ovn-nbctl  lr-del R2
>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -
>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>     -- add Logical_Router \
>     -R2 static_routes @lrt
>     -
>     -# Wait for ovn-controller to catch up.
>     -sleep 1
>     -
>     -# Send the packet again.
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -echo "------ hv1 dump after packet 2 ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump after packet 2 ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -echo "----------------------------"
>     -
>     -echo $expected >> expected
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
>     -AT_KEYWORDS([router-icmp-reply])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>     <http://191.168.1.0/24>) connected to it,
>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>     -    type=router options:router-port=ls1
>     addresses=\"00:00:00:01:02:f1\"
>     -
>     -# Connect ls2 to R1
>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>     -    type=router options:router-port=ls2
>     addresses=\"00:00:00:01:02:f2\"
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port ls2-lp1 in ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create one hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int vif1 -- \
>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif2 -- \
>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -for i in 1 2; do
>     -    : > vif$i.expected
>     -done
>     -# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ICMPv4
>     -# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
>     -# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are
>     -# provided, then it should be the ip and icmp checksums of the packet
>     -# responded; otherwise, no reply is expected.
>     -# In the absence of an ip checksum calculation helpers, this relies
>     -# on the caller to provide the checksums for the ip and icmp headers.
>     -# XXX This should be more systematic.
>     -#
>     -# INPORT is an lport number, e.g. 11 for vif11.
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>     -# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
>     -# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
>     -test_ipv4_icmp_request() {
>     -    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5
>     ip_chksum=$6 icmp_chksum=$7
>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>     -    shift; shift; shift; shift; shift; shift; shift
>     -    shift; shift
>     -
>     -    # Use ttl to exercise section 4.2.2.9 of RFC1812
>     -    local ip_ttl=01
>     -    local icmp_id=5fbf
>     -    local icmp_seq=0001
>     -    local icmp_data=$(seq 1 56 | xargs printf "%02x")
>     -    local icmp_type_code_request=0800
>     -    local
>     icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
>     -    local
>     packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload}
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    if test X$exp_icmp_chksum != X; then
>     -        # Expect to receive the reply, if any. In same port where
>     packet was sent.
>     -        # Note: src and dst fields are expected to be reversed.
>     -        local icmp_type_code_response=0000
>     -        local reply_icmp_ttl=fe
>     -        local
>     reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
>     -        local
>     reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
>     -        echo $reply >> vif$inport.expected
>     -    fi
>     -}
>     -
>     -# Send ping packet to router's ip addresses, from each of the 2
>     logical ports.
>     -rtr_l1_ip=$(ip_to_hex 192 168 1 1)
>     -rtr_l2_ip=$(ip_to_hex 172 16 1 1)
>     -l1_ip=$(ip_to_hex 192 168 1 2)
>     -l2_ip=$(ip_to_hex 172 16 1 2)
>     -
>     -# Ping router ip address that is on same subnet as the logical port
>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>     $rtr_l1_ip 0000 8510 02ff 8d10
>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>     $rtr_l2_ip 0000 8510 02ff 8d10
>     -
>     -# Ping router ip address that is on the other side of the logical
>     ports
>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>     $rtr_l2_ip 0000 8510 02ff 8d10
>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>     $rtr_l1_ip 0000 8510 02ff 8d10
>     -
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list logical_flow
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for inport in 1 2; do
>     -    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap],
>     [vif$inport.expected])
>     -done
>     -
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS,
>     1 LR])
>     -AT_KEYWORDS([policy-based-routing])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>     <http://191.168.1.0/24>) connected to it,
>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -ovn-nbctl ls-add ls3
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>     -    type=router options:router-port=ls1
>     addresses=\"00:00:00:01:02:f1\"
>     -
>     -# Connect ls2 to R1
>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>     -    type=router options:router-port=ls2
>     addresses=\"00:00:00:01:02:f2\"
>     -
>     -# Connect ls3 to R1
>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
>     <http://20.20.1.1/24>
>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>     -    type=router options:router-port=ls3
>     addresses=\"00:00:00:01:02:f3\"
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port ls2-lp1 in ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>     -
>     -# Create logical port ls3-lp1 in ls3
>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
>     -
>     -# Create one hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add pbr-hv
>     -as pbr-hv
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -ovs-vsctl -- add-port br-int vif1 -- \
>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif2 -- \
>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif3 -- \
>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>     -    ofport-request=1
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ls1_ro_mac=00:00:00:01:02:f1
>     -ls1_ro_ip=192.168.1.1
>     -
>     -ls2_ro_mac=00:00:00:01:02:f2
>     -ls2_ro_ip=172.16.1.1
>     -
>     -ls3_ro_mac=00:00:00:01:02:f3
>     -
>     -ls1_p1_mac=00:00:00:01:02:03
>     -ls1_p1_ip=192.168.1.2
>     -
>     -ls2_p1_mac=00:00:00:01:02:04
>     -ls2_p1_ip=172.16.1.2
>     -
>     -ls3_p1_mac=00:00:00:01:02:05
>     -
>     -# Create a drop policy
>     -ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24
>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>     <http://172.16.1.0/24>" drop
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>     "192.168.1.0" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>     ip4.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Check if packet hit the drop policy
>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24> actions=drop" | \
>     -    grep "priority=10" | \
>     -    grep "n_packets=1" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Expected to drop the packet.
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     pbr-hv/vif2-tx.pcap > vif2.packets
>     -rcvd_packet=`cat vif2.packets`
>     -AT_FAIL_IF([rcvd_packet = ""])
>     -
>     -# Override drop policy with allow
>     -ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24
>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>     <http://172.16.1.0/24>" allow
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>     "192.168.1.0" | wc -l], [0], [dnl
>     -2
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>     ip4.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Check if packet hit the allow policy
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>     -    grep "192.168.1.0" | \
>     -    grep "priority=20" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>     ip4.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>     -
>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>     -
>     -# Override allow policy with reroute
>     -ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24
>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>     <http://172.16.1.0/24>" reroute 20.20.1.2
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>     -    grep "192.168.1.0" | \
>     -    grep "priority=30" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>     ip4.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -echo "southbound flows"
>     -
>     -ovn-sbctl dump-flows | grep lr_in_policy
>     -echo "ovs flows"
>     -ovs-ofctl dump-flows br-int
>     -# Check if packet hit the allow policy
>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24>" | \
>     -    grep "priority=30" | \
>     -    grep "n_packets=1" | wc -l], [0], [dnl
>     -1
>     -])
>     -echo "packet hit reroute policy"
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>     ip4.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>     -
>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>     -
>     -OVN_CLEANUP([pbr-hv])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1
>     lport/LS, 1 LR])
>     -AT_KEYWORDS([policy-based-routing])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>     <http://191.168.1.0/24>) connected to it,
>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it.
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -ovn-nbctl ls-add ls3
>     -
>     -# Connect ls1 to R1
>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>     -    type=router options:router-port=ls1
>     addresses=\"00:00:00:01:02:f1\"
>     -
>     -# Connect ls2 to R1
>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>     -    type=router options:router-port=ls2
>     addresses=\"00:00:00:01:02:f2\"
>     -
>     -# Connect ls3 to R1
>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>     -    type=router options:router-port=ls3
>     addresses=\"00:00:00:01:02:f3\"
>     -
>     -# Create logical port ls1-lp1 in ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
>     -
>     -# Create logical port ls2-lp1 in ls2
>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
>     -
>     -# Create logical port ls3-lp1 in ls3
>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
>     -
>     -# Create one hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add pbr-hv
>     -as pbr-hv
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -ovs-vsctl -- add-port br-int vif1 -- \
>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif2 -- \
>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int vif3 -- \
>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>     -    ofport-request=1
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ls1_ro_mac=00:00:00:01:02:f1
>     -ls1_ro_ip=2001::1
>     -
>     -ls2_ro_mac=00:00:00:01:02:f2
>     -ls2_ro_ip=2002::1
>     -
>     -ls3_ro_mac=00:00:00:01:02:f3
>     -
>     -ls1_p1_mac=00:00:00:01:02:03
>     -ls1_p1_ip=2001::2
>     -
>     -ls2_p1_mac=00:00:00:01:02:04
>     -ls2_p1_ip=2002::2
>     -
>     -ls3_p1_mac=00:00:00:01:02:05
>     -
>     -# Create a drop policy
>     -ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 &&
>     ip6.dst==2002::/64" drop
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>     | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>     ip6.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Check if packet hit the drop policy
>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
>     -    grep "priority=10" | \
>     -    grep "n_packets=1" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Expected to drop the packet.
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     pbr-hv/vif2-tx.pcap > vif2.packets
>     -rcvd_packet=`cat vif2.packets`
>     -AT_FAIL_IF([rcvd_packet = ""])
>     -
>     -# Override drop policy with allow
>     -ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 &&
>     ip6.dst==2002::/64" allow
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>     | wc -l], [0], [dnl
>     -2
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>     ip6.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Check if packet hit the allow policy
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>     -    grep "2001" | \
>     -    grep "priority=20" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>     ip6.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>     -
>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>     -
>     -# Override allow policy with reroute
>     -ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 &&
>     ip6.dst==2002::/64" reroute 2003::2
>     -
>     -# Check logical flow
>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>     -    grep "2001" | \
>     -    grep "priority=30" | wc -l], [0], [dnl
>     -1
>     -])
>     -
>     -# Send packet.
>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>     eth.dst==$ls1_ro_mac &&
>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>     ip6.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -echo "southbound flows"
>     -
>     -ovn-sbctl dump-flows | grep lr_in_policy
>     -echo "ovs flows"
>     -ovs-ofctl dump-flows br-int
>     -# Check if packet hit the allow policy
>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
>     -    grep "priority=30" | \
>     -    grep "n_packets=1" | wc -l], [0], [dnl
>     -1
>     -])
>     -echo "packet hit reroute policy"
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>     ip6.dst==$ls2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>     -
>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>     -
>     -OVN_CLEANUP([pbr-hv])
>     -AT_CLEANUP
>     -
>     -# 1 hypervisor, 1 port
>     -# make sure that the port state is properly set to up and back down
>     -# when created and deleted.
>     -AT_SETUP([ovn -- port state up and down])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl lsp-add ls1 lp1
>     -ovn-nbctl lsp-set-addresses lp1 unknown
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1 ovs-vsctl add-br br-phys
>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>     -
>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>     -
>     -as hv1 ovs-vsctl del-port br-int vif1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -# 1 hypervisor, 1 port
>     -# make sure that the OF rules created to support a datapath are
>     added/cleared
>     -# when logical switch is created and removed.
>     -AT_SETUP([ovn -- datapath rules added/removed])
>     -AT_KEYWORDS([cleanup])
>     -ovn_start
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1 ovs-vsctl add-br br-phys
>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>     -
>     -# This shell function checks if OF rules in br-int have clauses
>     -# related to OVN datapaths. The caller determines if it should find
>     -# a match in the output, or not.
>     -#
>     -# EXPECT_DATAPATH param determines whether flows that refer to
>     -#                 datapath to should be present or not. 0 means
>     -#                 they should not be.
>     -# STAGE_INFO param is a simple string to help identify the stage
>     -#            in the test when this function was invoked.
>     -test_datapath_in_of_rules() {
>     -    local expect_datapath=$1 stage_info=$2
>     -    echo "------ ovn-nbctl show ${stage_info} ------"
>     -    ovn-nbctl show
>     -    echo "------ ovn-sbctl show ${stage_info} ------"
>     -    ovn-sbctl show
>     -    echo "------ OF rules ${stage_info} ------"
>     -    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
>     -    # if there is a datapath mentioned in the output, check for the
>     -    # magic keyword that represents one, based on the exit status of
>     -    # a quiet grep
>     -    if test $expect_datapath != 0; then
>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [0], [ignore-nolog])
>     -    else
>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [1], [ignore-nolog])
>     -    fi
>     -}
>     -
>     -test_datapath_in_of_rules 0 "before ls+port create"
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl lsp-add ls1 lp1
>     -ovn-nbctl lsp-set-addresses lp1 unknown
>     -
>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>     -
>     -test_datapath_in_of_rules 1 "after port is bound"
>     -
>     -as hv1 ovs-vsctl del-port br-int vif1
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>     -
>     -ovn-nbctl lsp-set-addresses lp1
>     -ovn-nbctl lsp-del lp1
>     -ovn-nbctl ls-del ls1
>     -
>     -# wait for earlier changes to take effect
>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>     -
>     -# ensure OF rules are no longer present. There used to be a bug here.
>     -test_datapath_in_of_rules 0 "after lport+ls removal"
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- nd_na ])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -#TODO: since patch port for IPv6 logical router port is not ready
>     not,
>     -#  so we are not going to test vifs on different lswitches cases. Try
>     -#  to update for that once relevant stuff implemented.
>     -
>     -# In this test cases we create 1 lswitch, it has 2 VIF ports attached
>     -# with. NS packet we test, from one VIF for another VIF, will be
>     replied
>     -# by local ovn-controller, but not by target VIF.
>     -
>     -# Create hypervisors and logical switch lsw0.
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>     -ovn-nbctl lsp-add lsw0 lp1
>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3
>     fd81:ce49:a948:0:f816:3eff:fe94:598"
>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98
>     192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
>     -
>     -# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>     external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap
>     options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
>     -ovn-nbctl lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
>     fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae
>     192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>     -
>     -# Add ACL rule for ICMPv6 on lsw0
>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>     icmp6'  allow-related
>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>     icmp6'  allow-related
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv1${1%?}
>     -}
>     -for i in 1 2; do
>     -    : > $i.expected
>     -done
>     -
>     -# Complete Neighbor Solicitation packet and Neighbor
>     Advertisement packet
>     -# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
>     -# vif2 will not receive NS packet, since ovn-controller will
>     reply for it.
>     -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598
>     -na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
>     -echo $na_packet >> 1.expected
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -
>     -for i in 1 2; do
>     -    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
>     -done
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- address sets modification/removal smoke test])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
>     -ovn-nbctl set Address_Set $row name=set1
>     addresses=\"1.1.1.1,1.1.1.2\"
>     -ovn-nbctl destroy Address_Set $row
>     -
>     -sleep 1
>     -
>     -# A bug previously existed in the address set support code
>     -# that caused ovn-controller to crash after an address set
>     -# was updated and then removed.  This test case ensures
>     -# that ovn-controller is at least still running after
>     -# creating, updating, and deleting an address set.
>     -AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ipam])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Add a port to a switch that does not have a subnet set, then
>     set the
>     -# subnet which should result in an address being allocated for
>     the port.
>     -ovn-nbctl --wait=hv set NB_Global .
>     options:mac_prefix="0a:00:00:00:00:00"
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>     subnet=192.168.1.0/24
>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>     get Logical-Switch-Port p0 dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>     -])
>     -
>     -# Add 9 more ports to sw0, addresses should all be unique.
>     -for n in `seq 1 9`; do
>     -    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses
>     "p$n" dynamic
>     -done
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p1
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:04 192.168.1.3"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p2
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:05 192.168.1.4"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p3
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:06 192.168.1.5"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p4
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:07 192.168.1.6"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p5
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:08 192.168.1.7"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p6
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:09 192.168.1.8"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p7
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:0a 192.168.1.9"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p8
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:0b 192.168.1.10"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p9
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:0c 192.168.1.11"
>     -])
>     -
>     -# Trying similar tests with a second switch. MAC addresses should
>     be unique
>     -# across both switches but IP's only need to be unique within the
>     same switch.
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
>     -ovn-nbctl --wait=sb add Logical-Switch sw1 other_config
>     subnet=192.168.1.0/24
>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>     get Logical-Switch-Port p10 dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:0d 192.168.1.2"
>     -])
>     -
>     -for n in `seq 11 19`; do
>     -    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses
>     "p$n" dynamic
>     -done
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p11
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:0e 192.168.1.3"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p12
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:0f 192.168.1.4"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p13
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:10 192.168.1.5"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p14
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:11 192.168.1.6"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p15
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:12 192.168.1.7"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p16
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:13 192.168.1.8"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p17
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:14 192.168.1.9"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p18
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:15 192.168.1.10"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p19
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:16 192.168.1.11"
>     -])
>     -
>     -# Change a port's address to test for multiple ip's for a single
>     address entry
>     -# and addresses set by the user.
>     -ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2
>     192.168.1.12 192.168.1.14"
>     -ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p20
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:18 192.168.1.13"
>     -])
>     -
>     -# Test for logical router port address management.
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
>     -network="192.168.1.1/24 <http://192.168.1.1/24>"
>     mac=\"0a:00:00:a8:01:19\" \
>     --- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
>     --- set Logical_Switch_Port rp-sw0 type=router options:router-port=sw0
>     -ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p21
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:1a 192.168.1.15"
>     -])
>     -
>     -# Test for address reuse after logical port is deleted.
>     -ovn-nbctl lsp-del p0
>     -ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p23
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:03 192.168.1.2"
>     -])
>     -
>     -# Test for multiple addresses to one logical port.
>     -ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
>     -"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
>     -ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p26
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:17 192.168.1.16"
>     -])
>     -
>     -# Test for exhausting subnet address space.
>     -ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config
>     subnet=172.16.1.0/30
>     -ovn-nbctl <http://172.16.1.0/30-ovn-nbctl> --wait=sb lsp-add sw2
>     p27 -- lsp-set-addresses p27 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p27
>     dynamic_addresses], [0],
>     -     ["0a:00:00:10:01:03 172.16.1.2"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p28
>     dynamic_addresses], [0],
>     -     ["0a:00:00:00:00:01"
>     -])
>     -
>     -# Test that address management does not add duplicate MAC for
>     lsp/lrp peers.
>     -ovn-nbctl create Logical_Router name=R2
>     -ovn-nbctl ls-add sw3
>     -ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
>     -"0a:00:00:a8:01:18"
>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
>     -network="192.168.2.1/24 <http://192.168.2.1/24>"
>     mac=\"0a:00:00:a8:01:18\" \
>     --- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
>     --- set Logical_Switch_Port rp-sw3 type=router options:router-port=sw3
>     -ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 dynamic
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p30
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:1d 192.168.1.17"
>     -])
>     -
>     -# Test static MAC address with dynamically allocated IP
>     -ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
>     -"fe:dc:ba:98:76:54 dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>     dynamic_addresses], [0],
>     -     ["fe:dc:ba:98:76:54 192.168.1.18"
>     -])
>     -
>     -# Update the static MAC address with dynamically allocated IP and
>     check
>     -# if the MAC address is updated in
>     'Logical_Switch_Port.dynamic_adddresses'
>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 dynamic"
>     -
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>     dynamic_addresses], [0],
>     -     ["fe:dc:ba:98:76:55 192.168.1.18"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:1e 192.168.1.18"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>     dynamic_addresses], [0],
>     -     ["fe:dc:ba:98:76:56 192.168.1.18"
>     -])
>     -
>     -
>     -# Test the exclude_ips from the IPAM list
>     -ovn-nbctl --wait=sb set logical_switch sw0 \
>     -other_config:exclude_ips="192.168.1.19 192.168.1.21
>     192.168.1.23..192.168.1.50"
>     -
>     -ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
>     -"dynamic"
>     -# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p32
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:1e 192.168.1.20"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
>     -"dynamic"
>     -# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p33
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:1f 192.168.1.22"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
>     -"dynamic"
>     -# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is
>     excluded.
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p34
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:34 192.168.1.51"
>     -])
>     -
>     -# Now clear the exclude_ips list. 192.168.1.19 should be assigned.
>     -ovn-nbctl --wait=sb set Logical-switch sw0
>     other_config:exclude_ips="invalid"
>     -ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
>     -"dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p35
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:20 192.168.1.19"
>     -])
>     -
>     -# Set invalid data in exclude_ips list. It should be ignored.
>     -ovn-nbctl --wait=sb set Logical-switch sw0
>     other_config:exclude_ips="182.168.1.30"
>     -ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
>     -"dynamic"
>     -# 192.168.1.21 should be assigned as that's the next free one.
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:21 192.168.1.21"
>     -])
>     -
>     -# Clear the dynamic addresses assignment request.
>     -ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>     dynamic_addresses], [0],
>     -         [[[]]
>     -])
>     -
>     -# Set IPv6 prefix
>     -ovn-nbctl --wait=sb set Logical-switch sw0
>     other_config:ipv6_prefix="aef0::"
>     -ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
>     -"dynamic"
>     -
>     -# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6
>     should be
>     -# - aef0::800:ff:fe00:26 (EUI64)
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p37
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
>     -])
>     -
>     -ovn-nbctl --wait=sb ls-add sw4
>     -ovn-nbctl --wait=sb set Logical-switch sw4
>     other_config:ipv6_prefix="bef0::" \
>     --- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
>     <http://192.168.2.0/30>
>     -ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
>     -"dynamic"
>     -
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p38
>     dynamic_addresses], [0],
>     -     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
>     -"f0:00:00:00:10:12 dynamic"
>     -
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p39
>     dynamic_addresses], [0],
>     -     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
>     -])
>     -
>     -# Test the case where IPv4 addresses are exhausted and IPv6
>     prefix is set
>     -# p40 should not have an IPv4 address since the pool is exhausted
>     -ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
>     -"dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p40
>     dynamic_addresses], [0],
>     -         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
>     -])
>     -
>     -# Test dynamic changes on switch ports.
>     -#
>     -ovn-nbctl --wait=sb ls-add sw5
>     -ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
>     -"dynamic"
>     -# p41 will start with nothing
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         [[[]]
>     -])
>     -
>     -# Set a subnet. Now p41 should have an ipv4 address, too
>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>     subnet=192.168.1.0/24
>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>     -         ["0a:00:00:a8:01:22 192.168.1.2"
>     -])
>     -
>     -# Clear the other_config. The IPv4 address should be gone
>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         [[[]]
>     -])
>     -
>     -# Set an IPv6 prefix. Now p41 should have an IPv6 address.
>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>     other_config:ipv6_prefix="aef0::"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
>     -])
>     -
>     -# Change the MAC address to a static one. The IPv6 address should
>     update.
>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b dynamic"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
>     -])
>     -
>     -# Change the IPv6 prefix. The IPv6 address should update.
>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>     other_config:ipv6_prefix="bef0::"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
>     -])
>     -
>     -# Clear the other_config. The IPv6 address should be gone
>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         [[[]]
>     -])
>     -
>     -# Set the subnet again. Now p41 should get the IPv4 address again.
>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>     subnet=192.168.1.0/24
>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>     -         ["f0:00:00:00:10:2b 192.168.1.2"
>     -])
>     -
>     -# Add an excluded IP address that conflicts with p41. p41 should
>     update.
>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
>     -exclude_ips="192.168.1.2"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         ["f0:00:00:00:10:2b 192.168.1.3"
>     -])
>     -
>     -# Add static ip address
>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
>     -ovn-nbctl list Logical-Switch-Port p41
>     -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
>     -"dynamic 192.168.1.101"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>     dynamic_addresses], [0],
>     -         ["0a:00:00:a8:01:65 192.168.1.100"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p42
>     dynamic_addresses], [0],
>     -         ["0a:00:00:a8:01:66 192.168.1.101"
>     -])
>     -
>     -# define a mac address prefix
>     -ovn-nbctl ls-add sw6
>     -ovn-nbctl --wait=hv set NB_Global .
>     options:mac_prefix="00:11:22:33:44:55"
>     -ovn-nbctl --wait=sb set Logical-Switch sw6
>     other_config:subnet=192.168.100.0/24
>     -for <http://192.168.100.0/24-for> n in $(seq 1 3); do
>     -    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses
>     "p5$n" dynamic
>     -done
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p51
>     dynamic_addresses], [0],
>     -    ["00:11:22:a8:64:03 192.168.100.2"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p52
>     dynamic_addresses], [0],
>     -    ["00:11:22:a8:64:04 192.168.100.3"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p53
>     dynamic_addresses], [0],
>     -    ["00:11:22:a8:64:05 192.168.100.4"
>     -])
>     -
>     -# verify configuration order does not break IPAM/MACAM
>     -ovn-nbctl ls-add sw7
>     -for n in $(seq 1 3); do
>     -    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses
>     "p7$n" dynamic
>     -done
>     -ovn-nbctl --wait=sb set Logical-Switch sw7
>     other_config:ipv6_prefix="bef0::"
>     -p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 dynamic_addresses)
>     -p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 dynamic_addresses)
>     -p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 dynamic_addresses)
>     -AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
>     -AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
>     -AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
>     -
>     -# request to assign mac only
>     -#
>     -ovn-nbctl ls-add sw8
>     -ovn-nbctl --wait=sb set Logical-Switch sw8 other_config:mac_only=true
>     -for n in $(seq 1 3); do
>     -    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses
>     "p8$n" dynamic
>     -done
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p81
>     dynamic_addresses], [0],
>     -    ["00:11:22:00:00:06"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p82
>     dynamic_addresses], [0],
>     -    ["00:11:22:00:00:07"
>     -])
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p83
>     dynamic_addresses], [0],
>     -    ["00:11:22:00:00:08"
>     -])
>     -
>     -# clear mac_prefix and check it is allocated in a random manner
>     -ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
>     -ovn-nbctl ls-add sw9
>     -ovn-nbctl --wait=sb set Logical-Switch sw9 other_config:mac_only=true
>     -ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 dynamic
>     -
>     -mac_prefix=$(ovn-nbctl --wait=sb get NB_Global .
>     options:mac_prefix | tr -d \")
>     -port_addr=$(ovn-nbctl get Logical-Switch-Port p91
>     dynamic_addresses | tr -d \")
>     -AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
>     -
>     -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
>     -ovn-nbctl ls-add sw10
>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>     other_config:ipv6_prefix="ae01::"
>     -ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101
>     "dynamic ae01::1"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p101
>     dynamic_addresses], [0],
>     -    ["00:11:22:00:00:0a ae01::1"
>     -])
>     -
>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>     other_config:subnet=192.168.110.0/24
>     -ovn-nbctl <http://192.168.110.0/24-ovn-nbctl> --wait=sb lsp-add
>     sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 ae01::2"
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p102
>     dynamic_addresses], [0],
>     -    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
>     -])
>     -
>     -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 northd-backup
>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ipam connectivity])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -# Test for a ping using dynamically allocated addresses.
>     -ovn-nbctl --wait=hv set NB_Global .
>     options:mac_prefix="0a:00:00:00:00:00"
>     -ovn-nbctl ls-add foo -- add Logical_Switch foo other_config
>     subnet=192.168.1.0/24
>     -ovn-nbctl <http://192.168.1.0/24-ovn-nbctl> ls-add alice -- add
>     Logical_Switch alice other_config subnet=192.168.2.0/24
>     <http://192.168.2.0/24>
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -          options:router-port=foo \
>     -          -- lsp-set-addresses rp-foo router
>     -
>     -# Connect alice to R1
>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice type=router \
>     -          options:router-port=alice addresses=\"00:00:00:01:02:04\"
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl --wait=sb lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "dynamic"
>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>     foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl --wait=sb lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "dynamic"
>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>     alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
>     -
>     -# Create logical port foo2 in foo
>     -ovn-nbctl --wait=sb lsp-add foo foo2 \
>     --- lsp-set-addresses foo2 "dynamic"
>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>     foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
>     -
>     -# Create a hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=foo2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>     -    set interface hv1-vif3 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>     -    ofport-request=3
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and foo2
>     -src_mac="0a0000a80103"
>     -dst_mac="0a0000a80104"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 1 3`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="0a0000a80103"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Packet to Expect at foo2
>     -src_mac="0a0000a80103"
>     -dst_mac="0a0000a80104"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 1 3`
>     -expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > received1.packets
>     -echo $expected > expout
>     -AT_CHECK([cat received1.packets], [0], [expout])
>     -
>     -# Packet to Expect at alice1
>     -src_mac="000000010204"
>     -dst_mac="0a0000a80203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif3-tx.pcap > received2.packets
>     -echo $expected > expout
>     -AT_CHECK([cat received2.packets], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ovs-vswitchd restart])
>     -AT_KEYWORDS([vswitchd])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -net_add n1
>     -sim_add hv1
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -OVN_POPULATE_ARP
>     -sleep 2
>     -
>     -as hv1 ovs-vsctl show
>     -
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl dump-flows br-int
>     -total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
>     -
>     -echo "Total flows before vswitchd restart = " $total_flows
>     -
>     -# Code taken from ovs-save utility
>     -save_flows () {
>     -    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
>     -    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
>     -            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
>     -    echo "EOF" >> restore_flows.sh
>     -}
>     -
>     -restart_vswitchd () {
>     -    restore_flows=$1
>     -
>     -    if test $restore_flows = true; then
>     -        save_flows
>     -    fi
>     -
>     -    as hv1
>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>     -
>     -    if test $restore_flows = true; then
>     -        as hv1
>     -        ovs-vsctl --no-wait set open_vswitch .
>     other_config:flow-restore-wait="true"
>     -    fi
>     -
>     -    as hv1
>     -    start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>     -vofproto_dpif -vunixctl
>     -    ovs-ofctl dump-flows br-int
>     -
>     -    if test $restore_flows = true; then
>     -        sh ./restore_flows.sh
>     -        echo "Flows after restore"
>     -        as hv1
>     -        ovs-ofctl dump-flows br-int
>     -        ovs-vsctl --no-wait --if-exists remove open_vswitch .
>     other_config \
>     -            flow-restore-wait="true"
>     -    fi
>     -}
>     -
>     -# Save the flows, restart vswitchd and restore the flows
>     -restart_vswitchd true
>     -OVS_WAIT_UNTIL([
>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>     | wc -l`
>     -    echo "Total flows after vswitchd restart = "
>     $total_flows_after_restart
>     -    test "${total_flows}" = "${total_flows_after_restart}"
>     -])
>     -
>     -# Restart vswitchd without restoring
>     -restart_vswitchd false
>     -OVS_WAIT_UNTIL([
>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>     | wc -l`
>     -    echo "Total flows after vswitchd restart = "
>     $total_flows_after_restart
>     -    test "${total_flows}" = "${total_flows_after_restart}"
>     -])
>     -
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send arp for nexthop])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Topology: Two LSs - ls1 and ls2 are connected via router r0
>     -
>     -# Create logical switches
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -
>     -# Create  router
>     -ovn-nbctl create Logical_Router name=lr0
>     -
>     -# Add router ls1p1 port to gateway router
>     -ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
>     -ovn-nbctl <http://192.168.0.1/24-ovn-nbctl> lsp-add ls1 ls1lp1 --
>     set Logical_Switch_Port ls1lp1  \
>     -    type=router options:router-port=lrp-ls1lp1 \
>     -    addresses='"f0:00:00:00:00:01 192.168.0.1"'
>     -
>     -# Add router ls2p2 port to gateway router
>     -ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
>     -ovn-nbctl <http://192.168.1.1/24-ovn-nbctl> lsp-add ls2 ls2lp1 --
>     set Logical_Switch_Port ls2lp1 \
>     -    type=router options:router-port=lrp-ls2lp1 \
>     -    addresses='"f0:00:00:00:00:02 192.168.1.1"'
>     -
>     -# Set default gateway (nexthop) to 192.168.1.254
>     -ovn-nbctl lr-route-add lr0 "0.0.0.0/0 <http://0.0.0.0/0>"
>     192.168.1.254 lrp-ls2lp1
>     -
>     -# Create logical port ls1lp2 in ls1
>     -ovn-nbctl lsp-add ls1 ls1lp2 \
>     --- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
>     -
>     -# Create logical port ls2lp2 in ls2
>     -ovn-nbctl lsp-add ls2 ls2lp2 \
>     --- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
>     -    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
>     -    options:tx_pcap=hv1/ls1lp2-tx.pcap \
>     -    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
>     -    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
>     -    options:tx_pcap=hv1/ls2lp2-tx.pcap \
>     -    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
>     -    ofport-request=2
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -ovn-sbctl list chassis
>     -ovn-sbctl list encap
>     -echo "---------------------"
>     -
>     -echo "------Flows dump-----"
>     -as hv1
>     -ovs-ofctl dump-flows
>     -echo "---------------------"
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -src_mac="f00000000003"
>     -dst_mac="f00000000001"
>     -src_ip=`ip_to_hex 192 168 0 2`
>     -dst_ip=`ip_to_hex 8 8 8 8`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -# Send IP packet destined to 8.8.8.8 from lsp1lp2
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
>     -
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -# ARP packet should be received with Target IP Address set to
>     192.168.1.254 and
>     -# not 8.8.8.8
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ls2lp2-tx.pcap | trim_zeros > packets
>     -expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe"
>     -echo $expected > expout
>     -AT_CHECK([cat packets], [0], [expout])
>     -cat packets
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -# Create logical switch
>     -ovn-nbctl ls-add ls0
>     -# Create gateway router
>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>     -# Add router port to gateway router
>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>     <http://192.168.0.1/24>
>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>     -    type=router options:router-port=lrp0
>     addresses='"f0:00:00:00:00:01"'
>     -# Add nat-address option
>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="f0:00:00:00:00:01 192.168.0.2"
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0
>     -
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>     -
>     -# Wait until the patch ports are created in hv1 to connect br-int
>     to br-eth0
>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>     -
>     -# Wait for packet to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
>     -echo $expected > expout
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
>     -echo $expected >> expout
>     -AT_CHECK([sort packets], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in
>     localnet])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -# Create logical switch
>     -ovn-nbctl ls-add ls0
>     -# Create gateway router
>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>     -# Add router port to gateway router
>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>     <http://192.168.0.1/24>
>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>     -    type=router options:router-port=lrp0
>     addresses='"f0:00:00:00:00:01"'
>     -# Add nat-address option
>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="router"
>     -# Add NAT rules
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>     <http://10.0.0.0/24>])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
>     -# Add load balancers
>     -AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80
>     <http://192.168.0.3:80> 10.0.0.2:80
>     <http://10.0.0.2:80>,10.0.0.3:80 <http://10.0.0.3:80>])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>     -AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080
>     <http://192.168.0.3:8080> 10.0.0.2:8080
>     <http://10.0.0.2:8080>,10.0.0.3:8080 <http://10.0.0.3:8080>])
>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl \
>     -    -- add-br br-phys \
>     -    -- add-br br-eth0
>     -
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>     -
>     -# Wait until the patch ports are created to connect br-int to br-eth0
>     -OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>     -
>     -ovn-sbctl list port_binding lrp0-rp
>     -echo "*****"
>     -ovn-nbctl list logical_switch_port lrp0-rp
>     -ovn-nbctl list logical_router_port lrp0
>     -ovn-nbctl show
>     -# Wait for packet to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
>     -echo $expected > expout
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
>     -echo $expected >> expout
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003"
>     -echo $expected >> expout
>     -AT_CHECK([sort packets], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- delete mac bindings])
>     -ovn_start
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl -- add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -# Create logical switch ls0
>     -ovn-nbctl ls-add ls0
>     -# Create ports lp0, lp1 in ls0
>     -ovn-nbctl lsp-add ls0 lp0
>     -ovn-nbctl lsp-add ls0 lp1
>     -ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
>     -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
>     -dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" |
>     cut -f2 -d " "`
>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>     logical_port=lp0 mac="mac1"
>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>     logical_port=lp1 mac="mac2"
>     -ovn-sbctl find MAC_Binding
>     -# Delete port lp0 and check that its MAC_Binding is deleted.
>     -ovn-nbctl lsp-del lp0
>     -ovn-sbctl find MAC_Binding
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0
>     | wc -l` = 0])
>     -# Delete logical switch ls0 and check that its MAC_Binding is
>     deleted.
>     -ovn-nbctl ls-del ls0
>     -ovn-sbctl find MAC_Binding
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- conntrack zone allocation])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# 2 logical switches "foo" (192.168.1.0/24
>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>     <http://172.16.1.0/24>)
>     -# connected to a router R1.
>     -# foo has foo1 to act as a client.
>     -# bar has bar1, bar2, bar3 to act as servers.
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -for i in foo1 bar1 bar2 bar3; do
>     -    ovs-vsctl -- add-port br-int $i -- \
>     -        set interface $i external-ids:iface-id=$i \
>     -        options:tx_pcap=hv1/$i-tx.pcap \
>     -        options:rxq_pcap=hv1/$i-rx.pcap
>     -done
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port bar1, bar2 and bar3 in bar
>     -for i in `seq 1 3`; do
>     -    ip=`expr $i + 1`
>     -    ovn-nbctl lsp-add bar bar$i \
>     -    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
>     -done
>     -
>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep
>     REG13 | wc -l` -eq 4])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- tag allocation])
>     -ovn_start
>     -
>     -AT_CHECK([ovn-nbctl ls-add ls0])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
>     -AT_CHECK([ovn-nbctl ls-add ls1])
>     -
>     -dnl When a tag is provided, no allocation is done
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>     -])
>     -dnl The same 'tag' gets created in southbound database.
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c0"], [0], [3
>     -])
>     -
>     -dnl Allocate tags and see it getting created in both NB and SB
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c1"], [0], [1
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c2"], [0], [2
>     -])
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c3"], [0], [4
>     -])
>     -
>     -dnl A different parent.
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c4"], [0], [1
>     -])
>     -
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c5"], [0], [2
>     -])
>     -
>     -dnl Delete a logical port and create a new one.
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c6"], [0], [1
>     -])
>     -
>     -dnl Restart northd to see that the same allocation remains.
>     -as northd
>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>     -start_daemon ovn-northd \
>     -    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>     -    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>     -
>     -dnl Create a switch to make sure that ovn-northd has run through
>     the main loop.
>     -AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>     -])
>     -
>     -dnl Create a switch port with a tag that has already been allocated.
>     -dnl It should go through fine with a duplicate tag.
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
>     -])
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="c7"], [0], [2
>     -])
>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>     -])
>     -
>     -AT_CHECK([ovn-nbctl ls-add ls2])
>     -dnl When there is no parent_name provided (for say, 'localnet'),
>     'tag_request'
>     -dnl gets copied to 'tag'
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
>     -AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
>     -])
>     -dnl The same 'tag' gets created in southbound database.
>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>     port_binding \
>     -logical_port="local0"], [0], [25
>     -])
>     -dnl If 'tag_request' is 0 for localnet, nothing gets written to 'tag'
>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
>     -AT_CHECK([ovn-nbctl lsp-get-tag local1])
>     -dnl change the tag_request.
>     -AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1
>     tag_request=50])
>     -AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on
>     localnet])
>     -ovn_start
>     -ovn-nbctl ls-add lsw0
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -    ovs-vsctl add-br br-eth0
>     -    AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>     -done
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>     -
>     -
>     -# Create 3 vifs.
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>     "f0:00:00:00:00:01 192.168.1.1"])
>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>     "f0:00:00:00:00:01"])
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2
>     "f0:00:00:00:00:02 192.168.1.2"])
>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif2
>     "f0:00:00:00:00:02"])
>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif3
>     "f0:00:00:00:00:03 192.168.1.3"])
>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif3
>     "f0:00:00:00:00:03"])
>     -
>     -# Bind the localvif1 to hv1.
>     -as hv1
>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>     localvif1 external_ids:iface-id=localvif1])
>     -
>     -# On hv1, check that there are no flows outputting bcast to tunnel
>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>     ofctl_strip | grep output | wc -l` -eq 0])
>     -
>     -# On hv2, check that no flow outputs bcast to tunnel to hv1.
>     -as hv2
>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>     ofctl_strip | grep output | wc -l` -eq 0])
>     -
>     -# Now bind vif2 on hv2.
>     -AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface
>     localvif2 external_ids:iface-id=localvif2])
>     -
>     -# At this point, the broadcast flow on vif2 should be deleted.
>     -# because, there is now a localnet vif bound (table=32
>     programming logic)
>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>     ofctl_strip | grep output | wc -l` -eq 0])
>     -
>     -# Verify that the local net patch port exists on hv2.
>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>     -
>     -# Now bind vif3 on hv2.
>     -AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface
>     localvif3 external_ids:iface-id=localvif3])
>     -
>     -# Verify that the local net patch port still exists on hv2
>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>     -
>     -# Delete localvif2
>     -AT_CHECK([ovn-nbctl lsp-del localvif2])
>     -
>     -# Verify that the local net patch port still exists on hv2,
>     -# because, localvif3 is still bound.
>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -
>     -AT_SETUP([ovn -- ACL logging])
>     -AT_KEYWORDS([ovn])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -sim_add hv
>     -as hv
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -for i in lp1 lp2; do
>     -    ovs-vsctl -- add-port br-int $i -- \
>     -        set interface $i external-ids:iface-id=$i \
>     -        options:tx_pcap=hv/$i-tx.pcap \
>     -        options:rxq_pcap=hv/$i-rx.pcap
>     -done
>     -
>     -lp1_mac="f0:00:00:00:00:01"
>     -lp1_ip="192.168.1.2"
>     -
>     -lp2_mac="f0:00:00:00:00:02"
>     -lp2_ip="192.168.1.3"
>     -
>     -ovn-nbctl ls-add lsw0
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>     -ovn-nbctl --wait=sb sync
>     -
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>     -ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0
>     to-lport 1000 'tcp.dst==81' drop
>     -
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
>     -ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0
>     to-lport 1000 'tcp.dst==83' allow
>     -
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
>     -ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85'
>     allow-related
>     -
>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
>     -ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow
>     acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
>     -
>     -ovn-sbctl dump-flows
>     -
>     -
>     -# Send packet that should be dropped without logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should be dropped with logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should be allowed without logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should be allowed with logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should allow related flows without logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should allow related flows with logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should be rejected without logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Send packet that should be rejected with logging.
>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>     -        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log'
>     hv/ovn-controller.log) ])
>     -
>     -AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed
>     's/.*name=/name=/'], [0], [dnl
>     -name="drop-flow", verdict=drop, severity=alert:
>     tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn
>     -name="allow-flow", verdict=allow, severity=info:
>     tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn
>     -name="<unnamed>", verdict=allow, severity=info:
>     tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn
>     -name="reject-flow", verdict=reject, severity=alert:
>     tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn
>     -])
>     -
>     -OVN_CLEANUP([hv])
>     -AT_CLEANUP
>     -
>     -
>     -AT_SETUP([ovn -- ACL rate-limited logging])
>     -AT_KEYWORDS([ovn])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -sim_add hv
>     -as hv
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -for i in lp1 lp2; do
>     -    ovs-vsctl -- add-port br-int $i -- \
>     -        set interface $i external-ids:iface-id=$i \
>     -        options:tx_pcap=hv/$i-tx.pcap \
>     -        options:rxq_pcap=hv/$i-rx.pcap
>     -done
>     -
>     -lp1_mac="f0:00:00:00:00:01"
>     -lp1_ip="192.168.1.2"
>     -
>     -lp2_mac="f0:00:00:00:00:02"
>     -lp2_ip="192.168.1.3"
>     -
>     -ovn-nbctl ls-add lsw0
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>     -ovn-nbctl --wait=sb sync
>     -
>     -
>     -# Add an ACL that rate-limits logs at 10 per second.
>     -ovn-nbctl meter-add http-rl1 drop 10 pktps
>     -ovn-nbctl --log --severity=alert --meter=http-rl1
>     --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>     -
>     -# Add an ACL that rate-limits logs at 5 per second.
>     -ovn-nbctl meter-add http-rl2 drop 5 pktps
>     -ovn-nbctl --log --severity=alert --meter=http-rl2
>     --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
>     -
>     -# Add an ACL that doesn't rate-limit logs.
>     -ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0
>     to-lport 1000 'tcp.dst==82' drop
>     -ovn-nbctl --wait=hv sync
>     -
>     -# For each ACL, send 100 packets.
>     -for i in `seq 1 100`; do
>     -    ovs-appctl netdev-dummy/receive lp1
>     'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)'
>     -
>     -    ovs-appctl netdev-dummy/receive lp1
>     'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)'
>     -
>     -    ovs-appctl netdev-dummy/receive lp1
>     'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)'
>     -done
>     -
>     -# The rate at which packets are sent is highly system-dependent,
>     so we
>     -# can't count on precise drop counts.  To work around that, we just
>     -# check that exactly 100 "http-acl3" actions were logged and that
>     there
>     -# were more "http-acl1" actions than "http-acl2" ones.
>     -OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3'
>     hv/ovn-controller.log) ])
>     -
>     -# On particularly slow or overloaded systems, the transmission
>     rate may
>     -# be lower than the configured meter rate.  To prevent false test
>     -# failures, we check the duration count of the meter, and if it's
>     -# greater than nine seconds, just skip the test.
>     -d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep
>     "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
>     -
>     -echo "Meter duration: $d_secs"
>     -AT_SKIP_IF([test $d_secs -gt 9])
>     -
>     -# Print some information that may help debugging.
>     -as hv ovs-appctl -t ovn-controller meter-table-list
>     -as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
>     -
>     -n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
>     -n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
>     -n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
>     -
>     -AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
>     -AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
>     -
>     -OVN_CLEANUP([hv])
>     -AT_CLEANUP
>     -
>     -
>     -AT_SETUP([ovn -- DSCP marking and meter check])
>     -AT_KEYWORDS([ovn])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add lsw0
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>     -ovn-nbctl --wait=sb lsp-add lsw0 lp3
>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>     -ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
>     -ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
>     -ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
>     -ovn-nbctl --wait=sb sync
>     -net_add n1
>     -sim_add hv
>     -as hv
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap
>     options:rxq_pcap=vif1-rx.pcap ofport-request=1
>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>     external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap
>     options:rxq_pcap=vif2-rx.pcap ofport-request=2
>     -
>     -AT_CAPTURE_FILE([trace])
>     -ovn_trace () {
>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>     -}
>     -
>     -# Extracts nw_tos from the final flow from ofproto/trace output
>     and prints
>     -# it on stdout.  Prints "none" if no nw_tos was included.
>     -get_final_nw_tos() {
>     -    if flow=$(grep '^Final flow:' stdout); then :; else
>     -       # The output didn't have a final flow.
>     -       return 99
>     -    fi
>     -
>     -    tos=$(echo "$flow" | sed -n
>     's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
>     -    case $tos in
>     -        '') echo none ;;
>     -        *) echo $tos ;;
>     -    esac
>     -}
>     -
>     -# check_tos TOS
>     -#
>     -# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set
>     to TOS.
>     -check_tos() {
>     -    # First check with ovn-trace for logical flows.
>     -    echo "checking for tos $1"
>     -    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
>     -     echo 'output("lp2");') > expout
>     -    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src
>     == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src ==
>     1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
>     -
>     -    # Then re-check with ofproto/trace for a physical packet.
>     -    AT_CHECK([ovs-appctl ofproto/trace br-int
>     'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'],
>     [0], [stdout-nolog])
>     -    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
>     -])
>     -}
>     -
>     -# check at L2
>     -AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src ==
>     f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0],
>     [output("lp2");
>     -])
>     -AT_CHECK([ovs-appctl ofproto/trace br-int
>     'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'],
>     [0], [stdout-nolog])
>     -AT_CHECK([get_final_nw_tos], [0], [none
>     -])
>     -
>     -# check at L3 without dscp marking
>     -check_tos 0
>     -
>     -# Mark DSCP with a valid value
>     -qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS
>     priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\
>     is_chassis_resident(\"lp1\")" direction="from-lport" -- set
>     Logical_Switch lsw0 qos_rules=@lp1-qos)
>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>     -])
>     -check_tos 48
>     -
>     -# check at hv without qos meter
>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>     meter | wc -l], [0], [0
>     -])
>     -
>     -# Update the meter rate
>     -ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
>     -
>     -# check at hv with a qos meter table
>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>     rate=100 | wc -l], [0], [1
>     -])
>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>     meter | wc -l], [0], [1
>     -])
>     -
>     -# Update the DSCP marking
>     -ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
>     -check_tos 63
>     -
>     -# Update the meter rate
>     -ovn-nbctl --wait=hv set QoS $qos_id
>     bandwidth=rate=4294967295,burst=4294967295
>     -
>     -# check at hv with a qos meter table
>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>     burst_size=4294967295 | wc -l], [0], [1
>     -])
>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>     meter | wc -l], [0], [1
>     -])
>     -
>     -ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\""
>     direction="to-lport"
>     -check_tos 63
>     -
>     -# Disable DSCP marking
>     -ovn-nbctl --wait=hv qos-del lsw0
>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
>     -])
>     -check_tos 0
>     -
>     -# check at hv without qos meter
>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>     meter | wc -l], [0], [0
>     -])
>     -
>     -# check meter with chassis not resident
>     -ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" &&
>     is_chassis_resident("lp3")' rate=11123 burst=111230
>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>     -])
>     -
>     -# check no meter table
>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>     meter | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>     rate=11123 | wc -l], [0], [0
>     -])
>     -
>     -OVN_CLEANUP([hv])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- read-only sb db:ptcp access])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -
>     -: > .$1.db.~lock~
>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>     -
>     -# Add read-only remote to sb ovsdb-server
>     -AT_CHECK(
>     -  [ovsdb-tool transact ovn-sb.db \
>     -     ['["OVN_Southbound",
>     -       {"op": "insert",
>     -        "table": "SB_Global",
>     -        "row": {
>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>     -       {"op": "insert",
>     -        "table": "Connection",
>     -        "uuid-name": "xyz",
>     -        "row": {"target": "ptcp:0:127.0.0.1",
>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>     -
>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock
>     --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
>     -
>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>     -
>     -# read-only accesses should succeed
>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global],
>     [0], [stdout], [ignore])
>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list
>     Connection], [0], [stdout], [ignore])
>     -
>     -# write access should fail
>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch
>     vxlan 1.2.4.8], [1], [ignore],
>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>     allowed when database server is in read only mode","error":"not
>     allowed"}
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- read-only sb db:pssl access])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>     -\\]"])
>     -
>     -: > .$1.db.~lock~
>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>     -
>     -# Add read-only remote to sb ovsdb-server
>     -AT_CHECK(
>     -  [ovsdb-tool transact ovn-sb.db \
>     -     ['["OVN_Southbound",
>     -       {"op": "insert",
>     -        "table": "SB_Global",
>     -        "row": {
>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>     -       {"op": "insert",
>     -        "table": "Connection",
>     -        "uuid-name": "xyz",
>     -        "row": {"target": "pssl:0:127.0.0.1",
>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>     -
>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
>     - --remote=db:OVN_Southbound,SB_Global,connections \
>     - --private-key="$PKIDIR/testpki-privkey2.pem" \
>     - --certificate="$PKIDIR/testpki-cert2.pem" \
>     - --ca-cert="$PKIDIR/testpki-cacert.pem" \
>     -                          ovn-sb.db
>     -
>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>     -
>     -# read-only accesses should succeed
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -                    list SB_Global], [0], [stdout], [ignore])
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -                    list Connection], [0], [stdout], [ignore])
>     -
>     -# write access should fail
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>     allowed when database server is in read only mode","error":"not
>     allowed"}
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- nb connection/ssl commands])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>     -\\]"])
>     -
>     -: > .$1.db.~lock~
>     -ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
>     -
>     -# Start nb db server using db connection/ssl entries (unpopulated
>     initially)
>     -start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
>     - --remote=db:OVN_Northbound,NB_Global,connections \
>     - --private-key=db:OVN_Northbound,SSL,private_key \
>     - --certificate=db:OVN_Northbound,SSL,certificate \
>     - --ca-cert=db:OVN_Northbound,SSL,ca_cert \
>     -                          ovn-nb.db
>     -
>     -# Populate SSL configuration entries in nb db
>     -AT_CHECK(
>     -    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
>     -                       $PKIDIR/testpki-cert.pem \
>     -                       $PKIDIR/testpki-cacert.pem], [0],
>     [stdout], [ignore])
>     -
>     -# Populate a passive SSL connection in nb db
>     -AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0],
>     [stdout], [ignore])
>     -
>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>     -
>     -# Verify SSL connetivity to nb db server
>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          list NB_Global],
>     -         [0], [stdout], [ignore])
>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          list Connection],
>     -         [0], [stdout], [ignore])
>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          get-connection],
>     -         [0], [stdout], [ignore])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- sb connection/ssl commands])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>     -\\]"])
>     -
>     -: > .$1.db.~lock~
>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>     -
>     -# Start sb db server using db connection/ssl entries (unpopulated
>     initially)
>     -start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
>     - --remote=db:OVN_Southbound,SB_Global,connections \
>     - --private-key=db:OVN_Southbound,SSL,private_key \
>     - --certificate=db:OVN_Southbound,SSL,certificate \
>     - --ca-cert=db:OVN_Southbound,SSL,ca_cert \
>     -                          ovn-sb.db
>     -
>     -# Populate SSL configuration entries in sb db
>     -AT_CHECK(
>     -    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
>     -                       $PKIDIR/testpki-cert.pem \
>     -                       $PKIDIR/testpki-cacert.pem], [0],
>     [stdout], [ignore])
>     -
>     -# Populate a passive SSL connection in sb db
>     -AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0],
>     [stdout], [ignore])
>     -
>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>     -
>     -# Verify SSL connetivity to sb db server
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          list SB_Global],
>     -         [0], [stdout], [ignore])
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          list Connection],
>     -         [0], [stdout], [ignore])
>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>     - --private-key=$PKIDIR/testpki-privkey.pem \
>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>     -          get-connection],
>     -         [0], [stdout], [ignore])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- nested containers])
>     -ovn_start
>     -
>     -# Physical network:
>     -# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
>     -
>     -# Logical network:
>     -# 3 Logical switches - "mgmt" (172.16.1.0/24
>     <http://172.16.1.0/24>), "foo" (192.168.1.0/24
>     <http://192.168.1.0/24>)
>     -# and "bar" (192.168.2.0/24 <http://192.168.2.0/24>). They are
>     all connected to router R1.
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl ls-add mgmt
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -
>     -# Connect mgmt to R1
>     -ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt
>     type=router \
>     -          options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>     type=router \
>     -          options:router-port=bar addresses=\"00:00:00:01:02:04\"
>     -
>     -# "mgmt" has VM1 and VM2 connected
>     -ovn-nbctl lsp-add mgmt vm1 \
>     --- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
>     -
>     -ovn-nbctl lsp-add mgmt vm2 \
>     --- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# "foo1" and "foo2" are containers belonging to switch "foo"
>     -# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as
>     parent_port.
>     -ovn-nbctl lsp-add foo foo1 vm1 1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
>     -
>     -ovn-nbctl lsp-add foo foo2 vm2 2 \
>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>     -
>     -# "bar1" and "bar2" are containers belonging to switch "bar"
>     -# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as
>     parent_port.
>     -ovn-nbctl lsp-add bar bar1 vm1 2 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
>     -
>     -ovn-nbctl lsp-add bar bar2 vm2 1 \
>     --- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>     -
>     -# bar3 is a standalone VM belonging to switch "bar"
>     -ovn-nbctl lsp-add bar bar3 \
>     --- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int vm1 -- \
>     -    set interface vm1 external-ids:iface-id=vm1 \
>     -    options:tx_pcap=hv1/vm1-tx.pcap \
>     -    options:rxq_pcap=hv1/vm1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int bar3 -- \
>     -    set interface bar3 external-ids:iface-id=bar3 \
>     -    options:tx_pcap=hv1/bar3-tx.pcap \
>     -    options:rxq_pcap=hv1/bar3-rx.pcap \
>     -    ofport-request=2
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int vm2 -- \
>     -    set interface vm2 external-ids:iface-id=vm2 \
>     -    options:tx_pcap=hv2/vm2-tx.pcap \
>     -    options:rxq_pcap=hv2/vm2-rx.pcap \
>     -    ofport-request=1
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and foo2 (same switch, different
>     HVs and
>     -# different VLAN tags).
>     -src_mac="f00000010205"
>     -dst_mac="f00000010206"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 1 3`
>     -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at foo2
>     -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -echo  $packet > expected
>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>     -
>     -# Send ip packets between foo1 and bar2 (different switch,
>     different HV)
>     -src_mac="f00000010205"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 3`
>     -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at bar2
>     -src_mac="000000010204"
>     -dst_mac="f00000010208"
>     -packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -echo  $packet >> expected
>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>     -
>     -# Send ip packets between foo1 and bar1
>     -# (different switch, loopback to same vm but different tag)
>     -src_mac="f00000010205"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at bar1
>     -src_mac="000000010204"
>     -dst_mac="f00000010207"
>     -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -echo  $packet > expected1
>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>     -
>     -# Send ip packets between bar1 and bar3
>     -# (same switch. But one is container and another is a standalone VM)
>     -src_mac="f00000010207"
>     -dst_mac="f00000010209"
>     -src_ip=`ip_to_hex 192 168 2 2`
>     -dst_ip=`ip_to_hex 192 168 2 3`
>     -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at bar3
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -echo  $packet > expected
>     -OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
>     -
>     -# Send ip packets between foo1 and vm1.
>     -(different switch, container to the VM hosting it.)
>     -src_mac="f00000010205"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 2`
>     -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at vm1
>     -src_mac="000000010202"
>     -dst_mac="f00000010203"
>     -packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -echo  $packet >> expected1
>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>     -
>     -# Send packets from vm1 to bar1.
>     -(different switch, A hosting VM to a container inside it)
>     -src_mac="f00000010203"
>     -dst_mac="000000010202"
>     -src_ip=`ip_to_hex 172 16 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at vm1
>     -src_mac="000000010204"
>     -dst_mac="f00000010207"
>     -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -echo  $packet >> expected1
>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>     -
>     -# Send broadcast packet from foo1. foo1 should not receive the
>     same packet.
>     -src_mac="f00000010205"
>     -dst_mac="ffffffffffff"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 255 255 255 255`
>     -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>     -
>     -# expected packet at VM1
>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based
>     routes])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>     LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and bar
>     -# (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>     -#
>     -# R2 and R3 are gateway routers.
>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and R3 has
>     bob (172.16.1.0/24 <http://172.16.1.0/24>)
>     -# connected to it. Note how both alice and bob have the same
>     subnet behind it.
>     -# We are trying to simulate external network via those 2
>     switches. In real
>     -# world the switch ports of these switches will have addresses
>     set as "unknown"
>     -# to make them learning switches. Or those switches will be
>     "localnet" ones.
>     -
>     -# Create three hypervisors and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=bar1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>     -    set interface hv3-vif1 external-ids:iface-id=bob1 \
>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>     -ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add bob
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>     type=router \
>     -    options:router-port=bar addresses=\"00:00:01:01:02:04\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect bob to R3
>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>     <http://172.16.1.2/24>
>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>     -    type=router options:router-port=bob
>     addresses=\"00:00:03:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Connect R3 to join
>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>     <http://20.0.0.3/24>
>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>     -    type=router options:router-port=R3_join
>     addresses='"00:00:04:01:02:05"'
>     -
>     -# Install static routes with source ip address as the policy for
>     routing.
>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>     go via R3.
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>     <http://192.168.1.0/24> 20.0.0.2
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>     <http://192.168.2.0/24> 20.0.0.3
>     -
>     -# Install static routes with destination ip address as the policy
>     for routing.
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port bar1 in bar
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
>     -
>     -# Create logical port bob1 in bob
>     -ovn-nbctl lsp-add bob bob1 \
>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -# Send ip packets between foo1 and bar1
>     -# (East-west traffic should flow normally)
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 3`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>     -
>     -# Send ip packets between bar1 and bob1
>     -src_mac="f00000010204"
>     -dst_mac="000001010204"
>     -src_ip=`ip_to_hex 192 168 2 2`
>     -dst_ip=`ip_to_hex 172 16 1 4`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>     -#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
>     -
>     -# Packet to expect at bar1
>     -src_mac="000001010204"
>     -dst_mac="f00000010204"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 192 168 2 2`
>     -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -echo $expected > expected
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -
>     -# Packet to Expect at alice1
>     -src_mac="000002010203"
>     -dst_mac="f00000010205"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 3`
>     -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
>     -echo $expected > expected
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Packet to Expect at bob1
>     -src_mac="000003010203"
>     -dst_mac="f00000010206"
>     -src_ip=`ip_to_hex 192 168 2 2`
>     -dst_ip=`ip_to_hex 172 16 1 4`
>     -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
>     -echo $expected > expected
>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>     10.0.0.4 aef0::4"
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>     10.0.0.6 20.0.0.4"
>     -
>     -DNS1=`ovn-nbctl create DNS records={}`
>     -DNS2=`ovn-nbctl create DNS records={}`
>     -
>     -ovn-nbctl set DNS $DNS1 records:vm1.ovn.org
>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>     -ovn-nbctl set DNS $DNS1 records:vm2.ovn.org
>     <http://vm2.ovn.org>="10.0.0.6 20.0.0.4"
>     -ovn-nbctl set DNS $DNS2 records:vm3.ovn.org
>     <http://vm3.ovn.org>="40.0.0.4"
>     -
>     -ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
>     -
>     -net_add n1
>     -sim_add hv1
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -OVN_POPULATE_ARP
>     -sleep 2
>     -as hv1 ovs-vsctl show
>     -
>     -echo "*************************"
>     -ovn-sbctl list DNS
>     -echo "*************************"
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -# set_dns_params host_name
>     -# Sets the dns_req_data and dns_resp_data
>     -set_dns_params() {
>     -    local hname=$1
>     -    local ttl=00000e10
>     -    an_count=0001
>     -    type=0001
>     -    case $hname in
>     -    vm1)
>     -        # vm1.ovn.org <http://vm1.ovn.org>
>     -        query_name=03766d31036f766e036f726700
>     -        # IPv4 address - 10.0.0.4
>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>     -        ;;
>     -    vm2)
>     -        # vm2.ovn.org <http://vm2.ovn.org>
>     -        query_name=03766d32036f766e036f726700
>     -        # IPv4 address - 10.0.0.6
>     - expected_dns_answer=${query_name}00010001${ttl}00040a000006
>     -        # IPv4 address - 20.0.0.4
>     -
>     expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004
>     -        an_count=0002
>     -        ;;
>     -    vm3)
>     -        # vm3.ovn.org <http://vm3.ovn.org>
>     -        query_name=03766d33036f766e036f726700
>     -        # IPv4 address - 40.0.0.4
>     - expected_dns_answer=${query_name}00010001${ttl}000428000004
>     -        ;;
>     -    vm1_ipv6_only)
>     -        # vm1.ovn.org <http://vm1.ovn.org>
>     -        query_name=03766d31036f766e036f726700
>     -        # IPv6 address - aef0::4
>     -        type=001c
>     -
>     expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004
>     -        ;;
>     -    vm1_ipv4_v6)
>     -        # vm1.ovn.org <http://vm1.ovn.org>
>     -        query_name=03766d31036f766e036f726700
>     -        type=00ff
>     -        an_count=0002
>     -        # IPv4 address - 10.0.0.4
>     -        # IPv6 address - aef0::4
>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>     -
>     expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
>     -
>     expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004
>     -        ;;
>     -    vm1_invalid_type)
>     -        # vm1.ovn.org <http://vm1.ovn.org>
>     -        query_name=03766d31036f766e036f726700
>     -        # IPv6 address - aef0::4
>     -        type=0002
>     -        ;;
>     -    vm1_incomplete)
>     -        # set type to none
>     -        type=''
>     -    esac
>     -    # TTL - 3600
>     -    local dns_req_header=010201200001000000000000
>     -    local dns_resp_header=010281200001${an_count}00000000
>     -    dns_req_data=${dns_req_header}${query_name}${type}0001
>     -
>     dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer}
>     -}
>     -
>     -# This shell function sends a DNS request packet
>     -# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
>     -test_dns() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     dns_reply=$6
>     -    local dns_query_data=$7
>     -    shift; shift; shift; shift; shift; shift; shift;
>     -    # Packet size => IPv4 header (20) + UDP header (8) +
>     -    #                DNS data (header + query)
>     -    ip_len=`expr 28 + ${#dns_query_data} / 2`
>     -    udp_len=`expr $ip_len - 20`
>     -    ip_len=$(printf "%x" $ip_len)
>     -    udp_len=$(printf "%x" $udp_len)
>     -    local
>     request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
>     - request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
>     -    # dns data
>     -    request=${request}${dns_query_data}
>     -
>     -    if test $dns_reply != 0; then
>     -        local dns_reply=$1
>     -        ip_len=`expr 28 + ${#dns_reply} / 2`
>     -        udp_len=`expr $ip_len - 20`
>     -        ip_len=$(printf "%x" $ip_len)
>     -        udp_len=$(printf "%x" $udp_len)
>     -        local
>     reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
>     - reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
>     -        echo $reply >> $inport.expected
>     -    else
>     -        for outport; do
>     -            echo $request >> $outport.expected
>     -        done
>     -    fi
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>     -}
>     -
>     -test_dns6() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     dns_reply=$6
>     -    local dns_query_data=$7
>     -    shift; shift; shift; shift; shift; shift; shift;
>     -    # Packet size => UDP header (8) +
>     -    #                DNS data (header + query)
>     -    ip_len=`expr 8 + ${#dns_query_data} / 2`
>     -    udp_len=$ip_len
>     -    ip_len=$(printf "%x" $ip_len)
>     -    udp_len=$(printf "%x" $udp_len)
>     -    local
>     request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
>     -    request=${request}9234003500${udp_len}0000
>     -    #dns data
>     -    request=${request}${dns_query_data}
>     -
>     -    if test $dns_reply != 0; then
>     -        local dns_reply=$1
>     -        ip_len=`expr 8 + ${#dns_reply} / 2`
>     -        udp_len=$ip_len
>     -        ip_len=$(printf "%x" $ip_len)
>     -        udp_len=$(printf "%x" $udp_len)
>     -        local
>     reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
>     -        reply=${reply}0035923400${udp_len}0000${dns_reply}
>     -        echo $reply >> $inport.expected
>     -    else
>     -        for outport; do
>     -            echo $request >> $outport.expected
>     -        done
>     -    fi
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>     -}
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>     -
>     -set_dns_params vm2
>     -src_ip=`ip_to_hex 10 0 0 4`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=1
>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 1.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap > 1.packets
>     -cat 1.expected | cut -c -48 > expout
>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 1.expected | cut -c 53- > expout
>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -set_dns_params vm1
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=1
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Clear the query name options for ls1-lp2
>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
>     <http://vm2.ovn.org>
>     -
>     -set_dns_params vm2
>     -src_ip=`ip_to_hex 10 0 0 4`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=0
>     -test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply
>     $dns_req_data
>     -
>     -# NXT_RESUMEs should be 3.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap > 1.packets
>     -AT_CHECK([cat 1.packets], [0], [])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Clear the query name for ls1-lp1
>     -# Since ls1 has no query names configued,
>     -# ovn-northd should not add the DNS flows.
>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
>     <http://vm1.ovn.org>
>     -
>     -set_dns_params vm1
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=0
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data
>     -
>     -# NXT_RESUMEs should be 3 only.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Test IPv6 (AAAA records) using IPv4 packet.
>     -# Add back the DNS options for ls1-lp1.
>     -ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org
>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>     -
>     -set_dns_params vm1_ipv6_only
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=1
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 4.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
>     -set_dns_params vm1_ipv4_v6
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=1
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 5.
>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -cat 2.expected | cut -c -48 > expout
>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 2.expected | cut -c 53- > expout
>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Invalid type.
>     -set_dns_params vm1_invalid_type
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=0
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data
>     -
>     -# NXT_RESUMEs should be 6.
>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Incomplete DNS packet.
>     -set_dns_params vm1_incomplete
>     -src_ip=`ip_to_hex 10 0 0 6`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=0
>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data
>     -
>     -# NXT_RESUMEs should be 7.
>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Add one more DNS record to the ls1.
>     -ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
>     -
>     -set_dns_params vm3
>     -src_ip=`ip_to_hex 10 0 0 4`
>     -dst_ip=`ip_to_hex 10 0 0 1`
>     -dns_reply=1
>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 8.
>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap > 1.packets
>     -cat 1.expected | cut -c -48 > expout
>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat 1.expected | cut -c 53- > expout
>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -# Try DNS query over IPv6
>     -set_dns_params vm1
>     -src_ip=aef00000000000000000000000000004
>     -dst_ip=aef00000000000000000000000000001
>     -dns_reply=1
>     -test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>     $dns_req_data $dns_resp_data
>     -
>     -# NXT_RESUMEs should be 9.
>     -OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap > 1.packets
>     -# Skipping the UDP checksum.
>     -cat 1.expected | cut -c 1-120,125- > expout
>     -AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
>     -
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -rm -f 1.expected
>     -rm -f 2.expected
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA
>     distributed router gateway port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add gw1
>     -as gw1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -sim_add gw2
>     -as gw2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.4
>     -
>     -sim_add ext1
>     -as ext1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -# 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
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add outside
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect alice to R1 as distributed router gateway port on gw1
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl \
>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>     -                                     chassis_name=gw1 \
>     -                                     priority=20 -- \
>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>     -                                     chassis_name=gw2 \
>     -                                     priority=10 -- \
>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port outside1 in outside
>     -ovn-nbctl lsp-add outside outside1 \
>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# Create localnet port in alice
>     -ovn-nbctl lsp-add alice ln-alice
>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>     -ovn-nbctl lsp-set-type ln-alice localnet
>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>     -# mapping to the external network, is the one generating packets
>     -as gw1 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -as gw2 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -as ext1 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 2
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -test_ip_packet()
>     -{
>     -    local active_gw=$1
>     -    local backup_gw=$2
>     -    local backup_vswitchd_dead=$3
>     -
>     -    # Send ip packet between foo1 and outside1
>     -    src_mac="f00000010203" # foo1 mac
>     -    dst_mac="000001010203" # rp-foo mac (internal router leg)
>     -    src_ip=`ip_to_hex 192 168 1 2`
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -    # ARP request packet to expect at outside1
>     -
>     #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -    # Send ARP reply from outside1 back to the router
>     -    # XXX: note, we could avoid this if we plug this port into a
>     netns
>     -    # and setup the IP address into the port, so the kernel would
>     simply reply
>     -    src_mac="000002010203"
>     -    reply_mac="f00000010204"
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -    src_ip=`ip_to_hex 172 16 1 1`
>     -
>     arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
>     -
>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>     -
>     -    OVS_WAIT_UNTIL([
>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>     table=66 | \
>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>     -    ])
>     -
>     -    # Packet to Expect at ext1 chassis, outside1 port
>     -    src_mac="000002010203"
>     -    dst_mac="f00000010204"
>     -    src_ip=`ip_to_hex 192 168 1 2`
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -
>     expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -    echo $expected > ext1-vif1.expected
>     -
>     exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>     -
>     -    if test $backup_vswitchd_dead != 1; then
>     -        # Reset the file only if vswitchd in backup gw is alive
>     -        as $backup_gw reset_pcap_file br-phys_n1
>     $backup_gw/br-phys_n1
>     -    fi
>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>     -
>     -    # Resend packet from foo1 to outside1
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -    sleep 1
>     -
>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap  > packets
>     -    cat packets | grep $expected > exp
>     -    # Its possible that $active_gw/br-phys_n1-tx.pcap may have
>     received multiple
>     -    # garp packets. So consider only the first packet.
>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>     -    AT_CHECK([cat exp], [0], [expout])
>     -    rm -f expout
>     -    if test $backup_vswitchd_dead != 1; then
>     -        # Check for backup gw only if vswitchd is alive
>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap  > packets
>     -        AT_CHECK([grep $expected packets | sort], [0], [])
>     -    fi
>     -}
>     -
>     -test_ip_packet gw1 gw2 0
>     -
>     -ovn-nbctl --timeout=3 --wait=hv \
>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>     -                                     chassis_name=gw1 \
>     -                                     priority=10 -- \
>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>     -                                     chassis_name=gw2 \
>     -                                     priority=20 -- \
>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -test_ip_packet gw2 gw1 0
>     -
>     -# Get the claim count of both gw1 and gw2.
>     -gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log |
>     wc -l`
>     -gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log |
>     wc -l`
>     -
>     -# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
>     -as gw2
>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>     -
>     -# gw1 should claim the cr-alice and the claim count of gw1 should be
>     -# incremented by 1.
>     -gw1_claim_ct=$((gw1_claim_ct+1))
>     -
>     -OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
>     -| grep -c "cr-alice: Claiming"`])
>     -
>     -AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
>     -grep -c "cr-alice: Claiming"`])
>     -
>     -test_ip_packet gw1 gw2 1
>     -
>     -as gw2
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>     -
>     -OVN_CLEANUP([hv1],[gw1],[ext1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA
>     distributed router gateway port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add gw1
>     -as gw1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -sim_add gw2
>     -as gw2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.4
>     -
>     -sim_add ext1
>     -as ext1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -# 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
>     -
>     -ovn-nbctl create Logical_Router name=R0
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add join
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add outside
>     -
>     -#Connect foo to R0
>     -ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
>     -    type=router options:router-port=R0-foo \
>     -    -- lsp-set-addresses foo-R0 router
>     -
>     -#Connect R0 to join
>     -ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
>     <http://100.60.1.1/24>
>     -ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port join-R0 \
>     -    type=router options:router-port=R0-join \
>     -    -- lsp-set-addresses join-R0 router
>     -
>     -#Connect join to R1
>     -ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
>     <http://100.60.1.2/24>
>     -ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port join-R1 \
>     -    type=router options:router-port=R1-join \
>     -    -- lsp-set-addresses join-R1 router
>     -
>     -#add route rules
>     -ovn-nbctl lr-route-add R0 0.0.0.0/0 <http://0.0.0.0/0> 100.60.1.2
>     -ovn-nbctl lr-route-add R1 192.168.0.0/16 <http://192.168.0.0/16>
>     100.60.1.1
>     -
>     -# Connect alice to R1 as distributed router gateway port on gw1
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -
>     -ovn-nbctl \
>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>     -                                     chassis_name=gw1 \
>     -                                     priority=20 -- \
>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>     -                                     chassis_name=gw2 \
>     -                                     priority=10 -- \
>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port outside1 in outside
>     -ovn-nbctl lsp-add outside outside1 \
>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# Create localnet port in alice
>     -ovn-nbctl lsp-add alice ln-alice
>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>     -ovn-nbctl lsp-set-type ln-alice localnet
>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>     -# mapping to the external network, is the one generating packets
>     -as gw1 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -as gw2 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -as ext1 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>     -
>     -# hv1 should be in 'ref_chassis' of the ha_chasssi_group as logical
>     -# switch 'foo' can reach the router 'R1' (which has gw router port)
>     -# via foo1 -> foo -> R0 -> join -> R1
>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="hv1"`
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$hv1_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 2
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -test_ip_packet()
>     -{
>     -    local active_gw=$1
>     -    local backup_gw=$2
>     -
>     -    # Send ip packet between foo1 and outside1
>     -    src_mac="f00000010203" # foo1 mac
>     -    dst_mac="000001010203" # foo-R0 mac (internal router leg)
>     -    src_ip=`ip_to_hex 192 168 1 2`
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -    # ARP request packet to expect at outside1
>     -
>     #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -    # Send ARP reply from outside1 back to the router
>     -    # XXX: note, we could avoid this if we plug this port into a
>     netns
>     -    # and setup the IP address into the port, so the kernel would
>     simply reply
>     -    src_mac="000002010203"
>     -    reply_mac="f00000010204"
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -    src_ip=`ip_to_hex 172 16 1 1`
>     -
>     arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
>     -
>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>     -
>     -    OVS_WAIT_UNTIL([
>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>     table=66 | \
>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>     -    ])
>     -
>     -    # Packet to Expect at ext1 chassis, outside1 port
>     -    src_mac="000002010203"
>     -    dst_mac="f00000010204"
>     -    src_ip=`ip_to_hex 192 168 1 2`
>     -    dst_ip=`ip_to_hex 172 16 1 3`
>     -
>     expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
>     -    echo $expected > ext1-vif1.expected
>     -
>     exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>     -
>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>     -    as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>     -
>     -    # Resend packet from foo1 to outside1
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap  > packets
>     -    cat packets | grep $expected > exp
>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>     -    AT_CHECK([cat exp], [0], [expout])
>     -
>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap  > packets
>     -    AT_CHECK([grep $expected packets | sort], [0], [])
>     -}
>     -
>     -test_ip_packet gw1 gw2
>     -
>     -ovn-nbctl --timeout=3 --wait=hv \
>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>     -                                     chassis_name=gw1 \
>     -                                     priority=10 -- \
>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>     -                                     chassis_name=gw2 \
>     -                                     priority=20 -- \
>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -test_ip_packet gw2 gw1
>     -
>     -OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 1 LR with distributed router gateway port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR R1 that has switches foo (192.168.1.0/24
>     <http://192.168.1.0/24>) and
>     -# alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to it. 
>     The logical port
>     -# between R1 and alice has a "redirect-chassis" specified,
>     -# i.e. it is the distributed router gateway port.
>     -# Switch alice also has a localnet port defined.
>     -# An additional switch outside has a localnet port and the
>     -# same subnet as alice (172.16.1.0/24 <http://172.16.1.0/24>).
>     -
>     -# Physical network:
>     -# Three hypervisors hv[123].
>     -# hv1 hosts vif foo1.
>     -# hv2 is the "redirect-chassis" that hosts the distributed
>     -# router gateway port.
>     -# hv3 hosts vif outside1.
>     -# In order to show that connectivity works only through hv2,
>     -# an initial round of tests is run without any bridge-mapping
>     -# defined for the localnet on hv2.  These tests are expected
>     -# to fail.
>     -# Subsequent tests are run after defining the bridge-mapping
>     -# for the localnet on hv2. These tests are expected to succeed.
>     -
>     -# Create three hypervisors and create OVS ports corresponding
>     -# to logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -# 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
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add outside
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect alice to R1 as distributed router gateway port on hv2
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24> \
>     -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port outside1 in outside
>     -ovn-nbctl lsp-add outside outside1 \
>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# Create localnet port in alice
>     -ovn-nbctl lsp-add alice ln-alice
>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>     -ovn-nbctl lsp-set-type ln-alice localnet
>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
>     -as hv1 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -as hv3 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 2
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -ovn-sbctl list chassis
>     -ovn-sbctl list encap
>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>     -ovn-sbctl list Gateway_Chassis
>     -echo "------ Port_Binding chassisredirect -------"
>     -ovn-sbctl find Port_Binding type=chassisredirect
>     -echo "-------------------------------------------"
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -echo "------ hv3 dump ----------"
>     -as hv3 ovs-ofctl show br-int
>     -as hv3 ovs-ofctl dump-flows br-int
>     -echo "--------------------------"
>     -
>     -
>     -# Check that redirect mapping is programmed only on hv2
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep
>     =0x3,metadata=0x1 | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep
>     =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
>     -])
>     -# Check that hv1 sends chassisredirect port traffic to hv2
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep
>     =0x3,metadata=0x1 | grep output | wc -l], [0], [1
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep
>     =0x3,metadata=0x1 | wc -l], [0], [0
>     -])
>     -# Check that arp reply on distributed gateway port is only
>     programmed on hv2
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep
>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep
>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
>     -])
>     -
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -
>     -: > hv2-vif1.expected
>     -: > hv3-vif1.expected
>     -
>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>     -#
>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>     provided, then
>     -# it should be the hardware address of the target to expect to
>     receive in an
>     -# ARP reply; otherwise no reply is expected.
>     -#
>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>     -# SHA and REPLY_HA are each 12 hex digits.
>     -# SPA and TPA are each 8 hex digits.
>     -test_arp() {
>     -    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
>     -    local
>     request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>     $request
>     -
>     -    if test X$reply_ha != X; then
>     -        # Expect to receive the reply, if any.
>     -        local
>     reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>     -        echo $reply >> hv${hv}-vif$inport.expected
>     -    fi
>     -}
>     -
>     -rtr_ip=$(ip_to_hex 172 16 1 1)
>     -foo_ip=$(ip_to_hex 192 168 1 2)
>     -outside_ip=$(ip_to_hex 172 16 1 3)
>     -
>     -echo $rtr_ip
>     -echo $foo_ip
>     -echo $outside_ip
>     -
>     -# ARP for router IP address from outside1, no response expected
>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip
>     -
>     -# Now check the packets actually received against the ones expected.
>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>     -
>     -# Send ip packet between foo1 and outside1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 3`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -# Now check the packets actually received against the ones expected.
>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>     -
>     -# Now add bridge-mappings on hv2, which should make everything work
>     -as hv2 ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -# Wait until the patch ports are created in hv2 to connect br-int
>     to br-phys
>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>     -grep "Port patch-br-int-to-ln-alice" | wc -l`])
>     -
>     -# ARP for router IP address from outside1
>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
>     -
>     -# hv3-vif1.expected should also have the gw router port garp packet.
>     -exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
>     -echo $exp_gw_ip_garp >> hv3-vif1.expected
>     -
>     -# Now check the packets actually received against the ones expected.
>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>     -
>     -# Send ip packet between foo1 and outside1
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 172 16 1 3`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -# Packet to Expect at outside1
>     -src_mac="000002010203"
>     -dst_mac="f00000010204"
>     -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -echo "------ hv1 dump ----------"
>     -as hv1 ovs-ofctl show br-int
>     -as hv1 ovs-ofctl dump-flows br-int
>     -echo "------ hv2 dump ----------"
>     -as hv2 ovs-ofctl show br-int
>     -as hv2 ovs-ofctl dump-flows br-int
>     -echo "------ hv3 dump ----------"
>     -as hv3 ovs-ofctl show br-int
>     -as hv3 ovs-ofctl dump-flows br-int
>     -echo "----------------------------"
>     -
>     -echo $expected >> hv3-vif1.expected
>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>     -
>     -#Check ovn-trace over "chassisredirect" port
>     -AT_CAPTURE_FILE([trace])
>     -ovn_trace () {
>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>     -}
>     -
>     -echo 'ip.ttl--;' > expout
>     -echo 'eth.src = 00:00:02:01:02:03;' >> expout
>     -echo 'eth.dst = f0:00:00:01:02:04;' >> expout
>     -echo 'output("ln-alice");' >> expout
>     -AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src ==
>     f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src ==
>     192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0],
>     [expout])
>     -
>     -# Create logical port alice1 in alice on hv1
>     -as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
>     -
>     -# Create logical port foo2 in foo on hv2
>     -as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=foo2 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovn-nbctl lsp-add foo foo2 \
>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -: > hv1-vif2.expected
>     -
>     -# Send ip packet between alice1 and foo2
>     -src_mac="f00000010205"
>     -dst_mac="000002010203"
>     -src_ip=`ip_to_hex 172 16 1 4`
>     -dst_ip=`ip_to_hex 192 168 1 3`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>     -
>     -# Packet to Expect at foo2
>     -src_mac="000001010203"
>     -dst_mac="f00000010206"
>     -src_ip=`ip_to_hex 172 16 1 4`
>     -dst_ip=`ip_to_hex 192 168 1 3`
>     -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
>     -
>     -echo $expected >> hv2-vif1.expected
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
>     -
>     -AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding
>     logical_port=cr-alice | wc -l], [0], [1
>     -])
>     -
>     -ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice
>     options redirect-chassis
>     -
>     -AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc
>     -l], [0], [0
>     -])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed
>     router])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -# Create logical switches
>     -ovn-nbctl ls-add ls0
>     -ovn-nbctl ls-add ls1
>     -# Create distributed router
>     -ovn-nbctl create Logical_Router name=lr0
>     -# Add distributed gateway port to distributed router
>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>     <http://192.168.0.1/24> \
>     -    -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>     -    type=router options:router-port=lrp0 addresses="router"
>     -# Add router port to ls1
>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>     <http://10.0.0.1/24>
>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>     -    type=router options:router-port=lrp1 addresses="router"
>     -# Add logical ports for NAT rules
>     -ovn-nbctl lsp-add ls1 foo1 \
>     --- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
>     -ovn-nbctl lsp-add ls1 foo2 \
>     --- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
>     -# Add nat-addresses option
>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="router"
>     -# Add NAT rules
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>     <http://10.0.0.0/24>])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3
>     10.0.0.3 foo1 f0:00:00:00:00:03])
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4
>     10.0.0.4 foo2 f0:00:00:00:00:04])
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -# Initially test with no bridge-mapping on hv2, expect to receive
>     no packets
>     -
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -# Initially test with no bridge-mapping on hv3
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port
>     network_name=physnet1])
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 2
>     -
>     -# Expect no packets when hv2 bridge-mapping is not present
>     -: > packets
>     -OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
>     -
>     -# Add bridge-mapping on hv2
>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -
>     -# Wait until the patch ports are created in hv2 to connect br-int
>     to br-phys
>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>     -
>     -# Wait for packets to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
>     -echo $expected > expout
>     -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
>     -echo $expected >> expout
>     -AT_CHECK([sort packets], [0], [expout])
>     -sort packets | cat
>     -
>     -# Temporarily remove nat-addresses option to avoid race conditions
>     -# due to GARP backoff
>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses=""
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>     -
>     -# Add OVS ports for foo1 and foo2 on hv3
>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>     -    set interface hv3-vif1 external-ids:iface-id=foo1 \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv3-vif2 -- \
>     -    set interface hv3-vif2 external-ids:iface-id=foo2 \
>     -    ofport-request=2
>     -
>     -# Add bridge-mapping on hv3
>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -
>     -# Wait until the patch ports are created in hv3 to connect br-int
>     to br-phys
>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>     -
>     -# Re-add nat-addresses option
>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="router"
>     -
>     -# Wait for packets to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>     -garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
>     -echo $garp_1 > expout
>     -garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
>     -echo $garp_2 >> expout
>     -
>     -cat packets | grep $garp_1 | head -1 > exp
>     -cat packets | grep $garp_2 | head -1 >> exp
>     -AT_CHECK([cat exp], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -# VLAN traffic for external network redirected through
>     distributed router
>     -# gateway port should use vlans(i.e input network vlan tag)
>     across hypervisors
>     -# instead of tunneling.
>     -AT_SETUP([ovn -- vlan traffic for external network with
>     distributed router gateway port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# # One LR R1 that has switches foo (192.168.1.0/24
>     <http://192.168.1.0/24>) and
>     -# # alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>     it.  The logical port
>     -# # between R1 and alice has a "redirect-chassis" specified,
>     -# # i.e. it is the distributed router gateway port(172.16.1.6).
>     -# # Switch alice also has a localnet port defined.
>     -# # An additional switch outside has the same subnet as alice
>     -# # (172.16.1.0/24 <http://172.16.1.0/24>), a localnet port and
>     nexthop port(172.16.1.1)
>     -# # which will receive the packet destined for external network
>     -# # (i.e 8.8.8.8 as destination ip).
>     -
>     -# Physical network:
>     -# # Four hypervisors hv[1234].
>     -# # hv1 hosts vif foo1.
>     -# # hv2 is the "redirect-chassis" that hosts the distributed
>     router gateway port.
>     -# # Later to test GARPs for the router port - foo, hv2 and hv4
>     are added to the ha_chassis_group
>     -# # hv3 hosts nexthop port vif outside1.
>     -# # All other tests connect hypervisors to network n1 through
>     br-phys for tunneling.
>     -# # But in this test, hv1 won't connect to n1(and no br-phys in
>     hv1), and
>     -# # in order to show vlans(instead of tunneling) used between hv1
>     and hv2,
>     -# # a new network n2 created and hv1 and hv2 connected to this
>     network through br-ex.
>     -# # hv2 and hv3 are still connected to n1 network through br-phys.
>     -net_add n1
>     -
>     -# We are not calling ovn_attach for hv1, to avoid adding br-phys.
>     -# Tunneling won't work in hv1 as ovn-encap-ip is not added to any
>     bridge in hv1
>     -sim_add hv1
>     -as hv1
>     -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,vxlan \
>     -    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
>     -    -- add-br br-int \
>     -    -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true \
>     -    -- set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=public:br-ex
>     -
>     -start_daemon ovn-controller
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>     -
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings="phys:br-phys"
>     -
>     -sim_add hv4
>     -as hv4
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.4
>     -ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>     -
>     -# Create network n2 for vlan connectivity between hv1 and hv2
>     -net_add n2
>     -
>     -as hv1
>     -ovs-vsctl add-br br-ex
>     -net_attach n2 br-ex
>     -
>     -as hv2
>     -ovs-vsctl add-br br-ex
>     -net_attach n2 br-ex
>     -
>     -as hv4
>     -ovs-vsctl add-br br-ex
>     -net_attach n2 br-ex
>     -
>     -OVN_POPULATE_ARP
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add outside
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect alice to R1 as distributed router gateway port
>     (172.16.1.6) on hv2
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24
>     <http://172.16.1.6/24> \
>     -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router \
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port outside1 in outside, which is a nexthop address
>     -# for 172.16.1.0/24 <http://172.16.1.0/24>
>     -ovn-nbctl lsp-add outside outside1 \
>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
>     -
>     -# Set default gateway (nexthop) to 172.16.1.1
>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>"
>     172.16.1.1 alice
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24
>     <http://192.168.1.1/24>])
>     -ovn-nbctl set Logical_Switch_Port rp-alice
>     options:nat-addresses=router
>     -
>     -ovn-nbctl lsp-add foo ln-foo
>     -ovn-nbctl lsp-set-addresses ln-foo unknown
>     -ovn-nbctl lsp-set-options ln-foo network_name=public
>     -ovn-nbctl lsp-set-type ln-foo localnet
>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
>     -
>     -# Create localnet port in alice
>     -ovn-nbctl lsp-add alice ln-alice
>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>     -ovn-nbctl lsp-set-type ln-alice localnet
>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -# Check that there is a logical flow in logical switch foo's pipeline
>     -# to set the outport to rp-foo (which is expected).
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>     ls_in_l2_lkup | \
>     -grep rp-foo | grep -v is_chassis_resident | wc -l`])
>     -
>     -# Set the option 'reside-on-redirect-chassis' for foo
>     -ovn-nbctl set logical_router_port foo
>     options:reside-on-redirect-chassis=true
>     -# Check that there is a logical flow in logical switch foo's pipeline
>     -# to set the outport to rp-foo with the condition
>     is_chassis_redirect.
>     -ovn-sbctl dump-flows foo
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>     ls_in_l2_lkup | \
>     -grep rp-foo | grep is_chassis_resident | wc -l`])
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list nat
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -ovn-sbctl list chassis
>     -echo "---------------------"
>     -
>     -for chassis in hv1 hv2 hv3; do
>     -    as $chassis
>     -    echo "------ $chassis dump ----------"
>     -    ovs-vsctl show br-int
>     -    ovs-ofctl show br-int
>     -    ovs-ofctl dump-flows br-int
>     -    echo "--------------------------"
>     -done
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -foo1_ip=$(ip_to_hex 192 168 1 2)
>     -gw_ip=$(ip_to_hex 172 16 1 6)
>     -dst_ip=$(ip_to_hex 8 8 8 8)
>     -nexthop_ip=$(ip_to_hex 172 16 1 1)
>     -
>     -foo1_mac="f00000010203"
>     -foo_mac="000001010203"
>     -gw_mac="000002010203"
>     -nexthop_mac="f00000010204"
>     -
>     -# Send ip packet from foo1 to 8.8.8.8
>     -src_mac="f00000010203"
>     -dst_mac="000001010203"
>     -packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
>     -
>     -# Wait for GARPs announcing gw IP to arrive
>     -OVS_WAIT_UNTIL([
>     -    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>     -    ])
>     -
>     -# VLAN tagged packet with router port(192.168.1.1) MAC as
>     destination MAC
>     -# is expected on bridge connecting hv1 and hv2
>     -expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
>     -echo $expected > hv1-br-ex_n2.expected
>     -
>     -# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
>     -# As connection tracking not enabled for this test, snat can't be
>     done on the packet.
>     -# We still see foo1 as the source ip address. But source
>     mac(gateway MAC) and
>     -# dest mac(nexthop mac) are properly configured.
>     -expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000
>     -echo $expected > hv3-vif1.expected
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
>     -as hv3 reset_pcap_file hv3-vif1 hv3/vif1
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -sleep 2
>     -
>     -# On hv1, table 32 check that no packet goes via the tunnel port
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
>     -| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
>     -]])
>     -
>     -ip_packet() {
>     -    grep "1010203f00000010203"
>     -}
>     -
>     -# Check vlan tagged packet on the bridge connecting hv1 and hv2
>     with the
>     -# foo1's mac.
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
>     -cat hv1-br-ex_n2.expected > expout
>     -AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
>     -
>     -# Check expected packet on nexthop interface
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
>     -cat hv3-vif1.expected > expout
>     -AT_CHECK([sort hv3-vif1], [0], [expout])
>     -
>     -# Test the GARP for the router port ip - 192.168.1.1
>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>     -
>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>     -
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
>     -
>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>     ha_chassis_group name=hagrp1`
>     -ovn-nbctl remove logical_router_port alice options redirect-chassis
>     -ovn-nbctl --wait=sb set logical_router_port alice
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -# When hv2 claims the gw router port cr-alice, it should send out
>     -# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
>     -
>     -# foo1 (on hv1) should receive GARP without VLAN tag
>     -exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101"
>     -echo $exp_garp_on_foo1 > foo1.expout
>     -
>     -# ovn-controller on hv2 should send garp with VLAN tag
>     -sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101"
>     -
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>     -# Wait until we receive atleast 1 packet
>     -OVS_WAIT_UNTIL([test 1=`$PYTHON
>     "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-ex_n2-tx.pcap | wc -l`])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-ex_n2-tx.pcap | head -1 > packets
>     -echo $sent_garp > expout
>     -AT_CHECK([cat packets], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv4/br-ex_n2-tx.pcap > empty
>     -AT_CHECK([cat empty], [0], [])
>     -
>     -# Make hv4 master
>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
>     -
>     -# Wait till cr-alice is claimed by hv4
>     -hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=hv4)
>     -# check that the chassis redirect port has been claimed by the
>     gw1 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -# Reset the pcap file for hv2/br-ex_n2. From now on
>     ovn-controller in hv2
>     -# should not send GARPs for the router ports.
>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>     -
>     -echo $sent_garp > br-ex_n2.expout
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>     -OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
>     -
>     -sleep 2
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-ex_n2-tx.pcap > empty
>     -AT_CHECK([cat empty], [0], [])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
>     -AT_KEYWORDS([ovn-nd_ra])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# In this test case we create 1 lswitch with 3 VIF ports attached,
>     -# and a lrouter connected to the lswitch.
>     -# We generate the Router solicitation packet and verify the
>     Router Advertisement
>     -# reply packet from the ovn-controller.
>     -
>     -# Create hypervisor and logical switch lsw0, logical router lr0,
>     attach lsw0
>     -# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode
>     column to
>     -# 'slaac' to allow lrp0 send RA for SLAAC mode.
>     -ovn-nbctl ls-add lsw0
>     -ovn-nbctl lr-add lr0
>     -ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
>     -ovn-nbctl set Logical_Router_Port lrp0
>     ipv6_ra_configs:address_mode="slaac"
>     -ovn-nbctl \
>     -    -- lsp-add lsw0 lsp0 \
>     -    -- set Logical_Switch_Port lsp0 type=router \
>     -                     options:router-port=lrp0 \
>     -                     addresses='"fa:16:3e:00:00:01
>     fdad:1234:5678::1"'
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -ovn-nbctl lsp-add lsw0 lp1
>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
>     fdad:1234:5678:0:f816:3eff:fe:2"
>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
>     fdad:1234:5678:0:f816:3eff:fe:2"
>     -
>     -ovn-nbctl lsp-add lsw0 lp2
>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
>     fdad:1234:5678:0:f816:3eff:fe:3"
>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
>     fdad:1234:5678:0:f816:3eff:fe:3"
>     -
>     -ovn-nbctl lsp-add lsw0 lp3
>     -ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
>     fdad:1234:5678:0:f816:3eff:fe:4"
>     -ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
>     fdad:1234:5678:0:f816:3eff:fe:4"
>     -
>     -# Add ACL rule for ICMPv6 on lsw0
>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>     icmp6'  allow-related
>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>     icmp6'  allow-related
>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 &&
>     icmp6'  allow-related
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>     -    set interface hv1-vif3 external-ids:iface-id=lp3 \
>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>     -    ofport-request=3
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -# Make sure that ovn-controller has installed the corresponding
>     OF Flow.
>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>     -
>     -# This shell function sends a Router Solicitation packet.
>     -# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
>     -test_ipv6_ra() {
>     -    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
>     prefix_opt=$6
>     -    local
>     request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac}
>     -
>     -    local len=24
>     -    local mtu_opt=""
>     -    if test $mtu != 0; then
>     -        len=`expr $len + 8`
>     -        mtu_opt=05010000${mtu}
>     -    fi
>     -
>     -    if test ${#prefix_opt} != 0; then
>     - prefix_opt=${prefix_opt}fdad1234567800000000000000000000
>     -        len=`expr $len + ${#prefix_opt} / 2`
>     -    fi
>     -
>     -    len=$(printf "%x" $len)
>     -    local lrp_mac=fa163e000001
>     -    local lrp_lla=fe80000000000000f8163efffe000001
>     -    local
>     reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt}
>     -    echo $reply >> $inport.expected
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
>     -}
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>     -
>     -# MTU is not set and the address mode is set to slaac
>     -addr_mode=00
>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>     -src_mac=fa163e000002
>     -src_lla=fe80000000000000f8163efffe000002
>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
>     $default_prefix_option_config
>     -
>     -# NXT_RESUME should be 1.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap  > 1.packets
>     -
>     -cat 1.expected | cut -c -112 > expout
>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum.
>     -cat 1.expected | cut -c 117- > expout
>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>     -
>     -rm -f *.expected
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -reset_pcap_file hv1-vif3 hv1/vif3
>     -
>     -# Set the MTU to 1500
>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>     ipv6_ra_configs:mtu=1500
>     -
>     -# Make sure that ovn-controller has installed the corresponding
>     OF Flow.
>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>     -
>     -addr_mode=00
>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>     -src_mac=fa163e000003
>     -src_lla=fe80000000000000f8163efffe000003
>     -mtu=000005dc
>     -
>     -test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
>     $default_prefix_option_config
>     -
>     -# NXT_RESUME should be 2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap  > 2.packets
>     -
>     -cat 2.expected | cut -c -112 > expout
>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum.
>     -cat 2.expected | cut -c 117- > expout
>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>     -
>     -rm -f *.expected
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -reset_pcap_file hv1-vif3 hv1/vif3
>     -
>     -# Set the address mode to dhcpv6_stateful
>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>     -# Make sure that ovn-controller has installed the corresponding
>     OF Flow.
>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>     -
>     -addr_mode=80
>     -default_prefix_option_config=03044080ffffffffffffffff00000000
>     -src_mac=fa163e000004
>     -src_lla=fe80000000000000f8163efffe000004
>     -mtu=000005dc
>     -
>     -test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
>     $default_prefix_option_config
>     -
>     -# NXT_RESUME should be 3.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif3-tx.pcap  > 3.packets
>     -
>     -cat 3.expected | cut -c -112 > expout
>     -AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum.
>     -cat 3.expected | cut -c 117- > expout
>     -AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
>     -
>     -rm -f *.expected
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -reset_pcap_file hv1-vif3 hv1/vif3
>     -
>     -# Set the address mode to dhcpv6_stateless
>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>     -# Make sure that ovn-controller has installed the corresponding
>     OF Flow.
>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>     -
>     -addr_mode=40
>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>     -src_mac=fa163e000002
>     -src_lla=fe80000000000000f8163efffe000002
>     -mtu=000005dc
>     -
>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>     $default_prefix_option_config
>     -
>     -# NXT_RESUME should be 4.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap  > 1.packets
>     -
>     -cat 1.expected | cut -c -112 > expout
>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum.
>     -cat 1.expected | cut -c 117- > expout
>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>     -
>     -rm -f *.expected
>     -reset_pcap_file hv1-vif1 hv1/vif1
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -reset_pcap_file hv1-vif3 hv1/vif3
>     -
>     -# Set the address mode to invalid.
>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>     ipv6_ra_configs:address_mode=invalid
>     -# Make sure that ovn-controller has not installed any OF Flow for
>     IPv6 ND RA.
>     -OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int |
>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>     -
>     -addr_mode=40
>     -default_prefix_option_config=""
>     -src_mac=fa163e000002
>     -src_lla=fe80000000000000f8163efffe000002
>     -mtu=000005dc
>     -
>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>     $default_prefix_option_config
>     -
>     -# NXT_RESUME should be 4 only.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif1-tx.pcap  > 1.packets
>     -AT_CHECK([cat 1.packets], [0], [])
>     -
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- /32 router IP address])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# 2 LS 'foo' and 'alice' connected via router R1.
>     -# R1 connects to 'alice' with a /32 IP address. We use static
>     routes and
>     -# nexthop to push traffic to a logical port in switch 'alice'
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>     type=router \
>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>     -
>     -# Connect alice to R1.
>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
>     <http://172.16.1.1/32>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -          type=router options:router-port=alice
>     addresses=\"00:00:00:01:02:04\"
>     -
>     -# Create logical port foo1 in foo
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical port alice1 in alice
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
>     -
>     -#install default route in R1 to use alice1's IP address as nexthop
>     -ovn-nbctl lr-route-add R1 0.0.0.0/0 <http://0.0.0.0/0> 10.0.0.2 alice
>     -
>     -# Create two hypervisor and create OVS ports corresponding to
>     logical ports.
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -
>     -# 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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -# Send ip packets between foo1 and alice1
>     -src_mac="f00000010203"
>     -dst_mac="000000010203"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 10 0 0 2`
>     -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -
>     -# Send the first packet to trigger a ARP response and population of
>     -# mac_bindings table.
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" |
>     wc -l` -gt 0])
>     -ovn-nbctl --wait=hv sync
>     -
>     -# Packet to Expect at 'alice1'
>     -src_mac="000000010204"
>     -dst_mac="f00000010204"
>     -src_ip=`ip_to_hex 192 168 1 2`
>     -dst_ip=`ip_to_hex 10 0 0 2`
>     -echo
>     "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000"
>     > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -# Add localport to the switch
>     -ovn-nbctl lsp-add ls1 lp01
>     -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
>     -ovn-nbctl lsp-set-type lp01 localport
>     -
>     -net_add n1
>     -
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -    ovs-vsctl add-port br-int vif01 -- \
>     -        set Interface vif01 external-ids:iface-id=lp01 \
>     - options:tx_pcap=hv${i}/vif01-tx.pcap \
>     - options:rxq_pcap=hv${i}/vif01-rx.pcap \
>     -                              ofport-request=${i}0
>     -
>     -    ovs-vsctl add-port br-int vif${i}1 -- \
>     -        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
>     - options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
>     - options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
>     -                              ofport-request=${i}1
>     -
>     -    ovn-nbctl lsp-add ls1 lp${i}1
>     -    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
>     -    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
>     -
>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup])
>     -done
>     -
>     -ovn-nbctl --wait=sb sync
>     -ovn-sbctl dump-flows
>     -
>     -OVN_POPULATE_ARP
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    echo hv${1%?}
>     -}
>     -#
>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is
>     specified as
>     -# logical switch port numbers, e.g. 11 for vif11.
>     -#
>     -# EOUT is the end-to-end output port, that is, where the packet
>     will end up
>     -# after possibly bouncing through one or more localnet ports. 
>     LOUT is the
>     -# logical output port, which might be a localnet port, as seen by
>     ovn-trace
>     -# (which doesn't know what localnet ports are connected to and
>     therefore can't
>     -# figure out the end-to-end answer).
>     -#
>     -# DEFHV is the default hypervisor from where the packet is going
>     to be sent
>     -# if the source port is a localport.
>     -for i in 1 2; do
>     -    for j in 0 1; do
>     -        : > $i$j.expected
>     -    done
>     -done
>     -test_packet() {
>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
>     -    echo "$@"
>     -
>     -    # First try tracing the packet.
>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>     eth.src==$src && eth.type==0x$eth"
>     -    if test $lout != drop; then
>     -        echo "output(\"$lout\");"
>     -    fi > expout
>     -    AT_CAPTURE_FILE([trace])
>     -    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed
>     '1,/Minimal trace/d'], [0], [expout])
>     -
>     -    # Then actually send a packet, for an end-to-end test.
>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>     -    hv=`vif_to_hv $inport`
>     -    # If hypervisor 0 (localport) use the defhv parameter
>     -    if test $hv = hv0; then
>     -        hv=$defhv
>     -    fi
>     -    vif=vif$inport
>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>     -    if test $eout != drop; then
>     -        echo $packet >> ${eout#lp}.expected
>     -    fi
>     -}
>     -
>     -
>     -# lp11 and lp21 are on different hypervisors
>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>     -
>     -# Both VIFs should be able to reach the localport on their own HV
>     -test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
>     -test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
>     -
>     -# Packet sent from localport on same hv should reach the vif
>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 lp11 hv1
>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 lp21 hv2
>     -
>     -# Packet sent from localport on different hv should be dropped
>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop lp21 hv1
>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop lp11 hv2
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2; do
>     -    for j in 0 1; do
>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>     -    done
>     -done
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -# create gateways with external network connectivity
>     -
>     -for i in 1 2; do
>     -    sim_add gw$i
>     -    as gw$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -    ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -done
>     -
>     -ovn-nbctl ls-add inside
>     -ovn-nbctl ls-add outside
>     -
>     -# create hypervisors with a vif port each to an internal network
>     -
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.1$i
>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>     -        ofport-request=1
>     -
>     -        ovn-nbctl lsp-add inside inside$i \
>     -            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i
>     192.168.1.10$i"
>     -
>     -done
>     -
>     -OVN_POPULATE_ARP
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -# Connect inside to R1
>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>     rp-inside \
>     -    type=router options:router-port=inside \
>     -    -- lsp-set-addresses rp-inside router
>     -
>     -# Connect outside to R1 as distributed router gateway port on gw1+gw2
>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>     <http://192.168.0.101/24>
>     -
>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>     -- \
>     -          --id=@gc1 create Gateway_Chassis \
>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>     -- \
>     -          set Logical_Router_Port outside
>     'gateway_chassis=[@gc0,@gc1]'
>     -
>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>     rp-outside \
>     -    type=router options:router-port=outside \
>     -    -- lsp-set-addresses rp-outside router
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -echo "---------NB dump-----"
>     -ovn-nbctl show
>     -echo "---------------------"
>     -ovn-nbctl list logical_router
>     -echo "---------------------"
>     -ovn-nbctl list logical_router_port
>     -echo "---------------------"
>     -
>     -echo "---------SB dump-----"
>     -ovn-sbctl list datapath_binding
>     -echo "---------------------"
>     -ovn-sbctl list port_binding
>     -echo "---------------------"
>     -ovn-sbctl dump-flows
>     -echo "---------------------"
>     -ovn-sbctl list chassis
>     -ovn-sbctl list encap
>     -echo "---------------------"
>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>     -ovn-sbctl list Gateway_Chassis
>     -echo "------ Port_Binding chassisredirect -------"
>     -ovn-sbctl find Port_Binding type=chassisredirect
>     -echo "-------------------------------------------"
>     -
>     -# There should be one ha_chassis_group with the name "outside"
>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>     -ha_chassis_group name="outside"`
>     -
>     -AT_CHECK([test $ha_chassi_grp_name = outside])
>     -
>     -# There should be 2 ha_chassis rows in SB DB.
>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
>     -grep -v chassis-name | awk '{print $3}' \
>     -| grep '-' | wc -l ], [0], [2
>     -])
>     -
>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>     -# Trim the spaces.
>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>     -
>     -ha_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>     -do
>     -    ha_ch_list="$ha_ch_list $i"
>     -done
>     -
>     -# Trim the spaces.
>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>     -
>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>     -
>     -for chassis in gw1 gw2 hv1 hv2; do
>     -    as $chassis
>     -    echo "------ $chassis dump ----------"
>     -    ovs-ofctl show br-int
>     -    ovs-ofctl dump-flows br-int
>     -    echo "--------------------------"
>     -done
>     -bfd_dump() {
>     -    for chassis in gw1 gw2 hv1 hv2; do
>     -        as $chassis
>     -        echo "------ $chassis dump (BFD)----"
>     -        echo "BFD (from $chassis):"
>     -        # dump BFD config and status to the other chassis
>     -        for chassis2 in gw1 gw2 hv1 hv2; do
>     -            if [[ "$chassis" != "$chassis2" ]]; then
>     -                echo " -> $chassis2:"
>     -                echo "   $(ovs-vsctl --bare --columns
>     bfd,bfd_status find Interface name=ovn-$chassis2-0)"
>     -            fi
>     -        done
>     -        echo "--------------------------"
>     -    done
>     -}
>     -
>     -bfd_dump
>     -
>     -hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>     Interface name=ovn-gw1-0)
>     -hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>     Interface name=ovn-gw2-0)
>     -hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>     Interface name=ovn-gw1-0)
>     -hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>     Interface name=ovn-gw2-0)
>     -
>     -echo $hv1_gw1_ofport
>     -echo $hv1_gw2_ofport
>     -echo $hv2_gw1_ofport
>     -echo $hv2_gw2_ofport
>     -
>     -echo "--- hv1 ---"
>     -as hv1 ovs-ofctl dump-flows br-int table=32
>     -
>     -echo "--- hv2 ---"
>     -as hv2 ovs-ofctl dump-flows br-int table=32
>     -
>     -gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw1)
>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
>     -
>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw1
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# make sure ARP responder flows for outside router port reside on
>     gw1 too
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>     -]])
>     -
>     -# check that the chassis redirect port has been claimed by the
>     gw1 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="hv1"`
>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="hv2"`
>     -
>     -exp_ref_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>     -do
>     -    if test $i = $hv1_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    elif test $i = $hv2_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    fi
>     -done
>     -
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -
>     -# at this point, we invert the priority of the gw chassis between
>     gw1 and gw2
>     -
>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>     -                    name=outside_gw1 chassis_name=gw1 priority=10
>     -- \
>     -          --id=@gc1 create Gateway_Chassis \
>     -                    name=outside_gw2 chassis_name=gw2 priority=20
>     -- \
>     -          set Logical_Router_Port outside
>     'gateway_chassis=[@gc0,@gc1]'
>     -
>     -
>     -# XXX: Let the change propagate down to the ovn-controllers
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -# we make sure that the hypervisors noticed, and inverted the
>     slave ports
>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -# check that the chassis redirect port has been reclaimed by the
>     gw2 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -# check BFD enablement on tunnel ports from gw1 #########
>     -as gw1
>     -for chassis in gw2 hv1 hv2; do
>     -    echo "checking gw1 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -
>     -
>     -# check BFD enablement on tunnel ports from gw2 ##########
>     -as gw2
>     -for chassis in gw1 hv1 hv2; do
>     -    echo "checking gw2 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -
>     -# check BFD enablement on tunnel ports from hv1 ###########
>     -as hv1
>     -for chassis in gw1 gw2; do
>     -    echo "checking hv1 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -# make sure BFD is not enabled to hv2, we don't need it
>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-hv2-0],[0],
>     -         [[
>     -]])
>     -
>     -
>     -# check BFD enablement on tunnel ports from hv2 ##########
>     -as hv2
>     -for chassis in gw1 gw2; do
>     -    echo "checking hv2 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -# make sure BFD is not enabled to hv1, we don't need it
>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-hv1-0],[0],
>     -         [[
>     -]])
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw2 now
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# disconnect GW2 from the network, GW1 should take over
>     -as gw2
>     -port=${sandbox}_br-phys
>     -as main ovs-vsctl del-port n1 $port
>     -
>     -bfd_dump
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw2 now
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# check that the chassis redirect port has been reclaimed by the
>     gw1 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
>     -as gw2
>     -for chassis in gw1 hv1 hv2; do
>     -    echo "checking gw2 -> $chassis"
>     -    OVS_WAIT_UNTIL([
>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0)
>     -    test "$bfd_cfg" = "enable=true min_rx=2000"
>     -])
>     -done
>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
>     -for chassis in gw1 hv1 hv2; do
>     -    echo "checking gw2 -> $chassis"
>     -    OVS_WAIT_UNTIL([
>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0)
>     -    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
>     -])
>     -done
>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
>     -for chassis in gw1 hv1 hv2; do
>     -    echo "checking gw2 -> $chassis"
>     -    OVS_WAIT_UNTIL([
>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0)
>     -    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
>     -])
>     -done
>     -
>     -# Delete the inside1 vif. The ref_chassis in ha_chassis_group
>     shouldn't have
>     -# reference to hv1.
>     -as hv1 ovs-vsctl del-port hv1-vif1
>     -
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$hv2_ch_uuid" = "$ref_ch_list"])
>     -
>     -# Delete the inside2 vif.
>     -ovn-sbctl show
>     -
>     -echo "Deleting hv2-vif1"
>     -as hv2 ovs-vsctl del-port hv2-vif1
>     -
>     -# ref_chassis of ha_chassis_group should be empty
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     exp_ref_ch_list=""
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# Delete the Gateway_Chassis for lrp - outside
>     -ovn-nbctl clear Logical_Router_Port outside gateway_chassis
>     -
>     -# There shoud be no ha_chassis_group rows in SB DB.
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc -l`])
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>     -
>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>     -ovn-nbctl remove NB_Global . options "bfd-min-tx"
>     -ovn-nbctl remove NB_Global . options "bfd-mult"
>     -
>     -# Now test with HA chassis group instead of Gateway chassis in NB DB
>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>     -
>     -ovn-nbctl list ha_chassis_group
>     -ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>     ha_chassis_group name=hagrp1`
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
>     -
>     -# ovn-northd should not create HA chassis group and HA chassis rows
>     -# unless the HA chassis group in OVN NB DB is associated to
>     -# a logical router port.
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>     -
>     -# Associate hagrp1 to outside logical router port
>     -ovn-nbctl set Logical_Router_Port outside
>     ha_chassis_group=$hagrp1_uuid
>     -
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>     -find ha_chassis_group | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>     chassis | \
>     -grep -v chassis-name | wc -l`])
>     -
>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw1
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# make sure ARP responder flows for outside router port reside on
>     gw1 too
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>     -]])
>     -
>     -# check that the chassis redirect port has been claimed by the
>     gw1 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -# Re add the ovs ports.
>     -for i in 1 2; do
>     -    as hv$i
>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>     -        ofport-request=1
>     -done
>     -
>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="hv1"`
>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>     name="hv2"`
>     -
>     -exp_ref_ch_list=''
>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>     -do
>     -    if test $i = $hv1_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    elif test $i = $hv2_ch_uuid; then
>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>     -    fi
>     -done
>     -
>     -OVS_WAIT_UNTIL(
>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>     ha_chassis_group | sort`
>     -     # Trim the spaces.
>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>     -
>     -# Increase the priority of gw2
>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
>     -
>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>     -| wc -l], [0], [1
>     -])
>     -
>     -# check that the chassis redirect port has been reclaimed by the
>     gw2 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -# check BFD enablement on tunnel ports from gw1 #########
>     -as gw1
>     -for chassis in gw2 hv1 hv2; do
>     -    echo "checking gw1 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -
>     -# check BFD enablement on tunnel ports from gw2 ##########
>     -as gw2
>     -for chassis in gw1 hv1 hv2; do
>     -    echo "checking gw2 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -
>     -# check BFD enablement on tunnel ports from hv1 ###########
>     -as hv1
>     -for chassis in gw1 gw2; do
>     -    echo "checking hv1 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -# make sure BFD is not enabled to hv2, we don't need it
>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-hv2-0],[0],
>     -         [[
>     -]])
>     -
>     -# check BFD enablement on tunnel ports from hv2 ##########
>     -as hv2
>     -for chassis in gw1 gw2; do
>     -    echo "checking hv2 -> $chassis"
>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-$chassis-0],[0],
>     -             [[enable=true
>     -]])
>     -done
>     -# make sure BFD is not enabled to hv1, we don't need it
>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>     name=ovn-hv1-0],[0],
>     -         [[
>     -]])
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw2 now
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# disconnect GW2 from the network, GW1 should take over
>     -as gw2
>     -port=${sandbox}_br-phys
>     -as main ovs-vsctl del-port n1 $port
>     -
>     -bfd_dump
>     -
>     -# make sure that flows for handling the outside router port
>     reside on gw2 now
>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>     -]])
>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>     -]])
>     -
>     -# check that the chassis redirect port has been reclaimed by the
>     gw1 chassis
>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>     Port_Binding \
>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>     -]])
>     -
>     -OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA
>     distributed router])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -ovn-nbctl ls-add ls0
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl create Logical_Router name=lr0
>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
>     <http://192.168.0.100/24>
>     -
>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>     -                    name=outside_gw1 chassis_name=hv2 priority=10
>     -- \
>     -          --id=@gc1 create Gateway_Chassis \
>     -                    name=outside_gw2 chassis_name=hv3 priority=1 -- \
>     -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>     -    type=router options:router-port=lrp0 addresses="router"
>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>     <http://10.0.0.1/24>
>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>     -    type=router options:router-port=lrp1 addresses="router"
>     -
>     -# Add NAT rules
>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24
>     <http://10.0.0.0/24>])
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -
>     -sim_add hv3
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>     -
>     -# Create a localnet port.
>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>     -
>     -# wait for earlier changes to take effect
>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>     -# add nat-addresses option
>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="router"
>     -
>     -# Wait for packets to be received through hv2.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -only_broadcast_from_lrp1() {
>     -    grep "fffffffffffff00000000001"
>     -}
>     -
>     -garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064"
>     -echo $garp > expout
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv1_snoop_tx
>     -echo "packets on hv1-snoopvif:"
>     -cat hv1_snoop_tx
>     -AT_CHECK([sort hv1_snoop_tx], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv2_br_phys_tx
>     -echo "packets on hv2 br-phys tx"
>     -cat hv2_br_phys_tx
>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv3_br_phys_tx
>     -echo "packets on hv3 br-phys tx"
>     -cat hv3_br_phys_tx
>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
>     -
>     -
>     -# at this point, we invert the priority of the gw chassis between
>     hv2 and hv3
>     -
>     -ovn-nbctl --wait=hv \
>     -          --id=@gc0 create Gateway_Chassis \
>     -                    name=outside_gw1 chassis_name=hv2 priority=1 -- \
>     -          --id=@gc1 create Gateway_Chassis \
>     -                    name=outside_gw2 chassis_name=hv3 priority=10
>     -- \
>     -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
>     -
>     -
>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>     -
>     -# Wait for packets to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq >  hv1_snoopvif_tx
>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv3_br_phys_tx
>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv2_br_phys_tx
>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>     -
>     -# change localnet port tag.
>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
>     -
>     -# wait for earlier changes to take effect
>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int
>     table=65 | \
>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>     -])
>     -
>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int
>     table=65 | \
>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>     -])
>     -
>     -# update nat-addresses option
>     -ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
>     -
>     -#Wait until the Port_Binding.nat_addresses is cleared.
>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns
>     nat_addresses find port_binding \
>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>     -
>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>     -
>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>     nat-addresses="router"
>     -
>     -#Wait until the Port_Binding.nat_addresses is set.
>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns
>     nat_addresses find port_binding \
>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>     -
>     -# Wait for packets to be received.
>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064"
>     -echo $garp > expout
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq >  hv1_snoopvif_tx
>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv3_br_phys_tx
>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>     uniq > hv2_br_phys_tx
>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't
>     bounce the master])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -# create two gateways with external network connectivity
>     -for i in 1 2; do
>     -    sim_add gw$i
>     -    as gw$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -    ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -done
>     -
>     -ovn-nbctl ls-add inside
>     -ovn-nbctl ls-add outside
>     -
>     -# create one hypervisors with a vif port the internal network
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.11
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=inside1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovn-nbctl lsp-add inside inside1 \
>     -        -- lsp-set-addresses inside1 "f0:00:00:01:22:01
>     192.168.1.101"
>     -
>     -
>     -OVN_POPULATE_ARP
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -
>     -# Connect inside to R1
>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>     rp-inside \
>     -    type=router options:router-port=inside \
>     -    -- lsp-set-addresses rp-inside router
>     -
>     -# Connect outside to R1 as distributed router gateway port on gw1+gw2
>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>     <http://192.168.0.101/24>
>     -
>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>     -- \
>     -          --id=@gc1 create Gateway_Chassis \
>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>     -- \
>     -          set Logical_Router_Port outside
>     'gateway_chassis=[@gc0,@gc1]'
>     -
>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>     rp-outside \
>     -    type=router options:router-port=outside \
>     -    -- lsp-set-addresses rp-outside router
>     -
>     -# Create localnet port in outside
>     -ovn-nbctl lsp-add outside ln-outside
>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>     -ovn-nbctl lsp-set-type ln-outside localnet
>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -# currently when ovn-controller is restarted, the old entry is
>     deleted
>     -# and a new one is created, which leaves the Gateway_Chassis with
>     -# an empty chassis for a while. NOTE: restarting ovn-controller
>     in tests
>     -# doesn't have the same effect because "name" is conserved, and the
>     -# Chassis entry is not replaced.
>     -
>     -> gw1/ovn-controller.log
>     -
>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
>     -ovn-sbctl destroy Chassis $gw2_chassis
>     -
>     -OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport"
>     gw1/ovn-controller.log`])
>     -
>     -OVN_CLEANUP([gw1],[gw2],[hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
>     -AT_KEYWORDS([ovn-nd_ns for unknown mac])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add sw0_ip6
>     -ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
>     -ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>     -
>     -ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>     -
>     -ovn-nbctl lr-add lr0_ip6
>     -ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01
>     aef0:0:0:0:0:0:0:0/64
>     -ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
>     -ovn-nbctl lsp-set-type lrp0_ip6-attachment router
>     -ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
>     -ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
>     -ovn-nbctl set logical_router_port lrp0_ip6
>     ipv6_ra_configs:address_mode=slaac
>     -
>     -ovn-nbctl ls-add public
>     -ovn-nbctl lsp-add public ln-public
>     -ovn-nbctl lsp-set-addresses ln-public unknown
>     -ovn-nbctl lsp-set-type ln-public localnet
>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>     -
>     -ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
>     -2001:db8:1:0:200:02ff:fe01:0204/64 \
>     --- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
>     -
>     -#install static route
>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>     -ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
>     --- add Logical_Router lr0_ip6 static_routes @lrt
>     -
>     -ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
>     -rp-ip6_public  type=router options:router-port=ip6_public \
>     --- lsp-set-addresses rp-ip6_public router
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
>     -
>     -# There should be 2 Neighbor Advertisement flows for the router port
>     -# aef0:: ip address in logical switch pipeline with action
>     nd_na_router.
>     -AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
>     -grep "nd_na_router" | wc -l], [0], [2
>     -])
>     -
>     -# There should be 4 Neighbor Advertisement flows with action
>     nd_na_router
>     -# in the router pipeline for the router lr0_ip6.
>     -AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
>     -wc -l], [0], [4
>     -])
>     -
>     -cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public |
>     grep _uuid | cut -f2 -d ":"`
>     -
>     -# There is only one chassis.
>     -chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d ":"`
>     -OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding
>     $cr_uuid chassis`])
>     -
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for
>     unknown MAC
>     -# addresses. ovn-controller should generate an IPv6 NS request
>     for IPv6
>     -# packets whose MAC is unknown (in the ARP_REQUEST router
>     pipeline stage.
>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -# This function sends ipv6 packet
>     -test_ipv6() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
>     -
>     -    local
>     packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
>     -    packet=${packet}8000000000000000
>     -
>     -    src_mac=000002010204
>     -
>     expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
>     - expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
>     - expected_packet=${expected_packet}${nd_target}0101${src_mac}
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
>     -    rm -f ipv6_ns.expected
>     -    echo $expected_packet >> ipv6_ns.expected
>     -}
>     -
>     -src_mac=506400000002
>     -dst_mac=00000000af01
>     -src_ip=aef0000000000000526400fffe000002
>     -dst_ip=20010db800010000020002fffe010205
>     -dst_mcast_mac=3333ff010205
>     -mcast_node_ip=ff0200000000000000000001ff010205
>     -nd_target=20010db800010000020002fffe010205
>     -# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
>     -# should be received by the ports attached to br-phys.
>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>     -$mcast_node_ip $nd_target
>     -
>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>     " " -f1)])
>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>     " -f1)])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-phys_n1-tx.pcap | \
>     -trim_zeros > 1.packets
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-phys-tx.pcap | \
>     -trim_zeros > 2.packets
>     -
>     -cat ipv6_ns.expected | cut -c -112 > expout
>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum
>     -cat ipv6_ns.expected | cut -c 117- > expout
>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>     -
>     -# Now send a packet with destination ip other than
>     -# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>     -reset_pcap_file br-phys hv1/br-phys
>     -
>     -src_mac=506400000002
>     -dst_mac=00000000af01
>     -src_ip=aef0000000000000526400fffe000002
>     -dst_ip=20020ab8000100000200020000020306
>     -# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
>     -dst_mcast_mac=3333ff011305
>     -mcast_node_ip=ff0200000000000000000001ff011305
>     -nd_target=20010db800010000020002fffe011305
>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>     -$mcast_node_ip $nd_target
>     -
>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>     " " -f1)])
>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>     " -f1)])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-phys_n1-tx.pcap | \
>     -trim_zeros > 1.packets
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-phys-tx.pcap | \
>     -trim_zeros > 2.packets
>     -
>     -cat ipv6_ns.expected | cut -c -112 > expout
>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>     -
>     -# Skipping the ICMPv6 checksum
>     -cat ipv6_ns.expected | cut -c 117- > expout
>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- options:requested-chassis for logical port])
>     -ovn_start
>     -
>     -net_add n1
>     -
>     -ovn-nbctl ls-add ls0
>     -ovn-nbctl lsp-add ls0 lsp0
>     -
>     -# create two hypervisors, each with one vif port
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.11
>     -ovs-vsctl -- add-port br-int hv1-vif0 -- \
>     -set Interface hv1-vif0 ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.12
>     -ovs-vsctl -- add-port br-int hv2-vif0 -- \
>     -set Interface hv2-vif0 ofport-request=1
>     -
>     -# Allow only chassis hv1 to bind logical port lsp0.
>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -# Retrieve hv1 and hv2 chassis UUIDs from southbound database
>     -ovn-sbctl wait-until chassis hv1
>     -ovn-sbctl wait-until chassis hv2
>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
>     -hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
>     -
>     -# (1) Chassis hv2 should not bind lsp0 when requested-chassis is hv1.
>     -echo "verifying that hv2 does not bind lsp0 when hv2
>     physical/logical mapping is added"
>     -as hv2
>     -ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
>     -
>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0"
>     hv2/ovn-controller.log)])
>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding logical_port=lsp0) = x], [0], [])
>     -
>     -# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and
>     OFTABLE_LOG_TO_PHY tables.
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [1], [])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>     output], [1], [])
>     -
>     -# (3) Chassis hv1 should bind lsp0 when physical to logical
>     mapping exists on hv1.
>     -echo "verifying that hv1 binds lsp0 when hv1 physical/logical
>     mapping is added"
>     -as hv1
>     -ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>     -
>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>     hv1/ovn-controller.log)])
>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>     -
>     -# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and
>     OFTABLE_LOG_TO_PHY tables.
>     -as hv1 ovs-ofctl dump-flows br-int
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [0], [ignore])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>     actions=output:1], [0], [ignore])
>     -
>     -# (5) Chassis hv1 should release lsp0 binding and chassis hv2
>     should bind lsp0 when
>     -# the requested chassis for lsp0 is changed from hv1 to hv2.
>     -echo "verifying that lsp0 binding moves when requested-chassis is
>     changed"
>     -
>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>     this chassis" hv1/ovn-controller.log)])
>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding logical_port=lsp0) = x"$hv2_uuid"])
>     -
>     -# (6) Chassis hv2 should add flows and hv1 should not.
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [0], [ignore])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>     actions=output:1], [0], [ignore])
>     -
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [1], [])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>     output], [1], [])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- options:requested-chassis with hostname])
>     -
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls0
>     -ovn-nbctl lsp-add ls0 lsp0
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.11
>     -ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0
>     ofport-request=1
>     -
>     -ovn-sbctl wait-until chassis hv1
>     -hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis
>     name=hv1)
>     -echo "hv1_hostname=${hv1_hostname}"
>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>     requested-chassis=${hv1_hostname}
>     -as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>     -
>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
>     -echo "hv1_uuid=${hv1_uuid}"
>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>     hv1/ovn-controller.log)])
>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [0], [ignore])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>     actions=output:1], [0], [ignore])
>     -
>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>     requested-chassis=non-existant-chassis
>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>     this chassis" hv1/ovn-controller.log)])
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>     port_binding logical_port=lsp0) = x], [0], [])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>     in_port=1], [1], [])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>     output], [1], [])
>     -
>     -OVN_CLEANUP([hv1])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IPv6 periodic RA])
>     -ovn_start
>     -
>     -# This test sets up two hypervisors.
>     -# hv1 and hv2 run ovn-controllers, and
>     -# each has a VIF connected to the same
>     -# logical switch in OVN. The logical
>     -# switch is connected to a logical
>     -# router port that is configured to send
>     -# periodic router advertisements.
>     -#
>     -# The reason for having two ovn-controller
>     -# hypervisors is to ensure that the
>     -# periodic RAs being sent by each ovn-controller
>     -# are kept to their local hypervisors. If the
>     -# packets are not kept local, then each port
>     -# will receive too many RAs.
>     -
>     -net_add n1
>     -sim_add hv1
>     -sim_add hv2
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -
>     -ovn-nbctl lr-add ro
>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>     -
>     -ovn-nbctl ls-add sw
>     -ovn-nbctl lsp-add sw sw-ro
>     -ovn-nbctl lsp-set-type sw-ro router
>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>     -ovn-nbctl lsp-add sw sw-p1
>     -ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02
>     aef0::200:ff:fe00:2"
>     -ovn-nbctl lsp-add sw sw-p2
>     -ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03
>     aef0::200:ff:fe00:3"
>     -
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:send_periodic=true
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:address_mode=slaac
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:max_interval=4
>     -ovn-nbctl set Logical_Router_Port ro-sw
>     ipv6_ra_configs:min_interval=3
>     -
>     -for i in 1 2 ; do
>     -    as hv$i
>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>     -        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>     -        ofport-request=1
>     -done
>     -
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -
>     -}
>     -
>     -construct_expected_ra() {
>     -    local src_mac=000000000001
>     -    local dst_mac=333300000001
>     -    local src_addr=fe80000000000000020000fffe000001
>     -    local dst_addr=ff020000000000000000000000000001
>     -
>     -    local mtu=$1
>     -    local ra_mo=$2
>     -    local ra_prefix_la=$3
>     -
>     -    local slla=0101${src_mac}
>     -    local mtu_opt=""
>     -    if test $mtu != 0; then
>     -        mtu_opt=05010000${mtu}
>     -    fi
>     -    shift 3
>     -
>     -    local prefix=""
>     -    while [[ $# -gt 0 ]] ; do
>     -        local size=$1
>     -        local net=$2
>     -
>     prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
>     -        shift 2
>     -    done
>     -
>     -    local ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
>     -    local icmp=8600XXXX${ra}
>     -
>     -    local ip_len=$(expr ${#icmp} / 2)
>     -    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
>     -
>     -    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
>     -    local eth=${dst_mac}${src_mac}86dd${ip}
>     -    local packet=${eth}
>     -    echo $packet >> expected
>     -}
>     -
>     -ra_test() {
>     -    construct_expected_ra $@
>     -
>     -    for i in hv1 hv2 ; do
>     -        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut
>     -d " " -f1)])
>     -
>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" $i/vif1-tx.pcap > packets
>     -
>     -        cat expected | cut -c -112 > expout
>     -        AT_CHECK([cat packets | cut -c -112], [0], [expout])
>     -
>     -        # Skip ICMPv6 checksum.
>     -        cat expected | cut -c 117- > expout
>     -        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
>     -
>     -        rm -f packets
>     -        as $i reset_pcap_file $i-vif1 $i/vif1
>     -    done
>     -
>     -    rm -f expected
>     -}
>     -
>     -# Baseline test with no MTU
>     -ra_test 0 00 c0 40 aef00000000000000000000000000000
>     -
>     -# Now make sure an MTU option makes it
>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>     ipv6_ra_configs:mtu=1500
>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
>     -
>     -# Now test for multiple network prefixes
>     -ovn-nbctl --wait=hv set Logical_Router_port ro-sw
>     networks='aef0\:\:1/64 fd0f\:\:1/48'
>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30
>     fd0f0000000000000000000000000000
>     -
>     -# Test a different address mode now
>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>     -ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30
>     fd0f0000000000000000000000000000
>     -
>     -# And the other address mode
>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>     -ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30
>     fd0f0000000000000000000000000000
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ACL reject rule test])
>     -AT_KEYWORDS([acl-reject])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv4 packet with
>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>     of the icmp destination
>     -# unreachable frame generated from ACL rule hit
>     -#
>     -# INPORT is a lport number, e.g. 11 for vif11.
>     -# HV is a hypervisor number
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>     -test_ip_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ipv4_dst=$6 ip_chksum=$7
>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>     -    shift 9
>     -
>     -    local ip_ttl=ff
>     -    local
>     packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
>     -
>     -    local reply_icmp_ttl=ff
>     -    local icmp_type_code_response=0301
>     -    local icmp_data=00000000
>     -    local
>     reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
>     -    local
>     reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     EXP_ICMP_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv6 packet with
>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
>     -# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination
>     unreachable frame generated from ACL rule hit
>     -test_ipv6_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_dst=$6 exp_icmp_chksum=$7
>     -    shift 7
>     -
>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
>     -
>     -    local
>     reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>     EXP_TCP_RST_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an TCP syn segment with
>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT,
>     TCP_DPORT, TCP_CHKSUM  as specified.
>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>     checksums of the tcp reset segment generated from ACL rule hit
>     -#
>     -# INPORT is an lport number, e.g. 11 for vif11.
>     -# HV is an hypervisor number
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>     each 4 hex digits
>     -test_tcp_syn_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ipv4_dst=$6 ip_chksum=$7
>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>     -    shift 12
>     -
>     -    local ip_ttl=ff
>     -    local
>     packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
>     -
>     -    local tcp_rst_ttl=ff
>     -    local
>     reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# Create hypervisors hv[123].
>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>     -# Add all of the vifs to a single logical switch sw0.
>     -
>     -net_add n1
>     -ovn-nbctl ls-add sw0
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2 3; do
>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>     192.168.1.$i$j"
>     -
>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>     -                set interface vif$i$j \
>     -                external-ids:iface-id=sw0-p$i$j \
>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>     -                ofport-request=$i$j
>     -    done
>     -done
>     -
>     -OVN_POPULATE_ARP
>     -# allow some time for ovn-northd and ovn-controller to catch up.
>     -sleep 1
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -for i in 1 2 3; do
>     -    : > vif${i}1.expected
>     -done
>     -
>     -ovn-nbctl --log acl-add sw0 to-lport 1000 "outport ==
>     \"sw0-p12\"" reject
>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>     \"sw0-p11\"" reject
>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>     \"sw0-p21\"" reject
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -ovn-nbctl --timeout=3 --wait=hv sync
>     -
>     -test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168
>     1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
>     -test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168
>     1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
>     -test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168
>     1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
>     -
>     -test_ipv6_packet 11 1 000000000011 000000000021
>     fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 6183
>     -
>     -test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex
>     192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 4486
>     -test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex
>     192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 4486
>     -test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex
>     192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 4486
>     -
>     -for i in 1 2 3; do
>     -    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], [vif${i}1.expected])
>     -done
>     -
>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- Port Groups])
>     -AT_KEYWORDS([ovnpg])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -#
>     -# Three logical switches ls1, ls2, ls3.
>     -# One logical router lr0 connected to ls[123],
>     -# with nine subnets, three per logical switch:
>     -#
>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 <http://192.168.11.0/24>
>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 <http://192.168.12.0/24>
>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 <http://192.168.13.0/24>
>     -#    ...
>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 <http://192.168.33.0/24>
>     -#
>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>     first two
>     -# digits are the subnet and the last digit distinguishes the VIF.
>     -#
>     -# This test will create two port groups and uses them in ACL.
>     -
>     -get_lsp_uuid () {
>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>     -}
>     -
>     -pg1_ports=
>     -pg2_ports=
>     -for i in 1 2 3; do
>     -    ovn-nbctl ls-add ls$i
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            ovn-nbctl \
>     -                -- lsp-add ls$i lp$i$j$k \
>     -                -- lsp-set-addresses lp$i$j$k \
>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>     -            # logical ports lp[12]?1 belongs to port group pg1
>     -            if test $i != 3 && test $k == 1; then
>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>     -            fi
>     -            # logical ports lp[23]?2 belongs to port group pg2
>     -            if test $i != 1 && test $k == 2; then
>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>     -            fi
>     -        done
>     -    done
>     -done
>     -
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>     192.168.$i$j.254/24
>     -        ovn-nbctl \
>     -            -- lsp-add ls$i lrp$i$j-attachment \
>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>     type=router \
>     -                             options:router-port=lrp$i$j \
>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>     -    done
>     -done
>     -
>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>     -
>     -# create ACLs on all lswitches to drop traffic from pg2 to pg1
>     -ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src
>     == $pg2_ip4' drop
>     -ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src
>     == $pg2_ip4' drop
>     -ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src
>     == $pg2_ip4' drop
>     -
>     -# Physical network:
>     -#
>     -# Three hypervisors hv[123].
>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>     lp?13 on hv3.
>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>     on hv3.
>     -# lp?3[123] all on hv3.
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    case $1 in dnl (
>     -        ?11) echo 1 ;; dnl (
>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>     -        ?13 | ?23 | ?3?) echo 3 ;;
>     -    esac
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its
>     logical router
>     -# port, e.g. "vif_to_lrp 123" yields 12.
>     -vif_to_lrp() {
>     -    echo ${1%?}
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its logical
>     -# switch, e.g. "vif_to_ls 123" yields 1.
>     -vif_to_ls() {
>     -    echo ${1%??}
>     -}
>     -
>     -net_add n1
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -done
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            hv=`vif_to_hv $i$j$k`
>     -                as hv$hv ovs-vsctl \
>     -                -- add-port br-int vif$i$j$k \
>     -                -- set Interface vif$i$j$k \
>     -                    external-ids:iface-id=lp$i$j$k \
>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>     -                    ofport-request=$i$j$k
>     -        done
>     -    done
>     -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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -#
>     -# This shell function causes a packet to be received on INPORT. 
>     The packet's
>     -# content has Ethernet destination DST and source SRC (each
>     exactly 12 hex
>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>     (zero or
>     -# more) list the VIFs on which the packet should be received. 
>     INPORT and the
>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>     for vif123.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            : > $i$j$k.expected
>     -        done
>     -    done
>     -done
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    in_ls=`vif_to_ls $inport`
>     -    in_lrp=`vif_to_lrp $inport`
>     -    for outport; do
>     -        out_ls=`vif_to_ls $outport`
>     -        if test $in_ls = $out_ls; then
>     -            # Ports on the same logical switch receive exactly
>     the same packet.
>     -            echo $packet
>     -        else
>     -            # Routing decrements TTL and updates source and dest MAC
>     -            # (and checksum).
>     -            out_lrp=`vif_to_lrp $outport`
>     -            echo
>     f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
>     -        fi >> $outport.expected
>     -    done
>     -}
>     -
>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>     -as hv1 ovn-sbctl list port_binding
>     -as hv1 ovn-sbctl list datapath_binding
>     -as hv1 ovn-sbctl list port_group
>     -as hv1 ovn-sbctl list address_set
>     -as hv1 ovn-sbctl dump-flows
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Send IP packets between all pairs of source and destination ports,
>     -# packets matches ACL (pg2 to pg1) should be dropped
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -for is in 1 2 3; do
>     -  for js in 1 2 3; do
>     -    for ks in 1 2 3; do
>     -      bcast=
>     -      s=$is$js$ks
>     -      smac=f00000000$s
>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>     -      for id in 1 2 3; do
>     -          for jd in 1 2 3; do
>     -              for kd in 1 2 3; do
>     -                d=$id$jd$kd
>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>     -                if test $is = $id; then dmac=f00000000$d; else
>     dmac=00000000ff$is$js; fi
>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>     -
>     -                # packets matches ACL should be dropped
>     -                if test $id != 3 && test $kd == 1; then
>     -                    if test $is != 1 && test $ks == 2; then
>     -                        unicast=
>     -                    fi
>     -                fi
>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>     -              done
>     -          done
>     -        done
>     -      done
>     -  done
>     -done
>     -
>     -# Allow some time for packet forwarding.
>     -# XXX This can be improved.
>     -sleep 1
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>     $i$j$k`/vif$i$j$k-tx.pcap],
>     -                              [$i$j$k.expected])
>     -        done
>     -    done
>     -done
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ACLs on Port Groups])
>     -AT_KEYWORDS([ovnpg_acl])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -#
>     -# Three logical switches ls1, ls2, ls3.
>     -# One logical router lr0 connected to ls[123],
>     -# with nine subnets, three per logical switch:
>     -#
>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 <http://192.168.11.0/24>
>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 <http://192.168.12.0/24>
>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 <http://192.168.13.0/24>
>     -#    ...
>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 <http://192.168.33.0/24>
>     -#
>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>     first two
>     -# digits are the subnet and the last digit distinguishes the VIF.
>     -#
>     -# This test will create two port groups and ACLs will be applied
>     on them.
>     -
>     -get_lsp_uuid () {
>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>     -}
>     -
>     -pg1_ports=
>     -pg2_ports=
>     -for i in 1 2 3; do
>     -    ovn-nbctl ls-add ls$i
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            ovn-nbctl \
>     -                -- lsp-add ls$i lp$i$j$k \
>     -                -- lsp-set-addresses lp$i$j$k \
>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>     -            # logical ports lp[12]?1 belongs to port group pg1
>     -            if test $i != 3 && test $k == 1; then
>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>     -            fi
>     -            # logical ports lp[23]?2 belongs to port group pg2
>     -            if test $i != 1 && test $k == 2; then
>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>     -            fi
>     -        done
>     -    done
>     -done
>     -
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>     192.168.$i$j.254/24
>     -        ovn-nbctl \
>     -            -- lsp-add ls$i lrp$i$j-attachment \
>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>     type=router \
>     -                             options:router-port=lrp$i$j \
>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>     -    done
>     -done
>     -
>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>     -
>     -# create ACLs on pg1 to drop traffic from pg2 to pg1
>     -ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
>     -ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
>     -        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
>     -
>     -# Physical network:
>     -#
>     -# Three hypervisors hv[123].
>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>     lp?13 on hv3.
>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>     on hv3.
>     -# lp?3[123] all on hv3.
>     -
>     -# Given the name of a logical port, prints the name of the hypervisor
>     -# on which it is located.
>     -vif_to_hv() {
>     -    case $1 in dnl (
>     -        ?11) echo 1 ;; dnl (
>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>     -        ?13 | ?23 | ?3?) echo 3 ;;
>     -    esac
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its
>     logical router
>     -# port, e.g. "vif_to_lrp 123" yields 12.
>     -vif_to_lrp() {
>     -    echo ${1%?}
>     -}
>     -
>     -# Given the name of a logical port, prints the name of its logical
>     -# switch, e.g. "vif_to_ls 123" yields 1.
>     -vif_to_ls() {
>     -    echo ${1%??}
>     -}
>     -
>     -net_add n1
>     -for i in 1 2 3; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -done
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            hv=`vif_to_hv $i$j$k`
>     -                as hv$hv ovs-vsctl \
>     -                -- add-port br-int vif$i$j$k \
>     -                -- set Interface vif$i$j$k \
>     -                    external-ids:iface-id=lp$i$j$k \
>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>     -                    ofport-request=$i$j$k
>     -        done
>     -    done
>     -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
>     -
>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>     -# XXX This should be more systematic.
>     -sleep 1
>     -
>     -lsp_to_mac() {
>     -    echo f0:00:00:00:0${1:0:1}:${1:1:2}
>     -}
>     -
>     -lrp_to_mac() {
>     -    echo 00:00:00:00:ff:$1
>     -}
>     -
>     -# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
>     -#
>     -# This shell function causes a ICMP packet to be received on INPORT.
>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>     should
>     -# be received.  INPORT and the OUTPORTs are specified as logical
>     switch
>     -# port numbers, e.g. 123 for vif123.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            : > $i$j$k.expected
>     -        done
>     -    done
>     -done
>     -
>     -test_icmp() {
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     icmp_type=$6
>     -    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
>     -                  eth.dst==$dst_mac && ip.ttl==64 && ip4.src==$src_ip
>     -                  && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
>     -                  icmp4.code==0"
>     -    shift; shift; shift; shift; shift; shift
>     -    hv=hv`vif_to_hv $inport`
>     -    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -    in_ls=`vif_to_ls $inport`
>     -    in_lrp=`vif_to_lrp $inport`
>     -    for outport; do
>     -        out_ls=`vif_to_ls $outport`
>     -        if test $in_ls = $out_ls; then
>     -            # Ports on the same logical switch receive exactly
>     the same packet.
>     -            echo $packet | ovstest test-ovn expr-to-packets
>     -        else
>     -            # Routing decrements TTL and updates source and dest MAC
>     -            # (and checksum).
>     -            out_lrp=`vif_to_lrp $outport`
>     -            exp_smac=`lrp_to_mac $out_lrp`
>     -            exp_dmac=`lsp_to_mac $outport`
>     -            exp_packet="eth.src==$exp_smac && eth.dst==$exp_dmac &&
>     -                ip.ttl==63 && ip4.src==$src_ip && ip4.dst==$dst_ip &&
>     -                icmp4.type==$icmp_type && icmp4.code==0"
>     -            echo $exp_packet | ovstest test-ovn expr-to-packets
>     -
>     -        fi >> $outport.expected
>     -    done
>     -}
>     -
>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>     -as hv1 ovn-sbctl list port_binding
>     -as hv1 ovn-sbctl list datapath_binding
>     -as hv1 ovn-sbctl list port_group
>     -as hv1 ovn-sbctl list address_set
>     -as hv1 ovn-sbctl dump-flows
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Send IP packets between all pairs of source and destination ports,
>     -# packets matches ACL1 but not ACL2 should be dropped
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -for is in 1 2 3; do
>     -  for js in 1 2 3; do
>     -    for ks in 1 2 3; do
>     -      bcast=
>     -      s=$is$js$ks
>     -      slsp_mac=`lsp_to_mac $s`
>     -      slrp_mac=`lrp_to_mac $is$js`
>     -      sip=192.168.$is$js.$ks
>     -      for id in 1 2 3; do
>     -          for jd in 1 2 3; do
>     -              for kd in 1 2 3; do
>     -                d=$id$jd$kd
>     -                dlsp_mac=`lsp_to_mac $d`
>     -                dlrp_mac=`lrp_to_mac $id$jd`
>     -                dip=192.168.$id$jd.$kd
>     -                if test $is = $id; then dmac=$dlsp_mac; else
>     dmac=$slrp_mac; fi
>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>     -
>     -                # packets matches ACL1 but not ACL2 should be dropped
>     -                if test $id != 3 && test $kd == 1; then
>     -                    if test $is == 1 || test $ks != 2; then
>     -                        unicast=
>     -                    fi
>     -                fi
>     -                # icmp request (type = 8)
>     -                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
>     -
>     -                # if packets are not dropped, test the return
>     traffic (icmp echo)
>     -                # to make sure stateful works, too.
>     -                if test x$unicast != x; then
>     -                    if test $is = $id; then dmac=$slsp_mac; else
>     dmac=$dlrp_mac; fi
>     -                    # icmp echo (type = 0)
>     -                    test_icmp $unicast $dlsp_mac $dmac $dip $sip 0 $s
>     -                fi
>     -              done
>     -          done
>     -        done
>     -      done
>     -  done
>     -done
>     -
>     -# Allow some time for packet forwarding.
>     -# XXX This can be improved.
>     -sleep 1
>     -
>     -# Now check the packets actually received against the ones expected.
>     -for i in 1 2 3; do
>     -    for j in 1 2 3; do
>     -        for k in 1 2 3; do
>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>     $i$j$k`/vif$i$j$k-tx.pcap],
>     -                              [$i$j$k.expected])
>     -        done
>     -    done
>     -done
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- Address Set generation from Port Groups (static
>     addressing)])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -ovn-nbctl lsp-add ls1 lp1
>     -ovn-nbctl lsp-add ls1 lp2
>     -ovn-nbctl lsp-add ls1 lp3
>     -
>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1
>     2001:db8::1"
>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2
>     2001:db8::2"
>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3
>     2001:db8::3"
>     -
>     -ovn-nbctl create Port_Group name=pg1
>     -ovn-nbctl create Port_Group name=pg2
>     -
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>     pg1 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>     pg1 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>     pg2 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>     pg2 ports @p
>     -
>     -ovn-nbctl --wait=sb sync
>     -
>     -dnl Check if port group address sets were populated with ports'
>     addresses
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>     -         [0], [[["10.0.0.1", "10.0.0.2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>     -         [0], [[["10.0.0.2", "10.0.0.3"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>     -         [0], [[["2001:db8::1", "2001:db8::2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>     -         [0], [[["2001:db8::2", "2001:db8::3"]]
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-set-addresses lp1 \
>     -    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
>     -
>     -dnl Check if updated address got propagated to the port group
>     address sets
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>     -         [0], [[["10.0.0.11", "10.0.0.2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>     -         [0], [[["2001:db8::11", "2001:db8::2"]]
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic
>     addressing)])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl ls-add ls2
>     -ovn-nbctl ls-add ls3
>     -
>     -ovn-nbctl set Logical_Switch ls1 \
>     -    other_config:subnet=10.1.0.0/24 <http://10.1.0.0/24>
>     other_config:ipv6_prefix="2001:db8:1::"
>     -ovn-nbctl set Logical_Switch ls2 \
>     -    other_config:subnet=10.2.0.0/24 <http://10.2.0.0/24>
>     other_config:ipv6_prefix="2001:db8:2::"
>     -ovn-nbctl set Logical_Switch ls3 \
>     -    other_config:subnet=10.3.0.0/24 <http://10.3.0.0/24>
>     other_config:ipv6_prefix="2001:db8:3::"
>     -
>     -ovn-nbctl lsp-add ls1 lp1
>     -ovn-nbctl lsp-add ls2 lp2
>     -ovn-nbctl lsp-add ls3 lp3
>     -
>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
>     -
>     -ovn-nbctl create Port_Group name=pg1
>     -ovn-nbctl create Port_Group name=pg2
>     -
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>     pg1 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>     pg1 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>     pg2 ports @p
>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>     pg2 ports @p
>     -
>     -ovn-nbctl --wait=sb sync
>     -
>     -dnl Check if port group address sets were populated with ports'
>     addresses
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>     -         [0], [[["10.1.0.2", "10.2.0.2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>     -         [0], [[["10.2.0.2", "10.3.0.2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>     -         [0], [[["2001:db8:1::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>     -         [0], [[["2001:db8:2::ff:fe00:2", "2001:db8:3::ff:fe00:3"]]
>     -])
>     -
>     -ovn-nbctl --wait=sb set Logical_Switch ls1 \
>     -    other_config:subnet=10.11.0.0/24 <http://10.11.0.0/24>
>     other_config:ipv6_prefix="2001:db8:11::"
>     -
>     -dnl Check if updated address got propagated to the port group
>     address sets
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>     -         [0], [[["10.11.0.2", "10.2.0.2"]]
>     -])
>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>     -         [0], [[["2001:db8:11::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ACL conjunction])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add ls1
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>     -
>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>     -
>     -net_add n1
>     -sim_add hv1
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=2
>     -
>     -ovn-nbctl create Address_Set name=set1 \
>     -addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
>     -ovn-nbctl create Address_Set name=set2 \
>     -addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
>     -ovn-nbctl acl-add ls1 to-lport 1002 \
>     -'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
>     -ovn-nbctl acl-add ls1 to-lport 1001 \
>     -'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
>     -
>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>     -#
>     -# This shell function causes an ip packet to be received on INPORT.
>     -# The packet's content has Ethernet destination DST and source SRC
>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>     digits).
>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>     should
>     -# be received.  INPORT and the OUTPORTs are specified as logical
>     switch
>     -# port numbers, e.g. 11 for vif11.
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
>     -${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -    for outport; do
>     -        echo $packet >> $outport.expected
>     -    done
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -
>     -sip=`ip_to_hex 10 0 0 4`
>     -dip=`ip_to_hex 10 0 0 6`
>     -
>     -test_ip 1 f00000000001 f00000000002 $sip $dip 2
>     -
>     -cat 2.expected > expout
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [expout])
>     -
>     -# There should be total of 12 flows present with conjunction
>     action and 2 flows
>     -# with conj match. Eg.
>     -# table=44, priority=2002,conj_id=2,metadata=0x1
>     actions=resubmit(,45)
>     -# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6
>     actions=conjunction(2,2/2)
>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4
>     actions=conjunction(2,2/2)
>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5
>     actions=conjunction(2,2/2)
>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7
>     actions=conjunction(3,2/2)
>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9
>     actions=conjunction(3,2/2)
>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8
>     actions=conjunction(3,2/2)
>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6
>     actions=conjunction(2,1/2)
>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4
>     actions=conjunction(2,1/2)
>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5
>     actions=conjunction(2,1/2)
>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6
>     actions=conjunction(3,1/2)
>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4
>     actions=conjunction(3,1/2)
>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5
>     actions=conjunction(3,1/2)
>     -
>     -OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
>     -grep conjunction | wc -l`])
>     -OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
>     -grep conj_id | wc -l`])
>     -
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -# Set the ip address for ls1-lp2 from set2 so that the drop ACL
>     flow is hit.
>     -ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7
>     20.0.0.4"
>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>     10.0.0.7 20.0.0.4"
>     -
>     -reset_pcap_file hv1-vif2 hv1/vif2
>     -
>     -rm -f 2.packets
>     -
>     -sip=`ip_to_hex 10 0 0 4`
>     -dip=`ip_to_hex 10 0 0 7`
>     -
>     -test_ip 1 f00000000001 f00000000002 $sip $dip
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/vif2-tx.pcap > 2.packets
>     -AT_CHECK([cat 2.packets], [0], [])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- TTL exceeded])
>     -AT_KEYWORDS([ttl-exceeded])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv4 packet with
>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified
>     and TTL set to 1.
>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>     of the icmp time exceeded frame
>     -# generated by OVN logical router
>     -#
>     -# INPORT is a lport number, e.g. 11 for vif11.
>     -# HV is a hypervisor number
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>     -test_ip_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ipv4_dst=$6 ip_router=$7 ip_chksum=$8
>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
>     -    shift 10
>     -
>     -    local ip_ttl=01
>     -    local
>     packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
>     -
>     -    local reply_icmp_ttl=fe
>     -    local icmp_type_code_response=0b00
>     -    local icmp_data=00000000
>     -    local
>     reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
>     -    local
>     reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>     IPV6_ROUTER EXP_ICMP_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv6
>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified.
>     -# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum
>     of the icmpv6 ttl exceeded
>     -# packet sent by OVN logical router
>     -test_ip6_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>     -    shift 8
>     -
>     -    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
>     -    local
>     packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
>     -
>     -    local
>     reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -for i in 1 2; do
>     -    net_add n$i
>     -    ovn-nbctl ls-add sw$i
>     -
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n$i br-phys 192.168.$i.1
>     -
>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>     192.168.$i.1 2001:db8:$i::11"
>     -
>     -    ovs-vsctl -- add-port br-int vif$i -- \
>     -        set interface vif$i \
>     -        external-ids:iface-id=sw$i-p${i}0 \
>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>     -            ofport-request=$i
>     -done
>     -
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2; do
>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>     192.168.$i.254/24 2001:db8:$i::1/64
>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>     -              -- set Logical_Switch_Port lrp$i-attachment
>     type=router \
>     -                options:router-port=lrp$i
>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
>     -done
>     -
>     -OVN_POPULATE_ARP
>     -# allow some time for ovn-northd and ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -
>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>     1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae
>     f4ff
>     -test_ip6_packet 1 1 000000000001 00000000ff01
>     20010db8000100000000000000000011 20010db8000200000000000000000011
>     20010db8000100000000000000000001 d461
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>     -
>     -OVN_CLEANUP([hv1], [hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- router port unreachable])
>     -AT_KEYWORDS([router-port-unreachable])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
>     L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv4 packet with
>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM
>     as specified.
>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>     of the icmp frame generated by OVN logical router
>     -# EXP_ICMP_CODE are code and type of the icmp frame generated by
>     OVN logical router
>     -#
>     -# INPORT is a lport number, e.g. 11 for vif11.
>     -# HV is a hypervisor number
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>     -test_ip_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ip_router=$6 l4_proto=$7 ip_chksum=$8
>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10} exp_icmp_code=${11}
>     -    shift 11
>     -
>     -    local ip_ttl=ff
>     -    local
>     packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
>     -
>     -    local reply_icmp_ttl=fe
>     -    local icmp_data=00000000
>     -    local
>     reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
>     -    local
>     reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC
>     IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>     EXP_TCP_RST_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an TCP syn segment with
>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT,
>     TCP_DPORT, TCP_CHKSUM  as specified.
>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>     checksums of the tcp reset segment generated by OVN logical router
>     -#
>     -# INPORT is an lport number, e.g. 11 for vif11.
>     -# HV is an hypervisor number
>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>     each 4 hex digits
>     -test_tcp_syn_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ip_router=$6 ip_chksum=$7
>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>     -    shift 12
>     -
>     -    local ip_ttl=ff
>     -    local
>     packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
>     -
>     -    local tcp_rst_ttl=fe
>     -    local
>     reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>     TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is a TCP syn segment with
>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT
>     and TCP_CHKSUM as specified.
>     -# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset
>     segment generated by OVN logical router
>     -test_tcp6_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_router=$6
>     -    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
>     -    local exp_tcp_rst_chksum=${10}
>     -    shift 10
>     -
>     -    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
>     -    local
>     packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
>     -
>     -    local
>     reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>     IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
>     -#
>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv6
>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO,
>     IPV6_LEN and DATA as specified.
>     -# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of
>     the icmp6 packet sent by OVN logical router
>     -test_ip6_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
>     -    local exp_icmp_code=${10} exp_icmp_chksum=${11}
>     -    shift 11
>     -
>     -    local
>     ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
>     -
>     -    local
>     reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}
>     -    echo $reply >> vif$inport.expected
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -for i in 1 2; do
>     -    net_add n$i
>     -    ovn-nbctl ls-add sw$i
>     -
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n$i br-phys 192.168.$i.1
>     -
>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>     192.168.$i.1 2001:db8:$i::11"
>     -
>     -    ovs-vsctl -- add-port br-int vif$i -- \
>     -        set interface vif$i \
>     -        external-ids:iface-id=sw$i-p${i}0 \
>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>     -            ofport-request=$i
>     -done
>     -
>     -ovn-nbctl lr-add lr0
>     -for i in 1 2; do
>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>     192.168.$i.254/24 2001:db8:$i::1/64
>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>     -              -- set Logical_Switch_Port lrp$i-attachment
>     type=router \
>     -                options:router-port=lrp$i
>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
>     -done
>     -
>     -OVN_POPULATE_ARP
>     -# allow some time for ovn-northd and ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -
>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>     1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>     1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
>     -test_ip6_packet 1 1 000000000001 00000000ff01
>     20010db8000100000000000000000011 20010db8000100000000000000000001
>     11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>     -
>     -test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
>     -test_ip6_packet 2 2 000000000002 00000000ff02
>     20010db8000200000000000000000011 20010db8000200000000000000000001
>     84 0004 01020304 0103 627e
>     -test_tcp6_packet 2 2 000000000002 00000000ff02
>     20010db8000200000000000000000011 20010db8000200000000000000000001
>     8b40 3039 0000 4486
>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
>     -
>     -OVN_CLEANUP([hv1], [hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ovn-controller exit])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -# Logical network:
>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>     -# sw1 has a single port bound on hv1
>     -# sw2 has a single port bound on hv2
>     -
>     -ovn-nbctl lr-add ro
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl ls-add sw2
>     -
>     -sw1_ro_mac=00:00:10:00:00:01
>     -sw1_ro_ip=10.0.0.1
>     -sw2_ro_mac=00:00:20:00:00:01
>     -sw2_ro_ip=20.0.0.1
>     -sw1_p1_mac=00:00:10:00:00:02
>     -sw1_p1_ip=10.0.0.2
>     -sw2_p1_mac=00:00:20:00:00:02
>     -sw2_p1_ip=20.0.0.2
>     -
>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>     type=router \
>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>     type=router \
>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>     -
>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>     -
>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -OVN_POPULATE_ARP
>     -
>     -sleep 1
>     -
>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>     eth.dst==$sw1_ro_mac &&
>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>     ip4.dst==$sw2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -
>     -# Start by Sending the packet and make sure it makes it there as
>     expected
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>     ip4.dst==$sw2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Stop ovn-controller on hv2
>     -as hv2 ovs-appctl -t ovn-controller exit
>     -
>     -# Now send the packet again. This time, it should not arrive.
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>     -as hv2 start_daemon ovn-controller
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- external logical port])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -sim_add hv1
>     -sim_add hv2
>     -sim_add hv3
>     -
>     -ovn-nbctl ls-add ls1
>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>     -
>     -# Add a couple of external logical port
>     -ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
>     --- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 ae70::6"
>     -ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
>     -"f0:00:00:00:00:03 10.0.0.6 ae70::6"
>     -ovn-nbctl lsp-set-type ls1-lp_ext1 external
>     -
>     -ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
>     --- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 ae70::7"
>     -ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
>     -"f0:00:00:00:00:04 10.0.0.7 ae70::8"
>     -ovn-nbctl lsp-set-type ls1-lp_ext2 external
>     -
>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>     <http://10.0.0.0/24> \
>     -options="\"server_id\"=\"10.0.0.1\"
>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>     -
>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>     -
>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
>     -
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
>     -
>     -# Create a logical router and connect it to ls1
>     -ovn-nbctl lr-add lr0
>     -ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
>     <http://10.0.0.1/24>
>     -ovn-nbctl lsp-add ls1 ls1-lr0
>     -ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
>     -    options:router-port=lr0-ls1 addresses=router
>     -
>     -# Create HA chassis group
>     -ovn-nbctl ha-chassis-group-add hagrp1
>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>     -
>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>     ha_chassis_group name="hagrp1"`
>     -
>     -# There should be 1 HA_Chassis rows with chassis sets
>     -OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk
>     '{print $3}' \
>     -| grep '-' | wc -l ], [0], [1
>     -])
>     -
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-phys hv1-ext1 -- \
>     -    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
>     -    options:rxq_pcap=hv1/ext1-rx.pcap \
>     -    ofport-request=2
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-phys hv2-ext2 -- \
>     -    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
>     -    options:rxq_pcap=hv2/ext2-rx.pcap \
>     -    ofport-request=2
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -as hv3
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.3
>     -ovs-vsctl -- add-port br-phys hv3-ext3 -- \
>     -    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
>     -    options:rxq_pcap=hv3/ext3-rx.pcap \
>     -    ofport-request=2
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>     10.0.0.6 in hv1 and
>     -# hv2 as ha-chassis-group is not set and no localnet port added
>     to ls1.
>     -AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
>     -wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>     -])
>     -
>     -hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print $3}')
>     -hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print $3}')
>     -hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print $3}')
>     -
>     -# The port_binding row for ls1-lp_ext1 should have empty chassis
>     -chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -
>     -AT_CHECK([test x$chassis == x], [0], [])
>     -
>     -# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
>     -ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
>     -ha-chassis-group=$hagrp1_uuid
>     -
>     -# Get the hagrp1 uuid in SB DB.
>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>     ha_chassis_group \
>     -name="hagrp1"`
>     -
>     -# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
>     -OVS_WAIT_UNTIL(
>     -    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group find \
>     -port_binding logical_port=ls1-lp_ext1`
>     -     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
>     -
>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>     10.0.0.6 in hv1 and hv2
>     -# as no localnet port added to ls1 yet.
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>     -])
>     -
>     -# Add the localnet port to the logical switch ls1
>     -ovn-nbctl lsp-add ls1 ln-public
>     -ovn-nbctl lsp-set-addresses ln-public unknown
>     -ovn-nbctl lsp-set-type ln-public localnet
>     -ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
>     -
>     -ln_public_key=$(ovn-sbctl list port_binding ln-public | grep 
>     tunnel_key | \
>     -awk '{print $3}')
>     -
>     -# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of the
>     -# ha chassis group.
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = "$hv1_uuid"])
>     -
>     -# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port in hv1
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | grep
>     reg14=0x$ln_public_key | \
>     -wc -l], [0], [3
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>     -])
>     -
>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>     -])
>     -
>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 -
>     10.0.0.7 in hv1 and
>     -# hv2 as requested-chassis option is not set.
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
>     -])
>     -
>     -as hv1
>     -ovs-vsctl show
>     -
>     -# This shell function sends a DHCP request packet
>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
>     -test_dhcp() {
>     -    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
>     -    shift; shift; shift; shift; shift;
>     -    if test $use_ip != 0; then
>     -        src_ip=$1
>     -        dst_ip=$2
>     -        shift; shift;
>     -    else
>     -        src_ip=`ip_to_hex 0 0 0 0`
>     -        dst_ip=`ip_to_hex 255 255 255 255`
>     -    fi
>     -    local
>     request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip}
>     -    # udp header and dhcp header
>     -    request=${request}0044004300fc0000
>     -
>     request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac}
>     -    # client hardware padding
>     -    request=${request}00000000000000000000
>     -    # server hostname
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -    # boot file name
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     request=${request}0000000000000000000000000000000000000000000000000000000000000000
>     -    # dhcp magic cookie
>     -    request=${request}63825363
>     -    # dhcp message type
>     -    request=${request}3501${dhcp_type}ff
>     -
>     -    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
>     -    # total IP length will be the IP length of the request packet
>     -    # (which is 272 in our case) + 8 (padding bytes) +
>     (expected_dhcp_opts / 2)
>     -    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>     -    udp_len=`expr $ip_len - 20`
>     -    ip_len=$(printf "%x" $ip_len)
>     -    udp_len=$(printf "%x" $udp_len)
>     -    # $ip_len var will be in 3 digits i.e 134. So adding a '0'
>     before $ip_len
>     -    local
>     reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
>     -    # udp header and dhcp header.
>     -    # $udp_len var will be in 3 digits. So adding a '0' before
>     $udp_len
>     -
>     reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
>     -    # your ip address
>     -    reply=${reply}${offer_ip}
>     -    # next server ip address, relay agent ip address, client mac
>     address
>     -    reply=${reply}0000000000000000${src_mac}
>     -    # client hardware padding
>     -    reply=${reply}00000000000000000000
>     -    # server hostname
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -    # boot file name
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -
>     reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
>     -    # dhcp magic cookie
>     -    reply=${reply}63825363
>     -    # dhcp message type
>     -    local dhcp_reply_type=02
>     -    if test $dhcp_type = 03; then
>     -        dhcp_reply_type=05
>     -    fi
>     -
>     reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
>     -    echo $reply >> ext1_v4.expected
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive
>     hv${inport}-ext${inport} $request
>     -}
>     -
>     -
>     -trim_zeros() {
>     -    sed 's/\(00\)\{1,\}$//'
>     -}
>     -
>     -# This shell function sends a DHCPv6 request packet
>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>     OUTPORT...
>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>     DHCPv6
>     -# packet should be received twice (one from ovn-controller and
>     the other
>     -# from the "ovs-ofctl monitor br-int resume"
>     -test_dhcpv6() {
>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>     -    local req_pkt_in_expected=$6
>     -    local
>     request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
>     -    # dst ip ff02::1:2
>     -    request=${request}ff020000000000000000000000010002
>     -    # udp header and dhcpv6 header
>     -    request=${request}02220223002affff${msg_code}010203
>     -    # Client identifier
>     -    request=${request}0001000a00030001${src_mac}
>     -    # IA-NA (Identity Association for Non Temporary Address)
>     -    request=${request}0003000c0102030400000e1000001518
>     -    shift; shift; shift; shift; shift;
>     -
>     -    local server_mac=000000100001
>     -    local server_lla=fe80000000000000020000fffe100001
>     -    local reply_code=07
>     -    if test $msg_code = 01; then
>     -        reply_code=02
>     -    fi
>     -    local msg_len=54
>     -    if test $offer_ip = 1; then
>     -        msg_len=28
>     -    fi
>     -    local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
>     -    reply=${reply}${server_lla}${src_lla}
>     -
>     -    # udp header and dhcpv6 header
>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>     -    # Client identifier
>     -    reply=${reply}0001000a00030001${src_mac}
>     -    # IA-NA
>     -    if test $offer_ip != 1; then
>     - reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
>     -        reply=${reply}ffffffffffffffff
>     -    fi
>     -    # Server identifier
>     -    reply=${reply}0002000a00030001${server_mac}
>     -
>     -    echo $reply | trim_zeros >> ext${inport}_v6.expected
>     -    # The inport also receives the request packet since it is
>     connected
>     -    # to the br-phys.
>     -    #echo $request >> ext${inport}_v6.expected
>     -
>     -    as hv1 ovs-appctl netdev-dummy/receive
>     hv${inport}-ext${inport} $request
>     -}
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
>     -as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
>     -
>     -AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
>     -as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
>     -
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -# Send DHCPDISCOVER.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -server_mac=ff1000000001
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>     -$expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 1 in hv1.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 0 in hv2.
>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap > ext1_v4.packets
>     -cat ext1_v4.expected | cut -c -48 > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat ext1_v4.expected | cut -c 53- > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>     -
>     -# ovs-ofctl also resumes the packets and this causes other ports
>     to receive
>     -# the DHCP request packet. So reset the pcap files so that its
>     easier to test.
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -rm -f ext1_v4.expected
>     -rm -f ext1_v4.packets
>     -
>     -# Send DHCPv6 request
>     -src_mac=f00000000003
>     -src_lla=fe80000000000000f20000fffe000003
>     -offer_ip=ae700000000000000000000000000006
>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>     -
>     -# NXT_RESUMEs should be 2 in hv1.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 0 in hv2.
>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap | \
>     -sort > ext1_v6.packets
>     -cat ext1_v6.expected | cut -c -120 > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>     -# Skipping the UDP checksum
>     -cat ext1_v6.expected | cut -c 125- > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>     -
>     -rm -f ext1_v6.expected
>     -rm -f ext1_v6.packets
>     -
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -# Delete the ha-chassis hv1.
>     -ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = ""])
>     -
>     -# Add hv2 to the ha chassis group
>     -ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
>     -
>     -ovn-sbctl list ha_chassis_group
>     -ovn-sbctl list ha_chassis
>     -
>     -ovn-sbctl find port_binding logical_port=ls1-lp_ext1
>     -
>     -# The ls1-lp_ext1 should be bound to hv2
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = "$hv2_uuid"])
>     -
>     -# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port
>     in hv2
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | grep
>     reg14=0x$ln_public_key | \
>     -wc -l], [0], [3
>     -])
>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>     -])
>     -
>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>     -])
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>     -grep controller | grep tp_src=546 | grep \
>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>     -grep reg14=0x$ln_public_key | wc -l], [0], [0
>     -])
>     -
>     -# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should
>     come from
>     -# hv2 ovn-controller.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -server_mac=ff1000000001
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>     -$expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 2 in hv1.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 1 in hv2.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap > ext1_v4.packets
>     -cat ext1_v4.expected | cut -c -48 > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat ext1_v4.expected | cut -c 53- > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>     -
>     -# ovs-ofctl also resumes the packets and this causes other ports
>     to receive
>     -# the DHCP request packet. So reset the pcap files so that its
>     easier to test.
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -rm -f ext1_v4.expected
>     -
>     -# Send DHCPv6 request again
>     -src_mac=f00000000003
>     -src_lla=fe80000000000000f20000fffe000003
>     -offer_ip=ae700000000000000000000000000006
>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
>     -
>     -# NXT_RESUMEs should be 2 in hv1.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap | \
>     -sort > ext1_v6.packets
>     -cat ext1_v6.expected | cut -c -120 > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>     -# Skipping the UDP checksum
>     -cat ext1_v6.expected | cut -c 125- > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>     -
>     -rm -f ext1_v6.expected
>     -rm -f ext1_v6.packets
>     -
>     -as hv1
>     -ovs-vsctl show
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>     -reset_pcap_file br-phys hv1/br-phys
>     -
>     -as hv2
>     -ovs-vsctl show
>     -reset_pcap_file hv2-ext2 hv2/ext2
>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -reset_pcap_file br-phys hv2/br-phys
>     -
>     -# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
>     -# response should come from the router pipeline of hv2.
>     -ext1_mac=f00000000003
>     -router_mac=a01000000001
>     -ext1_ip=`ip_to_hex 10 0 0 6`
>     -router_ip=`ip_to_hex 10 0 0 1`
>     -arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip}
>     -
>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
>     -expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip}
>     -echo $expected_response > expout
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap > ext1_arp_resp
>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>     -
>     -# Verify that the response came from hv2
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv2/br-phys_n1-tx.pcap > ext1_arp_resp
>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>     -
>     -# Now add 3 ha chassis to the ha chassis group
>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
>     -
>     -# hv1 should be master and claim ls1-lp_ext1
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = "$hv1_uuid"])
>     -
>     -as hv1
>     -ovs-vsctl show
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>     -reset_pcap_file br-phys hv1/br-phys
>     -
>     -as hv2
>     -ovs-vsctl show
>     -reset_pcap_file hv2-ext2 hv2/ext2
>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -reset_pcap_file br-phys hv2/br-phys
>     -
>     -as hv3
>     -ovs-vsctl show
>     -reset_pcap_file hv3-ext3 hv3/ext3
>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>     -reset_pcap_file br-phys hv3/br-phys
>     -
>     -# Send DHCPDISCOVER.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -server_mac=ff1000000001
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>     -$expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 3 in hv1.
>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap > ext1_v4.packets
>     -cat ext1_v4.expected | cut -c -48 > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat ext1_v4.expected | cut -c 53- > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>     -
>     -# ovs-ofctl also resumes the packets and this causes other ports
>     to receive
>     -# the DHCP request packet. So reset the pcap files so that its
>     easier to test.
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -rm -f ext1_v4.expected
>     -rm -f ext1_v4.packets
>     -
>     -# Send DHCPv6 request
>     -src_mac=f00000000003
>     -src_lla=fe80000000000000f20000fffe000003
>     -offer_ip=ae700000000000000000000000000006
>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>     -
>     -# NXT_RESUMEs should be 4 in hv1.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap | \
>     -sort > ext1_v6.packets
>     -cat ext1_v6.expected | cut -c -120 > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>     -# Skipping the UDP checksum
>     -cat ext1_v6.expected | cut -c 125- > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>     -
>     -rm -f ext1_v6.expected
>     -rm -f ext1_v6.packets
>     -as hv1 reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -# Now increase the priority of hv3 so it becomes master.
>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
>     -
>     -# hv3 should be master and claim ls1-lp_ext1
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = "$hv3_uuid"])
>     -
>     -as hv1
>     -ovs-vsctl show
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>     -reset_pcap_file br-phys hv1/br-phys
>     -
>     -as hv2
>     -ovs-vsctl show
>     -reset_pcap_file hv2-ext2 hv2/ext2
>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>     -reset_pcap_file br-phys hv2/br-phys
>     -
>     -as hv2
>     -ovs-vsctl show
>     -reset_pcap_file hv3-ext3 hv3/ext3
>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>     -reset_pcap_file br-phys hv3/br-phys
>     -
>     -# Send DHCPDISCOVER.
>     -offer_ip=`ip_to_hex 10 0 0 6`
>     -server_ip=`ip_to_hex 10 0 0 1`
>     -server_mac=ff1000000001
>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>     -$expected_dhcp_opts
>     -
>     -# NXT_RESUMEs should be 4 in hv1.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 1 in hv3.
>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap > ext1_v4.packets
>     -cat ext1_v4.expected | cut -c -48 > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>     -# Skipping the IPv4 checksum.
>     -cat ext1_v4.expected | cut -c 53- > expout
>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>     -
>     -# ovs-ofctl also resumes the packets and this causes other ports
>     to receive
>     -# the DHCP request packet. So reset the pcap files so that its
>     easier to test.
>     -as hv1
>     -reset_pcap_file hv1-ext1 hv1/ext1
>     -
>     -rm -f ext1_v4.expected
>     -rm -f ext1_v4.packets
>     -
>     -# Send DHCPv6 request
>     -src_mac=f00000000003
>     -src_lla=fe80000000000000f20000fffe000003
>     -offer_ip=ae700000000000000000000000000006
>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>     -
>     -# NXT_RESUMEs should be 4 in hv1.
>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv2.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>     NXT_RESUME`])
>     -
>     -# NXT_RESUMEs should be 2 in hv3.
>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c
>     NXT_RESUME`])
>     -
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/ext1-tx.pcap | \
>     -sort > ext1_v6.packets
>     -cat ext1_v6.expected | cut -c -120 > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>     -# Skipping the UDP checksum
>     -cat ext1_v6.expected | cut -c 125- > expout
>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>     -
>     -# disconnect hv3 from the network, hv1 should take over
>     -as hv3
>     -port=${sandbox}_br-phys
>     -as main ovs-vsctl del-port n1 $port
>     -
>     -# hv1 should be master and claim ls1-lp_ext1
>     -OVS_WAIT_UNTIL(
>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>     -logical_port=ls1-lp_ext1`
>     -    test "$chassis" = "$hv1_uuid"])
>     -
>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- Address Set Incremental Processing])
>     -AT_KEYWORDS([ovn_as_inc])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.10
>     -
>     -ovn-nbctl ls-add ls1
>     -for i in 1 2; do
>     -    ovn-nbctl lsp-add ls1 lp$i \
>     -        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i"
>     -    as hv1 ovs-vsctl \
>     -        -- add-port br-int vif$i \
>     -        -- set Interface vif$i \
>     -            external-ids:iface-id=lp$i
>     -done
>     -
>     -for i in 1 2 3; do
>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>     -    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>     -            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}'
>     allow-related
>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>     [0], [ignore])
>     -
>     -    # Update address set as1
>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"],
>     [0], [ignore])
>     -
>     -    # Update address set as2
>     -    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>     [0], [ignore])
>     -
>     -    # Add another ACL referencing as1
>     -    n_flows_before=`ovs-ofctl dump-flows br-int | grep
>     "10.1.2.10" | wc -l`
>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>     -            'outport=="lp2" && ip4 && ip4.src == $as1' allow-related
>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>     | wc -l`
>     -    AT_CHECK([test $(expr $n_flows_before \* 2) =
>     $n_flows_after], [0], [ignore])
>     -
>     -    # Remove an ACL
>     -    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
>     -            'outport=="lp2" && ip4 && ip4.src == $as1'
>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>     | wc -l`
>     -    AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore])
>     -
>     -    # Remove as1 while it is still used by an ACL, the lflows
>     should be reparsed and
>     -    # parsing should fail.
>     -    echo "before del as1"
>     -    ovn-nbctl list addr | grep as1
>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid
>     -    echo "after del as1"
>     -    ovn-nbctl list addr | grep as1
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>     [1], [ignore])
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>     [1], [ignore])
>     -
>     -    # Recreate as1
>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>     [0], [ignore])
>     -
>     -    # Remove ACLs and address sets
>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr
>     $as2_uuid
>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>     [1], [ignore])
>     -
>     -    ovn-nbctl --wait=hv acl-del ls1
>     -done
>     -
>     -# Gracefully terminate daemons
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ovn-controller restart])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>     -# sw1 has a single port bound on hv1
>     -# sw2 has a single port bound on hv2
>     -
>     -ovn-nbctl lr-add ro
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl ls-add sw2
>     -
>     -sw1_ro_mac=00:00:10:00:00:01
>     -sw1_ro_ip=10.0.0.1
>     -sw2_ro_mac=00:00:20:00:00:01
>     -sw2_ro_ip=20.0.0.1
>     -sw1_p1_mac=00:00:10:00:00:02
>     -sw1_p1_ip=10.0.0.2
>     -sw2_p1_mac=00:00:20:00:00:02
>     -sw2_p1_ip=20.0.0.2
>     -
>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>     type=router \
>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>     type=router \
>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>     -
>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>     -
>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -OVN_POPULATE_ARP
>     -
>     -sleep 1
>     -
>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>     eth.dst==$sw1_ro_mac &&
>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>     ip4.dst==$sw2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -
>     -# Start by Sending the packet and make sure it makes it there as
>     expected
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -# Expected packet has TTL decreased by 1
>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>     ip4.dst==$sw2_p1_ip &&
>     -       udp && udp.src==53 && udp.dst==4369"
>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -# Stop ovn-controller on hv2 with --restart flag
>     -as hv2 ovs-appctl -t ovn-controller exit --restart
>     -
>     -# Now send the packet again. This time, it should still arrive
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -cat expected expected > expected2
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
>     -
>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>     -as hv2 start_daemon ovn-controller
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
>     -ovn_start
>     -
>     -# Set up a switch with some switch ports of varying address types
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl set logical_switch sw1
>     other_config:subnet=192.168.0.0/24 <http://192.168.0.0/24>
>     -
>     -ovn-nbctl lsp-add sw1 sw1-p1
>     -ovn-nbctl lsp-add sw1 sw1-p2
>     -ovn-nbctl lsp-add sw1 sw1-p3
>     -ovn-nbctl lsp-add sw1 sw1-p4
>     -
>     -ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1
>     aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
>     -ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
>     -ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
>     -ovn-nbctl lsp-set-addresses sw1-p4 "router"
>     -ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
>     -
>     -ovn-nbctl list logical_switch_port
>     -
>     -# Now try to add duplicate addresses on a new port. These should
>     all fail
>     -ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     10.0.0.1"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     10.0.0.2"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     aef0::1"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     aef0::2"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     192.168.0.2"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2
>     -])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>     192.168.0.3"], [1], [],
>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3
>     -])
>     -
>     -# Now try re-setting sw1-p1. This should succeed
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01
>     10.0.0.1 aef0::1"])
>     -
>     -# Now create a new switch and try setting IP addresses the same
>     as the
>     -# first switch. This should succeed.
>     -ovn-nbctl ls-add sw2
>     -ovn-nbctl lsp-add sw2 sw2-p1
>     -
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>     10.0.0.1"])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>     192.168.0.2"])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>     192.168.0.3"])
>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>     aef0::1"])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- router - check packet length - icmp defrag])
>     -AT_KEYWORDS([check packet length])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl lsp-add sw0 sw0-port1
>     -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
>     -
>     -ovn-nbctl lr-add lr0
>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
>     <http://10.0.0.1/24>
>     -ovn-nbctl lsp-add sw0 sw0-lr0
>     -ovn-nbctl lsp-set-type sw0-lr0 router
>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>     -
>     -ovn-nbctl ls-add public
>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> lsp-add public
>     public-lr0
>     -ovn-nbctl lsp-set-type public-lr0 router
>     -ovn-nbctl lsp-set-addresses public-lr0 router
>     -ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
>     -
>     -# localnet port
>     -ovn-nbctl lsp-add public ln-public
>     -ovn-nbctl lsp-set-type ln-public localnet
>     -ovn-nbctl lsp-set-addresses ln-public unknown
>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>     -
>     -ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
>     -ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
>     <http://10.0.0.0/24>
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -reset_pcap_file() {
>     -     local iface=$1
>     -     local pcap_file=$2
>     -     ovs-vsctl -- set Interface $iface
>     options:tx_pcap=dummy-tx.pcap \
>     - options:rxq_pcap=dummy-rx.pcap
>     -     rm -f ${pcap_file}*.pcap
>     -     ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     - options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -ip_to_hex() {
>     -     printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -test_ip_packet_larger() {
>     -    local icmp_pmtu_reply_expected=$1
>     -
>     -    # Send ip packet from sw0-port1 to outside
>     -    src_mac="505400000001" # sw-port1 mac
>     -    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
>     -    src_ip=`ip_to_hex 10 0 0 3`
>     -    dst_ip=`ip_to_hex 172 168 0 3`
>     -    # Set the packet length to 100.
>     -    pkt_len=0064
>     - packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
>     -    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
>     - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>     - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>     - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>     - orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>     -    packet=${packet}${orig_packet_l3}
>     -
>     -
>     gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064
>     -
>     -    # If icmp_pmtu_reply_expected is 0, it means the packet is
>     lesser than
>     -    # the gateway mtu and should be delivered to the provider
>     bridge via the
>     -    # localnet port.
>     -    # If icmp_pmtu_reply_expected is 1, it means the packet is
>     larger than
>     -    # the gateway mtu and ovn-controller should drop the packet
>     and instead
>     -    # generate ICMPv4  Destination Unreachable message with pmtu
>     set to 42.
>     -    if test $icmp_pmtu_reply_expected = 0; then
>     -        # Packet to expect at br-phys.
>     -        src_mac="000020201213"
>     -        dst_mac="00000012af11"
>     -        src_ip=`ip_to_hex 10 0 0 3`
>     -        dst_ip=`ip_to_hex 172 168 0 3`
>     - expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
>     - expected=${expected}${src_ip}${dst_ip}0304000000000000
>     - expected=${expected}000000000000000000000000000000000000
>     - expected=${expected}000000000000000000000000000000000000
>     - expected=${expected}000000000000000000000000000000000000
>     - expected=${expected}000000000000000000000000000000000000
>     -        echo $expected > br_phys_n1.expected
>     -        echo $gw_ip_garp >> br_phys_n1.expected
>     -    else
>     -        # MTU would be 100 - 18 = 82 (hex 0052)
>     -        mtu=0052
>     -        src_ip=`ip_to_hex 10 0 0 1`
>     -        dst_ip=`ip_to_hex 10 0 0 3`
>     -        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip
>     + payload))
>     -        reply_pkt_len=0080
>     -        ip_csum=bd91
>     -
>     icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
>     - icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
>     - icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
>     -        icmp_reply=${icmp_reply}${orig_packet_l3}
>     -        echo $icmp_reply > hv1-vif1.expected
>     -    fi
>     -
>     -    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
>     -    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>     -
>     -    # Send packet from sw0-port1 to outside
>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>     -
>     -    if test $icmp_pmtu_reply_expected = 0; then
>     -        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap],
>     [br_phys_n1.expected])
>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" hv1/vif1-tx.pcap > pkts
>     -        # hv1/vif1-tx.pcap can receive the GARP packet generated
>     by ovn-controller
>     -        # for the gateway router port. So ignore this packet.
>     -        cat pkts | grep -v $gw_ip_garp > packets
>     -        AT_CHECK([cat packets], [0], [])
>     -    else
>     -        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" hv1/br-phys_n1-tx.pcap  > \
>     -        pkts
>     -        # hv1/br-phys_n1-tx.pcap can receive the GARP packet
>     generated by ovn-controller
>     -        # for the gateway router port. So ignore this packet.
>     -        cat pkts | grep -v $gw_ip_garp > packets
>     -        AT_CHECK([cat packets], [0], [])
>     -    fi
>     -}
>     -
>     -ovn-nbctl show
>     -ovn-sbctl show
>     -
>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
>     -| grep "check_pkt_larger" | wc -l], [0], [[0
>     -]])
>     -dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep
>     _uuid | \
>     -awk '{print $3}')
>     -ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
>     -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
>     -
>     -# Set the gateway mtu to 100. If the packet length is > 100,
>     ovn-controller
>     -# should send icmp host not reachable with pmtu set to 100.
>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>     options:gateway_mtu=100
>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>     -OVS_WAIT_UNTIL([
>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>     "check_pkt_larger(100)" | \
>     -    wc -l` -eq 1
>     -])
>     -
>     -icmp_reply_expected=1
>     -test_ip_packet_larger $icmp_reply_expected
>     -
>     -# Set the gateway mtu to 500.
>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>     options:gateway_mtu=500
>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>     -OVS_WAIT_UNTIL([
>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>     "check_pkt_larger(500)" | \
>     -    wc -l` -eq 1
>     -])
>     -
>     -# Now the packet should be sent via the localnet port to br-phys.
>     -icmp_reply_expected=0
>     -test_ip_packet_larger $icmp_reply_expected
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IP packet buffering])
>     -AT_KEYWORDS([ip-buffering])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# One LR lr0 that has switches sw0 (192.168.1.0/24
>     <http://192.168.1.0/24>) and
>     -# sw1 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>     -#
>     -# Physical network:
>     -# Tw0 hypervisors hv[12].
>     -# hv1 hosts vif sw0-p0.
>     -# hv1 hosts vif sw1-p0.
>     -
>     -send_icmp_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ipv4_dst=$6 ip_chksum=$7 data=$8
>     -    shift 8
>     -
>     -    local ip_ttl=ff
>     -    local ip_len=001c
>     -    local
>     packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data}
>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
>     -}
>     -
>     -send_icmp6_packet() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>     -    shift 8
>     -
>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
>     -}
>     -
>     -get_arp_req() {
>     -    local eth_src=$1 spa=$2 tpa=$3
>     -    local
>     request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa}
>     -    echo $request
>     -}
>     -
>     -send_arp_reply() {
>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
>     -    local
>     request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa}
>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>     $request
>     -}
>     -
>     -send_na() {
>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 dst_ip=$6
>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>     -    local
>     request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src}
>     -
>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>     $request
>     -}
>     -
>     -get_nd() {
>     -    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>     -
>     request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src}
>     -
>     -    echo $request
>     -}
>     -
>     -net_add n1
>     -
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -
>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl ls-add sw1
>     -
>     -ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24> 2001:0:0:0:0:0:0:1/64
>     -ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
>     -    type=router options:router-port=sw0 \
>     -    -- lsp-set-addresses rp-sw0 router
>     -
>     -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64
>     -ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
>     -    type=router options:router-port=sw1 \
>     -    -- lsp-set-addresses rp-sw1 router
>     -
>     -ovn-nbctl lsp-add sw0 sw0-p0 \
>     -    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2
>     2001::2"
>     -
>     -ovn-nbctl lsp-add sw1 sw1-p0 \
>     -    -- lsp-set-addresses sw1-p0 unknown
>     -
>     -OVN_POPULATE_ARP
>     -ovn-nbctl --wait=hv sync
>     -
>     -ip_to_hex() {
>     -    printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -src_mac=f00000010203
>     -src_ip=$(ip_to_hex 192 168 1 2)
>     -src_ip6=20010000000000000000000000000002
>     -
>     -router_mac0=000001010203
>     -router_mac1=000002010203
>     -router_ip=$(ip_to_hex 172 16 1 1)
>     -router_ip6=20020000000000000000000000000001
>     -
>     -dst_mac=001122334455
>     -dst_ip=$(ip_to_hex 172 16 1 10)
>     -dst_ip6=20020000000000000000000000000010
>     -
>     -data=0800bee4391a0001
>     -
>     -send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 $data
>     -send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
>     -echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
>     -echo
>     "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}"
>     >> expected
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -nd_ip=ff0200000000000000000001ff000010
>     -ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
>     -
>     -send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
>     -echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
>     -echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >>
>     expected
>     -send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
>     -
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- neighbor update on same HV])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# A public switch (pub) with a localnet port connected to two LRs
>     (lr0 and lr1)
>     -# each with a distributed gateway port.
>     -# Two VMs: lp0 on sw0 connected to lr0
>     -#          lp1 on sw1 connected to lr1
>     -#
>     -# This test adds a floating IP to each VM so when they are bound
>     to the same
>     -# hypervisor, it checks that the GARP sent by ovn-controller
>     causes the
>     -# MAC_Binding entries to be updated properly on each logical router.
>     -# It will also capture packets on the physical interface to make
>     sure that the
>     -# GARPs have been sent out to the external network as well.
>     -
>     -# Create logical switches
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl ls-add pub
>     -
>     -# Created localnet port on public switch
>     -ovn-nbctl lsp-add pub ln-pub
>     -ovn-nbctl lsp-set-type ln-pub localnet
>     -ovn-nbctl lsp-set-addresses ln-pub unknown
>     -ovn-nbctl lsp-set-options ln-pub network_name=phys
>     -
>     -# Create logical routers and connect them to public switch
>     -ovn-nbctl create Logical_Router name=lr0
>     -ovn-nbctl create Logical_Router name=lr1
>     -
>     -ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
>     <http://172.24.4.220/24>
>     -ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
>     -    type=router options:router-port=lr0-pub
>     options:nat-addresses="router" addresses="router"
>     -ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
>     <http://172.24.4.221/24>
>     -ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
>     -    type=router options:router-port=lr1-pub
>     options:nat-addresses="router" addresses="router"
>     -
>     -ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
>     -ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
>     -
>     -# Connect sw0 and sw1 to lr0 and lr1
>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>     <http://10.0.0.254/24>
>     -ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0
>     type=router \
>     -    options:router-port=lr0-sw0 addresses="router"
>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
>     <http://20.0.0.254/24>
>     -ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1
>     type=router \
>     -    options:router-port=lr1-sw1 addresses="router"
>     -
>     -
>     -# Add SNAT rules
>     -ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
>     <http://10.0.0.0/24>
>     -ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
>     <http://20.0.0.0/24>
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 172.24.4.1
>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>     -
>     -ovs-vsctl add-port br-int vif0 -- set Interface vif0
>     external-ids:iface-id=lp0
>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>     external-ids:iface-id=lp1
>     -
>     -ovn-nbctl lsp-add sw0 lp0
>     -ovn-nbctl lsp-add sw1 lp1
>     -ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
>     -ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
>     -
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>     -
>     -# Create two floating IPs, one for each VIF
>     -ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
>     -ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
>     -
>     -# Check that the MAC_Binding entries have been properly created
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>     logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>     logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
>     -
>     -# Check that the GARPs went also to the external physical network
>     -# Wait until at least 4 packets have arrived and copy them to a
>     separate file as
>     -# more GARPs are expected in the capture in order to avoid race
>     conditions.
>     -OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>     <http://ovs-pcap.in>" hv1/br-phys-tx.pcap | wc -l` -gt 4])
>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>     hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
>     -
>     -# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
>     -echo
>     "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464"
>     > expout
>     -# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
>     -echo
>     "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc"
>     >> expout
>     -# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
>     -echo
>     "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8"
>     >> expout
>     -# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
>     -echo
>     "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd"
>     >> expout
>     -AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
>     -#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
>     -
>     -OVN_CLEANUP([hv1])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ipam to non-ipam])
>     -ovn_start
>     -
>     -ovn-nbctl --wait=hv set NB_Global .
>     options:mac_prefix="0a:00:00:00:00:00"
>     -ovn-nbctl ls-add sw0
>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>     subnet=192.168.1.0/24 <http://192.168.1.0/24>
>     -
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>     dynamic_addresses], [0],
>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>     -])
>     -
>     -ovn-nbctl --wait=sb lsp-set-addresses p0 router
>     -
>     -ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
>     -
>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>     dynamic_addresses], [0], [[[]]
>     -])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- ipam router ports])
>     -ovn_start
>     -
>     -ovn-nbctl ls-add sw
>     -ovn-nbctl set logical_switch sw
>     other-config:subnet=192.168.1.0/24 <http://192.168.1.0/24>
>     -
>     -for i in 2 3 4; do
>     -    ovn-nbctl lr-add ro$i
>     -    ovn-nbctl lsp-add sw swp$i
>     -    ovn-nbctl --wait=sb lsp-set-addresses swp$i
>     "02:00:00:00:00:0$i dynamic"
>     -    cidr=$(ovn-nbctl get logical_switch_port swp$i
>     dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
>     -    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 --
>     set logical_switch_port swp$i type=router
>     options:router-port=rop$i addresses=router;
>     -    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i
>     networks], [0], [[["192.168.1.$i/24"]]
>     -])
>     -done
>     -
>     -ovn-nbctl list logical_switch_port
>     -ovn-nbctl list logical_router_port
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- test transport zones])
>     -ovn_start
>     -
>     -net_add n1
>     -for i in 1 2 3 4 5; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.$i.1
>     -done
>     -
>     -dnl Wait for the changes to be propagated
>     -ovn-nbctl --wait=sb --timeout=3 sync
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -dnl Assert that each Chassis has a tunnel formed to every other
>     Chassis
>     -as hv1
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv2
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv3
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv4
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv5
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -]])
>     -
>     -dnl Let's now add some Chassis to different transport zones
>     -dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
>     -dnl   should have tunnels formed between the other two Chassis
>     (hv2 and hv3)
>     -dnl
>     -dnl * hv2: Will be part of one transport zone: tz1. It should
>     have a tunnel
>     -dnl   to hv1 but not to hv3
>     -dnl
>     -dnl * hv3: Will be part of one transport zone: tz2. It should
>     have a tunnel
>     -dnl   to hv1 but not to hv2
>     -dnl
>     -dnl * hv4 and hv5: Will not have any TZ set so they will keep the
>     tunnels
>     -dnl   between themselves and remove the tunnels to other Chassis
>     which now
>     -dnl   belongs to some TZs
>     -dnl
>     -as hv1
>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
>     -
>     -as hv2
>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
>     -
>     -as hv3
>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
>     -
>     -dnl Wait for the changes to be propagated
>     -ovn-nbctl --wait=sb --timeout=3 sync
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -as hv1
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv2-0
>     -ovn-hv3-0
>     -]])
>     -
>     -as hv2
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -]])
>     -
>     -as hv3
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -]])
>     -
>     -as hv4
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv5-0
>     -]])
>     -
>     -as hv5
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv4-0
>     -]])
>     -
>     -dnl Removing the transport zones should make all Chassis to create
>     -dnl tunnels between every other Chassis again
>     -for i in 1 2 3; do
>     -    as hv$i
>     -    ovs-vsctl remove open . external-ids ovn-transport-zones
>     -done
>     -
>     -dnl Wait for the changes to be propagated
>     -ovn-nbctl --wait=sb --timeout=3 sync
>     -ovn-nbctl --wait=hv --timeout=3 sync
>     -
>     -as hv1
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv2
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv3
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv4-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv4
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv5-0
>     -]])
>     -
>     -as hv5
>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>     type="geneve" | awk NF | sort], [0],
>     -[[ovn-hv1-0
>     -ovn-hv2-0
>     -ovn-hv3-0
>     -ovn-hv4-0
>     -]])
>     -
>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis
>     mac])
>     -ovn_start
>     -
>     -
>     -# In this test cases we create 2 switches, all connected to same
>     -# physical network (through br-phys on each HV). Each switch has
>     -# 1 VIF. Each HV has 1 VIF port. The first digit
>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>     -# lp23 means VIF 3 on hv2.
>     -#
>     -# Each switch's VLAN tag and their logical switch ports are:
>     -#   - ls1:
>     -#       - tagged with VLAN 101
>     -#       - ports: lp11
>     -#   - ls2:
>     -#       - tagged with VLAN 201
>     -#       - ports: lp22
>     -#
>     -# Note: a localnet port is created for each switch to connect to
>     -# physical network.
>     -
>     -for i in 1 2; do
>     -    ls_name=ls$i
>     -    ovn-nbctl ls-add $ls_name
>     -    ln_port_name=ln$i
>     -    if test $i -eq 1; then
>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>     -    elif test $i -eq 2; then
>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
>     -    fi
>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>     -done
>     -
>     -# lsp_to_ls LSP
>     -#
>     -# Prints the name of the logical switch that contains LSP.
>     -lsp_to_ls () {
>     -    case $1 in dnl (
>     -        lp?[[11]]) echo ls1 ;; dnl (
>     -        lp?[[12]]) echo ls2 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -vif_to_ls () {
>     -    case $1 in dnl (
>     -        vif?[[11]]) echo ls1 ;; dnl (
>     -        vif?[[12]]) echo ls2 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -hv_to_num () {
>     -    case $1 in dnl (
>     -        hv1) echo 1 ;; dnl (
>     -        hv2) echo 2 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -vif_to_num () {
>     -    case $1 in dnl (
>     -        vif22) echo 22 ;; dnl (
>     -        vif21) echo 21 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -vif_to_hv () {
>     -    case $1 in dnl (
>     -        vif[[1]]?) echo hv1 ;; dnl (
>     -        vif[[2]]?) echo hv2 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -vif_to_lrp () {
>     -    echo router-to-`vif_to_ls $1`
>     -}
>     -
>     -hv_to_chassis_mac () {
>     -     case $1 in dnl (
>     -        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
>     -        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
>     -        *) AT_FAIL_IF([:]) ;;
>     -    esac
>     -}
>     -
>     -ip_to_hex() {
>     -       printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -net_add n1
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovs-vsctl set open .
>     external-ids:ovn-bridge-mappings=phys:br-phys
>     -    ovs-vsctl set open .
>     external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    ovs-vsctl add-port br-int vif$i$i -- \
>     -        set Interface vif$i$i external-ids:iface-id=lp$i$i \
>     - options:tx_pcap=hv$i/vif$i$i-tx.pcap \
>     - options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
>     -                              ofport-request=$i$i
>     -
>     -    lsp_name=lp$i$i
>     -    ls_name=$(lsp_to_ls $lsp_name)
>     -
>     -    ovn-nbctl lsp-add $ls_name $lsp_name
>     -    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i
>     192.168.$i.$i"
>     -    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
>     -
>     -    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
>     -
>     -done
>     -
>     -ovn-nbctl lr-add router
>     -ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03
>     192.168.1.3/24
>     -ovn-nbctl <http://192.168.1.3/24-ovn-nbctl> lrp-add router
>     router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 <http://192.168.2.3/24>
>     -
>     -ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port
>     ls1-to-router type=router options:router-port=router-to-ls1 --
>     lsp-set-addresses ls1-to-router router
>     -ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port
>     ls2-to-router type=router options:router-port=router-to-ls2 --
>     lsp-set-addresses ls2-to-router router
>     -
>     -ovn-nbctl --wait=sb sync
>     -#ovn-sbctl dump-flows
>     -
>     -ovn-nbctl show
>     -ovn-sbctl show
>     -
>     -OVN_POPULATE_ARP
>     -
>     -test_ip() {
>     -    # This packet has bad checksums but logical L3 routing
>     doesn't check.
>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>     -    local
>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
>     -    shift; shift; shift; shift; shift
>     -    hv=`vif_to_hv $inport`
>     -    hv_num=`hv_to_num $hv`
>     -    chassis_mac=`hv_to_chassis_mac $hv`
>     -    as $hv ovs-appctl netdev-dummy/receive $inport $packet
>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>     -    in_ls=`vif_to_ls $inport`
>     -    in_lrp=`vif_to_lrp $inport`
>     -    for outport; do
>     -        out_ls=`vif_to_ls $outport`
>     -        if test $in_ls = $out_ls; then
>     -            # Ports on the same logical switch receive exactly
>     the same packet.
>     -            echo $packet
>     -        else
>     -            # Routing decrements TTL and updates source and dest MAC
>     -            # (and checksum).
>     -            outport_num=`vif_to_num $outport`
>     -            out_lrp=`vif_to_lrp $outport`
>     -            echo
>     f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
>     -        fi >> $outport.expected
>     -    done
>     -}
>     -
>     -# Dump a bunch of info helpful for debugging if there's a failure.
>     -
>     -echo "------ OVN dump ------"
>     -ovn-nbctl show
>     -ovn-sbctl show
>     -
>     -echo "------ hv1 dump ------"
>     -as hv1 ovs-vsctl show
>     -as hv1 ovs-vsctl list Open_Vswitch
>     -
>     -echo "------ hv2 dump ------"
>     -as hv2 ovs-vsctl show
>     -as hv2 ovs-vsctl list Open_Vswitch
>     -
>     -echo "Send traffic"
>     -sip=`ip_to_hex 192 168 1 1`
>     -dip=`ip_to_hex 192 168 2 2`
>     -test_ip vif11 f00000000011  000001010203 $sip $dip vif22
>     -
>     -echo "----------- Post Traffic hv1 dump -----------"
>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -as hv1 ovs-appctl fdb/show br-phys
>     -
>     -echo "----------- Post Traffic hv2 dump -----------"
>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>     -as hv2 ovs-appctl fdb/show br-phys
>     -
>     -OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
>     -
>     -OVN_CLEANUP([hv1],[hv2])
>     -
>     -AT_CLEANUP
>     -
>     -# Run ovn-nbctl in daemon mode, change to a backup database and
>     verify that
>     -# an insert operation is not allowed.
>     -AT_SETUP([ovn -- can't write to a backup database server instance])
>     -ovn_start
>     -on_exit 'kill $(cat ovn-nbctl.pid)'
>     -export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
>     -
>     -AT_CHECK([ovn-nbctl ls-add sw0])
>     -as ovn-nb
>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>     grep active | wc -l], [0], [1
>     -])
>     -ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server
>     tcp:192.0.2.2:6641 <http://192.0.2.2:6641>
>     -ovs-appctl -t ovsdb-server ovsdb-server/connect-active-ovsdb-server
>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>     grep -c backup], [0], [1
>     -])
>     -AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
>     -[ovn-nbctl: transaction error: {"details":"insert operation not
>     allowed when database server is in read only mode","error":"not
>     allowed"}
>     -])
>     -
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- controller event])
>     -AT_KEYWORDS([ovn_controller_event])
>     -ovn_start
>     -
>     -# Create hypervisors hv[12].
>     -# Add vif1[12] to hv1, vif2[12] to hv2
>     -# Add all of the vifs to a single logical switch sw0.
>     -
>     -net_add n1
>     -ovn-nbctl ls-add sw0
>     -for i in 1 2; do
>     -    sim_add hv$i
>     -    as hv$i
>     -    ovs-vsctl add-br br-phys
>     -    ovn_attach n1 br-phys 192.168.0.$i
>     -
>     -    for j in 1 2; do
>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>     192.168.1.$i$j"
>     -
>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>     -                set interface vif$i$j \
>     -                external-ids:iface-id=sw0-p$i$j \
>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>     -                ofport-request=$i$j
>     -    done
>     -done
>     -
>     -ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
>     -ovn-nbctl lb-add lb0 192.168.1.100:80 <http://192.168.1.100:80> ""
>     -ovn-nbctl ls-lb-add sw0 lb0
>     -uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer
>     name=lb0)
>     -
>     -OVN_POPULATE_ARP
>     -ovn-nbctl --timeout=3 --wait=hv sync
>     -ovn-sbctl lflow-list
>     -as hv1 ovs-ofctl dump-flows br-int
>     -
>     -packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 &&
>     eth.dst==00:00:00:00:00:21 &&
>     -       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 &&
>     ip4.dst==192.168.1.100 &&
>     -       tcp && tcp.src==10000 && tcp.dst==80"
>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>     -
>     -ovn-sbctl list controller_event
>     -uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_type], [0], [dnl
>     -empty_lb_backends
>     -])
>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip],
>     [0], [dnl
>     -"192.168.1.100:80 <http://192.168.1.100:80>"
>     -])
>     -AT_CHECK([ovn-sbctl get controller_event $uuid
>     event_info:protocol], [0], [dnl
>     -tcp
>     -])
>     -AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid
>     event_info:load_balancer], [0], [dnl
>     -"$uuid_lb"
>     -])
>     -AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], [dnl
>     -1
>     -])
>     -
>     -OVN_CLEANUP([hv1], [hv2])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- IGMP snoop/querier])
>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>     -ovn_start
>     -
>     -# Logical network:
>     -# Two independent logical switches (sw1 and sw2).
>     -# sw1:
>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>     -#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
>     -#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
>     -# sw2:
>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>     -#   - 1 port bound on hv1 (sw2-p1)
>     -#   - 1 port bound on hv2 (sw2-p2)
>     -#   - IGMP Querier from 20.0.0.254
>     -
>     -reset_pcap_file() {
>     -    local iface=$1
>     -    local pcap_file=$2
>     -    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>     -options:rxq_pcap=dummy-rx.pcap
>     -    rm -f ${pcap_file}*.pcap
>     -    ovs-vsctl -- set Interface $iface
>     options:tx_pcap=${pcap_file}-tx.pcap \
>     -options:rxq_pcap=${pcap_file}-rx.pcap
>     -}
>     -
>     -ip_to_hex() {
>     -     printf "%02x%02x%02x%02x" "$@"
>     -}
>     -
>     -#
>     -# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP REC_TYPE
>     -#                     IGMP_CSUM OUTFILE
>     -#
>     -# This shell function causes an IGMPv3 report to be received on
>     INPORT of HV.
>     -# The packet's content has Ethernet destination 01:00:5E:00:00:22
>     and source
>     -# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
>     -# GROUP is the IP multicast group to be joined/to leave (based on
>     REC_TYPE).
>     -# REC_TYPE == 04: join GROUP
>     -# REC_TYPE == 03: leave GROUP
>     -# The packet hexdump is also stored in OUTFILE.
>     -#
>     -send_igmp_v3_report() {
>     -    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 group=$6
>     -    local rec_type=$7 igmp_chksum=$8 outfile=$9
>     -
>     -    local eth_dst=01005e000016
>     -    local ip_dst=$(ip_to_hex 224 0 0 22)
>     -    local ip_ttl=01
>     -    local ip_ra_opt=94040000
>     -
>     -    local igmp_type=2200
>     -    local num_rec=00000001
>     -    local aux_dlen=00
>     -    local num_src=0000
>     -
>     -    local eth=${eth_dst}${eth_src}0800
>     -    local
>     ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt}
>     -    local
>     igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group}
>     -    local packet=${eth}${ip}${igmp}
>     -
>     -    echo ${packet} >> ${outfile}
>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>     -}
>     -
>     -#
>     -# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
>     -#
>     -# This shell function builds an IGMPv3 general query from ETH_SRC
>     and IP_SRC
>     -# and stores the hexdump of the packet in OUTFILE.
>     -#
>     -store_igmp_v3_query() {
>     -    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
>     -
>     -    local eth_dst=01005e000001
>     -    local ip_dst=$(ip_to_hex 224 0 0 1)
>     -    local ip_ttl=01
>     -    local igmp_type=11
>     -    local max_resp=0a
>     -    local igmp_chksum=eeeb
>     -    local addr=00000000
>     -
>     -    local eth=${eth_dst}${eth_src}0800
>     -    local
>     ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
>     -    local igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
>     -    local packet=${eth}${ip}${igmp}
>     -
>     -    echo ${packet} >> ${outfile}
>     -}
>     -
>     -#
>     -# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST
>     IP_LEN
>     -#    IP_PROTO DATA OUTFILE
>     -#
>     -# This shell function causes an IP multicast packet to be
>     received on INPORT
>     -# of HV.
>     -# The hexdump of the packet is stored in OUTFILE.
>     -#
>     -send_ip_multicast_pkt() {
>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 ip_dst=$6
>     -    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} outfile=${11}
>     -
>     -    local ip_ttl=20
>     -
>     -    local eth=${eth_dst}${eth_src}0800
>     -    local
>     ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst}
>     -    local packet=${eth}${ip}${data}
>     -
>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>     -    echo ${packet} >> ${outfile}
>     -}
>     -
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl ls-add sw2
>     -
>     -ovn-nbctl lsp-add sw1 sw1-p11
>     -ovn-nbctl lsp-add sw1 sw1-p12
>     -ovn-nbctl lsp-add sw1 sw1-p21
>     -ovn-nbctl lsp-add sw1 sw1-p22
>     -ovn-nbctl lsp-add sw2 sw2-p1
>     -ovn-nbctl lsp-add sw2 sw2-p2
>     -
>     -net_add n1
>     -sim_add hv1
>     -as hv1
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.1
>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>     -    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>     -    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>     -    ofport-request=1
>     -
>     -sim_add hv2
>     -as hv2
>     -ovs-vsctl add-br br-phys
>     -ovn_attach n1 br-phys 192.168.0.2
>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv2-vif2 -- \
>     -    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
>     -    options:tx_pcap=hv2/vif2-tx.pcap \
>     -    options:rxq_pcap=hv2/vif2-rx.pcap \
>     -    ofport-request=1
>     -ovs-vsctl -- add-port br-int hv2-vif3 -- \
>     -    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
>     -    options:tx_pcap=hv2/vif3-tx.pcap \
>     -    options:rxq_pcap=hv2/vif3-rx.pcap \
>     -    ofport-request=1
>     -
>     -OVN_POPULATE_ARP
>     -
>     -# Enable IGMP snooping on sw1.
>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>     -
>     -# No IGMP query should be generated by sw1 (mcast_querier="false").
>     -truncate -s 0 expected
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
>     -
>     -ovn-nbctl --wait=hv sync
>     -
>     -# Inject IGMP Join for 239.0.1.68 on sw1-p11.
>     -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 IGMP Join for 239.0.1.68 on sw1-p21.
>     -send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0
>     2) f9f9 \
>     -    $(ip_to_hex 239 0 1 68) 04 e9b9 \
>     -    /dev/null
>     -
>     -# Check that the IGMP Group is learned on both hv.
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    test "${total_entries}" = "2"
>     -])
>     -
>     -# Send traffic and make sure it gets forwarded only on the two
>     ports that
>     -# joined.
>     -truncate -s 0 expected
>     -truncate -s 0 expected_empty
>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>     -    000000000001 01005e000144 \
>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>     -    e518e518000a3b3a0000 \
>     -    expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>     -
>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
>     -send_igmp_v3_report hv1-vif1 hv1 \
>     -    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
>     -    $(ip_to_hex 239 0 1 68) 03 eab9 \
>     -    /dev/null
>     -
>     -# Check IGMP_Group table on both HV.
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    test "${total_entries}" = "1"
>     -])
>     -
>     -# Send traffic traffic and make sure it gets forwarded only on
>     the port that
>     -# joined.
>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>     -as hv2 reset_pcap_file hv2-vif1 hv2/vif1
>     -truncate -s 0 expected
>     -truncate -s 0 expected_empty
>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>     -    000000000001 01005e000144 \
>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>     -    e518e518000a3b3a0000 \
>     -    expected
>     -
>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>     -
>     -# Flush IGMP groups.
>     -ovn-sbctl ip-multicast-flush sw1
>     -ovn-nbctl --wait=hv -t 3 sync
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    test "${total_entries}" = "0"
>     -])
>     -
>     -# Enable IGMP snooping and querier on sw2 and set query interval
>     to minimum.
>     -ovn-nbctl set Logical_Switch sw2 \
>     -    other_config:mcast_snoop="true" \
>     -    other_config:mcast_querier="true" \
>     -    other_config:mcast_query_interval=1 \
>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>     -    other_config:mcast_ip4_src="20.0.0.254"
>     -
>     -# Wait for 1 query interval (1 sec) and check that two queries
>     are generated.
>     -truncate -s 0 expected
>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>     expected
>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>     expected
>     -
>     -sleep 1
>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
>     -
>     -OVN_CLEANUP([hv1], [hv2])
>     -AT_CLEANUP
>     diff --git a/tests/system-ovn.at <http://system-ovn.at>
>     b/tests/system-ovn.at <http://system-ovn.at>
>     deleted file mode 100644
>     index f88ad31..0000000
>     --- a/tests/system-ovn.at <http://system-ovn.at>
>     +++ /dev/null
>     @@ -1,1667 +0,0 @@
>     -AT_BANNER([system-ovn])
>     -
>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and
>     DNAT])
>     -AT_KEYWORDS([ovnnat])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>     -# to it.  R2 is a gateway router on which we add NAT rules.
>     -#
>     -#    foo -- R1 -- join - R2 -- alice
>     -#           |
>     -#    bar ----
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Static routes.
>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>     -"192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>     -
>     -# Add a DNAT rule.
>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>     logical_ip=192.168.1.2 \
>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>     -
>     -# Add a SNAT rule
>     -ovn-nbctl -- --id=@nat create nat type="snat"
>     logical_ip=192.168.2.2 \
>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>     -
>     -# wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>     'nat(src=30.0.0.1)'])
>     -
>     -# 'alice1' should be able to ping 'foo1' directly.
>     -NS_CHECK_EXEC([alice1], [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
>     -])
>     -
>     -# North-South DNAT: 'alice1' should also be able to ping 'foo1'
>     via 30.0.0.2
>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# Check conntrack entries.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>     traffic
>     -# from 30.0.0.1
>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# Add static routes to handle east-west NAT.
>     -ovn-nbctl lr-route-add R1 30.0.0.0/24 <http://30.0.0.0/24> 20.0.0.2
>     -
>     -# wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -
>     -# Flush conntrack entries for easier output parsing of next test.
>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>     -
>     -# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' receives it.
>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# As we have a static route that sends all packets with destination
>     -# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to
>     192.168.1.2
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1,
>     the source is
>     -# SNATted and 'foo1' receives it.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy SNAT])
>     -AT_KEYWORDS([ovnnat])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) connected
>     -# to it.  R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it.
>     -# R2 is a gateway router on which we add NAT rules.
>     -#
>     -#    foo -- R1 -- join - R2 -- alice
>     -
>     -ovn-nbctl lr-add R1
>     -ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add join
>     -
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Static routes.
>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Add a SNAT rule
>     -ovn-nbctl -- --id=@nat create nat type="snat"
>     logical_ip=192.168.1.2 \
>     -    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
>     -
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>     'nat(src=172.16.1.1)'])
>     -
>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>     traffic
>     -# from 172.16.1.1
>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
>     -AT_KEYWORDS([ovnnat])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>     LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it. Note how both alice and
>     -# bob have the same subnet behind it.  We are trying to simulate
>     external
>     -# network via those 2 switches. In real world the switch ports of
>     these
>     -# switches will have addresses set as "unknown" to make them
>     learning switches.
>     -# Or those switches will be "localnet" ones.
>     -#
>     -#    foo -- R1 -- join - R2 -- alice
>     -#           |          |
>     -#    bar ----          - R3 --- bob
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add bob
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect bob to R3
>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>     <http://172.16.1.2/24>
>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>     -    type=router options:router-port=bob
>     addresses=\"00:00:03:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Connect R3 to join
>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>     <http://20.0.0.3/24>
>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>     -    type=router options:router-port=R3_join
>     addresses='"00:00:04:01:02:05"'
>     -
>     -# Install static routes with source ip address as the policy for
>     routing.
>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>     go via R3.
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>     <http://192.168.1.0/24> 20.0.0.2
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>     <http://192.168.2.0/24> 20.0.0.3
>     -
>     -# Static routes.
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# For gateway routers R2 and R3, set a force SNAT rule.
>     -ovn-nbctl set logical_router R2 options:dnat_force_snat_ip=20.0.0.2
>     -ovn-nbctl set logical_router R3 options:dnat_force_snat_ip=20.0.0.3
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>     -"192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>     -
>     -# Logical port 'bob1' in switch 'bob'.
>     -ADD_NAMESPACES(bob1)
>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>     -         "172.16.1.2")
>     -ovn-nbctl lsp-add bob bob1 \
>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>     -
>     -# Router R2
>     -# Add a DNAT rule.
>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>     logical_ip=192.168.1.2 \
>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>     -
>     -# Add a SNAT rule
>     -ovn-nbctl -- --id=@nat create nat type="snat"
>     logical_ip=192.168.1.2 \
>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>     -
>     -# Router R3
>     -# Add a DNAT rule.
>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>     logical_ip=192.168.1.2 \
>     -    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
>     -
>     -# Add a SNAT rule
>     -ovn-nbctl -- --id=@nat create nat type="snat"
>     logical_ip=192.168.2.2 \
>     -    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
>     -
>     -# wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>     'nat(src=30.0.0.4)'])
>     -
>     -# North-South DNAT: 'alice1' should be able to ping 'foo1' via
>     30.0.0.2
>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# Check conntrack entries.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# But foo1 should receive traffic from 20.0.0.2
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# North-South DNAT: 'bob1' should be able to ping 'foo1' via 30.0.0.3
>     -NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# Check conntrack entries.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# But foo1 should receive traffic from 20.0.0.3
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.3) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives traffic
>     -# from 30.0.0.4
>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.4) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>     traffic
>     -# from 30.0.0.1
>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- load-balancing])
>     -AT_KEYWORDS([ovnlb])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# 2 logical switches "foo" (192.168.1.0/24
>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>     <http://172.16.1.0/24>)
>     -# connected to a router R1.
>     -# foo has foo1 to act as a client.
>     -# bar has bar1, bar2, bar3 to act as servers.
>     -#
>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Create logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:0f:01:02:03", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
>     -
>     -ADD_NAMESPACES(bar2)
>     -ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24
>     <http://172.16.1.3/24>", "f0:00:0f:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add bar bar2 \
>     --- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
>     -
>     -ADD_NAMESPACES(bar3)
>     -ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24
>     <http://172.16.1.4/24>", "f0:00:0f:01:02:05", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add bar bar3 \
>     --- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
>     -
>     -# Config OVN load-balancer with a VIP.
>     -uuid=`ovn-nbctl  create load_balancer
>     vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>     -
>     -# Create another load-balancer with another VIP.
>     -uuid=`ovn-nbctl create load_balancer
>     vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
>     -ovn-nbctl add logical_switch foo load_balancer $uuid
>     -
>     -# Config OVN load-balancer with another VIP (this time with ports).
>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>     <http://30.0.0.2:8000>"'='"172.16.1.2:80
>     <http://172.16.1.2:80>,172.16.1.3:80
>     <http://172.16.1.3:80>,172.16.1.4:80 <http://172.16.1.4:80>"'
>     -
>     -# Wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>     -grep 'nat(dst=172.16.1.4:80)'])
>     -
>     -# Start webservers in 'bar1', 'bar2' and 'bar3'.
>     -OVS_START_L7([bar1], [http])
>     -OVS_START_L7([bar2], [http])
>     -OVS_START_L7([bar3], [http])
>     -
>     -dnl Should work with the virtual IP 30.0.0.1 address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Should work with the virtual IP 30.0.0.3 address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Test load-balancing that includes L4 ports in NAT.
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>     wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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"])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- load-balancing - same subnet.])
>     -AT_KEYWORDS([ovnlb])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# 1 logical switch "foo" (192.168.1.0/24 <http://192.168.1.0/24>)
>     connected to router R1.
>     -# foo has foo1, foo2, foo3, foo4 as logical ports.
>     -#
>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>     Router is needed for default
>     -# gateway. We will test load-balancing with foo1 as a client and
>     foo2, foo3 and
>     -# foo4 as servers.
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl ls-add foo
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch
>     'foo'.
>     -ADD_NAMESPACES(foo1, foo2, foo3, foo4)
>     -for i in `seq 1 4`; do
>     -    j=`expr $i + 1`
>     -    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24",
>     "f0:00:00:01:02:0$j", \
>     -             "192.168.1.1")
>     -    ovn-nbctl lsp-add foo foo$i \
>     -        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 192.168.1.$j"
>     -done
>     -
>     -# Config OVN load-balancer with a VIP.
>     -uuid=`ovn-nbctl  create load_balancer
>     vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>     -
>     -# Config OVN load-balancer with another VIP (this time with ports).
>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>     <http://30.0.0.2:8000>"'='"192.168.1.3:80
>     <http://192.168.1.3:80>,192.168.1.4:80
>     <http://192.168.1.4:80>,192.168.1.5:80 <http://192.168.1.5:80>"'
>     -
>     -# Wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>     -grep 'nat(dst=192.168.1.5:80)'])
>     -
>     -# Start webservers in 'foo2', 'foo3' and 'foo4'.
>     -OVS_START_L7([foo2], [http])
>     -OVS_START_L7([foo3], [http])
>     -OVS_START_L7([foo4], [http])
>     -
>     -dnl Should work with the virtual IP address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Test load-balancing that includes L4 ports in NAT.
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>     wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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"])
>     -AT_CLEANUP
>     -
>     -AT_SETUP([ovn -- load balancing in gateway router])
>     -AT_KEYWORDS([ovnlb])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>     -# to it.  R2 is a gateway router on which we add load-balancing
>     rules.
>     -#
>     -#    foo -- R1 -- join - R2 -- alice
>     -#           |
>     -#    bar ----
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Static routes.
>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>     20.0.0.2
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>     -"192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>     -
>     -# Config OVN load-balancer with a VIP.
>     -uuid=`ovn-nbctl  create load_balancer
>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>     -
>     -# Config OVN load-balancer with another VIP (this time with ports).
>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>     <http://30.0.0.2:8000>"'='"192.168.1.2:80
>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>     -
>     -# Add SNAT rule to make sure that Load-balancing still works with
>     a SNAT rule.
>     -ovn-nbctl -- --id=@nat create nat type="snat"
>     logical_ip=192.168.2.2 \
>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>     -
>     -
>     -# Wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>     -grep 'nat(dst=192.168.2.2:80)'])
>     -
>     -# Start webservers in 'foo1', 'bar1'.
>     -OVS_START_L7([foo1], [http])
>     -OVS_START_L7([bar1], [http])
>     -
>     -dnl Should work with the virtual IP address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Test load-balancing that includes L4 ports in NAT.
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000
>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>     wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- multiple gateway routers, load-balancing])
>     -AT_KEYWORDS([ovnlb])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>     LS "join"
>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>     connected to it. Note how both alice and
>     -# bob have the same subnet behind it.  We are trying to simulate
>     external
>     -# network via those 2 switches. In real world the switch ports of
>     these
>     -# switches will have addresses set as "unknown" to make them
>     learning switches.
>     -# Or those switches will be "localnet" ones.
>     -#
>     -#    foo -- R1 -- join - R2 -- alice
>     -#           |          |
>     -#    bar ----          - R3 --- bob
>     -
>     -ovn-nbctl create Logical_Router name=R1
>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -ovn-nbctl ls-add bob
>     -ovn-nbctl ls-add join
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo
>     addresses=\"00:00:01:01:02:03\"
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar
>     addresses=\"00:00:01:01:02:04\"
>     -
>     -# Connect alice to R2
>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24>
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice
>     addresses=\"00:00:02:01:02:03\"
>     -
>     -# Connect bob to R3
>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>     <http://172.16.1.2/24>
>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>     -    type=router options:router-port=bob
>     addresses=\"00:00:03:01:02:03\"
>     -
>     -# Connect R1 to join
>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>     <http://20.0.0.1/24>
>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>     -    type=router options:router-port=R1_join
>     addresses='"00:00:04:01:02:03"'
>     -
>     -# Connect R2 to join
>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>     <http://20.0.0.2/24>
>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>     -    type=router options:router-port=R2_join
>     addresses='"00:00:04:01:02:04"'
>     -
>     -# Connect R3 to join
>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>     <http://20.0.0.3/24>
>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>     -    type=router options:router-port=R3_join
>     addresses='"00:00:04:01:02:05"'
>     -
>     -# Install static routes with source ip address as the policy for
>     routing.
>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>     go via R3.
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>     <http://192.168.1.0/24> 20.0.0.2
>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>     <http://192.168.2.0/24> 20.0.0.3
>     -
>     -# Static routes.
>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>     20.0.0.1
>     -
>     -# For gateway routers R2 and R3, set a force SNAT rule.
>     -ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
>     -ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>     -"192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>     -
>     -# Logical port 'bob1' in switch 'bob'.
>     -ADD_NAMESPACES(bob1)
>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>     -         "172.16.1.2")
>     -ovn-nbctl lsp-add bob bob1 \
>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>     -
>     -# Config OVN load-balancer with a VIP.
>     -uuid=`ovn-nbctl  create load_balancer
>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>     -ovn-nbctl set logical_router R3 load_balancer=$uuid
>     -
>     -# Wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>     -grep 'nat(dst=192.168.2.2)'])
>     -
>     -# Start webservers in 'foo1', 'bar1'.
>     -OVS_START_L7([foo1], [http])
>     -OVS_START_L7([bar1], [http])
>     -
>     -dnl Should work with the virtual IP address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Force SNAT should have worked.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- load balancing in router with gateway router port])
>     -AT_KEYWORDS([ovnlb])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# One LR R1 with switches foo (192.168.1.0/24
>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>     <http://192.168.2.0/24>),
>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>     it.  The port between R1 and
>     -# alice is the router gateway port where the R1 LB rules are applied.
>     -#
>     -#    foo -- R1 -- bar
>     -#           |
>     -#    alice ----
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24> \
>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar \
>     -    -- lsp-set-addresses rp-bar router
>     -
>     -# Connect alice to R1
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'foo2' in switch 'foo'.
>     -ADD_NAMESPACES(foo2)
>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo2 \
>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>     -         "192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>     -
>     -# Config OVN load-balancer with a VIP.
>     -uuid=`ovn-nbctl  create load_balancer
>     vips:172.16.1.10="192.168.1.2,192.168.2.2"`
>     -ovn-nbctl set logical_router R1 load_balancer=$uuid
>     -
>     -# Config OVN load-balancer with another VIP (this time with ports).
>     -ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000
>     <http://172.16.1.11:8000>"'='"192.168.1.2:80
>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>     -
>     -# Wait for ovn-controller to catch up.
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>     -grep 'nat(dst=192.168.2.2:80)'])
>     -
>     -# Start webservers in 'foo1', 'bar1'.
>     -OVS_START_L7([foo1], [http])
>     -OVS_START_L7([bar1], [http])
>     -
>     -dnl Should work with the virtual IP address through NAT
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1
>     --retry-connrefused -v -o wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -dnl Test load-balancing that includes L4 ports in NAT.
>     -for i in `seq 1 20`; do
>     -    echo Request $i
>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000
>     <http://172.16.1.11:8000> -t 5 -T 1 --retry-connrefused -v -o
>     wget$i.log])
>     -done
>     -
>     -dnl Each server should have at least one connection.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
>     -AT_KEYWORDS([ovnnat])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# One LR R1 with switches foo (192.168.1.0/24
>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>     <http://192.168.2.0/24>),
>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>     it.  The port between R1 and
>     -# alice is the router gateway port where the R1 NAT rules are
>     applied.
>     -#
>     -#    foo -- R1 -- alice
>     -#           |
>     -#    bar ----
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24> \
>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar \
>     -    -- lsp-set-addresses rp-bar router
>     -
>     -# Connect alice to R1
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'foo2' in switch 'foo'.
>     -ADD_NAMESPACES(foo2)
>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo2 \
>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>     -         "192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>     -
>     -# Add DNAT rules
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>     192.168.1.2 foo1 00:00:02:02:03:04])
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>     192.168.1.3 foo2 00:00:02:02:03:05])
>     -
>     -# Add a SNAT rule
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>     <http://192.168.0.0/16>])
>     -
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>     'nat(src=172.16.1.1)'])
>     -
>     -# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that DNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives
>     traffic
>     -# from 172.16.1.4
>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>     -
>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>     traffic
>     -# from 172.16.1.1
>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
>     -AT_KEYWORDS([ovnnat])
>     -
>     -CHECK_CONNTRACK()
>     -CHECK_CONNTRACK_NAT()
>     -ovn_start
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# One LR R1 with switches foo (192.168.1.0/24
>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>     <http://192.168.2.0/24>),
>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>     it.  The port between R1 and
>     -# alice is the router gateway port where the R1 NAT rules are
>     applied.
>     -#
>     -#    foo -- R1 -- alice
>     -#           |
>     -#    bar ----
>     -
>     -ovn-nbctl lr-add R1
>     -
>     -ovn-nbctl ls-add foo
>     -ovn-nbctl ls-add bar
>     -ovn-nbctl ls-add alice
>     -
>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>     <http://192.168.1.1/24>
>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>     <http://192.168.2.1/24>
>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>     <http://172.16.1.1/24> \
>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>     -
>     -# Connect foo to R1
>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>     -    type=router options:router-port=foo \
>     -    -- lsp-set-addresses rp-foo router
>     -
>     -# Connect bar to R1
>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>     -    type=router options:router-port=bar \
>     -    -- lsp-set-addresses rp-bar router
>     -
>     -# Connect alice to R1
>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>     rp-alice \
>     -    type=router options:router-port=alice \
>     -    -- lsp-set-addresses rp-alice router
>     -
>     -# Logical port 'foo1' in switch 'foo'.
>     -ADD_NAMESPACES(foo1)
>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo1 \
>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>     -
>     -# Logical port 'foo2' in switch 'foo'.
>     -ADD_NAMESPACES(foo2)
>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>     -         "192.168.1.1")
>     -ovn-nbctl lsp-add foo foo2 \
>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>     -
>     -# Logical port 'bar1' in switch 'bar'.
>     -ADD_NAMESPACES(bar1)
>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>     -         "192.168.2.1")
>     -ovn-nbctl lsp-add bar bar1 \
>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>     -
>     -# Logical port 'alice1' in switch 'alice'.
>     -ADD_NAMESPACES(alice1)
>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>     -         "172.16.1.1")
>     -ovn-nbctl lsp-add alice alice1 \
>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>     -
>     -# Add DNAT rules
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>     192.168.1.2 foo1 00:00:02:02:03:04])
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>     192.168.2.2 bar1 00:00:02:02:03:05])
>     -
>     -# Add a SNAT rule
>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>     <http://192.168.0.0/16>])
>     -
>     -ovn-nbctl --wait=hv sync
>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>     'nat(src=172.16.1.1)'])
>     -
>     -echo "------ hv dump ------"
>     -ovs-ofctl show br-int
>     -ovs-ofctl dump-flows br-int
>     -echo "---------------------"
>     -
>     -# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that no NAT happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>     FORMAT_CT(192.168.2.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>     -])
>     -
>     -# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that no NAT happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>     FORMAT_CT(192.168.2.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>     -])
>     -
>     -# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# We verify that no NAT happened via 'dump-conntrack' command.
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>     FORMAT_CT(192.168.2.2) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>     -])
>     -
>     -# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# Check conntrack entries.  First SNAT of 'foo1' address happens.
>     -# Then DNAT of 'bar1' address happens (listed first below).
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>     -
>     -# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>     FORMAT_PING], \
>     -[0], [dnl
>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>     -])
>     -
>     -# Check conntrack entries.  First SNAT of 'foo2' address happens.
>     -# Then DNAT of 'bar1' address happens (listed first below).
>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>     -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     -
>     -AT_SETUP([ovn -- 2 LSs IGMP])
>     -AT_KEYWORDS([ovnigmp])
>     -
>     -ovn_start
>     -
>     -OVS_TRAFFIC_VSWITCHD_START()
>     -ADD_BR([br-int])
>     -
>     -# Set external-ids in br-int needed for ovn-controller
>     -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.0.0.1 \
>     -        -- set bridge br-int fail-mode=secure
>     other-config:disable-in-band=true
>     -
>     -# Start ovn-controller
>     -start_daemon ovn-controller
>     -
>     -# Logical network:
>     -# Two independent logical switches (sw1 and sw2).
>     -# sw1:
>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>     -#   - 2 ports (sw1-p1 - sw1-p2)
>     -# sw2:
>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>     -#   - 2 port (sw2-p1 - sw2-p2)
>     -#   - IGMP Querier from 20.0.0.254
>     -
>     -ovn-nbctl ls-add sw1
>     -ovn-nbctl ls-add sw2
>     -
>     -for i in `seq 1 2`
>     -do
>     -    ADD_NAMESPACES(sw1-p$i)
>     -    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24",
>     "00:00:00:00:01:0$i", \
>     -            "10.0.0.254")
>     -    ovn-nbctl lsp-add sw1 sw1-p$i \
>     -        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 10.0.0.$i"
>     -done
>     -
>     -for i in `seq 1 2`
>     -do
>     -    ADD_NAMESPACES(sw2-p$i)
>     -    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24",
>     "00:00:00:00:02:0$i", \
>     -            "20.0.0.254")
>     -    ovn-nbctl lsp-add sw2 sw2-p$i \
>     -        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 20.0.0.$i"
>     -done
>     -
>     -# Enable IGMP snooping on sw1.
>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>     -
>     -# Inject IGMP Join for 239.0.1.68 on sw1-p1.
>     -NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32
>     <http://239.0.1.68/32> autojoin], [0])
>     -
>     -# Inject IGMP Join for 239.0.1.68 on sw1-p2
>     -NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32
>     <http://239.0.1.68/32> autojoin], [0])
>     -
>     -# Check that the IGMP Group is learned.
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>     ":" | wc -w`
>     -    test "${total_entries}" = "1"
>     -    test "${ports}" = "2"
>     -])
>     -
>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
>     -NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32
>     <http://239.0.1.68/32>], [0])
>     -
>     -# Check that only one port is left in the group.
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>     ":" | wc -w`
>     -    test "${total_entries}" = "1"
>     -    test "${ports}" = "1"
>     -])
>     -
>     -# Flush IGMP groups.
>     -ovn-sbctl ip-multicast-flush sw1
>     -ovn-nbctl --wait=hv -t 3 sync
>     -OVS_WAIT_UNTIL([
>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>     | wc -l`
>     -    test "${total_entries}" = "0"
>     -])
>     -
>     -# Enable IGMP snooping and querier on sw2 and set query interval
>     to minimum.
>     -ovn-nbctl set Logical_Switch sw2 \
>     -    other_config:mcast_snoop="true" \
>     -    other_config:mcast_querier="true" \
>     -    other_config:mcast_query_interval=1 \
>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>     -    other_config:mcast_ip4_src="20.0.0.254"
>     -
>     -# Check that queries are generated.
>     -NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp >
>     sw2-p1.pcap &])
>     -
>     -OVS_WAIT_UNTIL([
>     -    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
>     -    test "${total_queries}" = "2"
>     -])
>     -
>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>     -
>     -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
>     diff --git a/tests/test-ovn.c b/tests/test-ovn.c
>     deleted file mode 100644
>     index 0b9e824..0000000
>     --- a/tests/test-ovn.c
>     +++ /dev/null
>     @@ -1,1584 +0,0 @@
>     -/*
>     - * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
>     - *
>     - * Licensed under the Apache License, Version 2.0 (the "License");
>     - * you may not use this file except in compliance with the License.
>     - * You may obtain a copy of the License at:
>     - *
>     - * http://www.apache.org/licenses/LICENSE-2.0
>     - *
>     - * Unless required by applicable law or agreed to in writing,
>     software
>     - * distributed under the License is distributed on an "AS IS" BASIS,
>     - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
>     or implied.
>     - * See the License for the specific language governing
>     permissions and
>     - * limitations under the License.
>     - */
>     -
>     -#include <config.h>
>     -#include <errno.h>
>     -#include <getopt.h>
>     -#include <sys/wait.h>
>     -
>     -#include "command-line.h"
>     -#include "dp-packet.h"
>     -#include "fatal-signal.h"
>     -#include "flow.h"
>     -#include "openvswitch/dynamic-string.h"
>     -#include "openvswitch/match.h"
>     -#include "openvswitch/ofp-actions.h"
>     -#include "openvswitch/ofpbuf.h"
>     -#include "openvswitch/vlog.h"
>     -#include "ovn/actions.h"
>     -#include "ovn/expr.h"
>     -#include "ovn/lex.h"
>     -#include "ovn/logical-fields.h"
>     -#include "ovn/lib/ovn-l7.h"
>     -#include "ovn/lib/extend-table.h"
>     -#include "ovs-thread.h"
>     -#include "ovstest.h"
>     -#include "openvswitch/shash.h"
>     -#include "simap.h"
>     -#include "util.h"
>     -
>     -/* --relops: Bitmap of the relational operators to test, in
>     exhaustive test. */
>     -static unsigned int test_relops;
>     -
>     -/* --nvars: Number of numeric variables to test, in exhaustive
>     test. */
>     -static int test_nvars = 2;
>     -
>     -/* --svars: Number of string variables to test, in exhaustive
>     test. */
>     -static int test_svars = 2;
>     -
>     -/* --bits: Number of bits per variable, in exhaustive test. */
>     -static int test_bits = 3;
>     -
>     -/* --operation: The operation to test, in exhaustive test. */
>     -static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW }
>     operation
>     -    = OP_FLOW;
>     -
>     -/* --parallel: Number of parallel processes to use in test. */
>     -static int test_parallel = 1;
>     -
>     -/* -m, --more: Message verbosity */
>     -static int verbosity;
>     -
>     -static void
>     -compare_token(const struct lex_token *a, const struct lex_token *b)
>     -{
>     -    if (a->type != b->type) {
>     -        fprintf(stderr, "type differs: %d -> %d\n", a->type,
>     b->type);
>     -        return;
>     -    }
>     -
>     -    if (!((a->s && b->s && !strcmp(a->s, b->s))
>     -          || (!a->s && !b->s))) {
>     -        fprintf(stderr, "string differs: %s -> %s\n",
>     -                a->s ? a->s : "(null)",
>     -                b->s ? b->s : "(null)");
>     -        return;
>     -    }
>     -
>     -    if (a->type == LEX_T_INTEGER || a->type ==
>     LEX_T_MASKED_INTEGER) {
>     -        if (memcmp(&a->value, &b->value, sizeof a->value)) {
>     -            fprintf(stderr, "value differs\n");
>     -            return;
>     -        }
>     -
>     -        if (a->type == LEX_T_MASKED_INTEGER
>     -            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
>     -            fprintf(stderr, "mask differs\n");
>     -            return;
>     -        }
>     -
>     -        if (a->format != b->format
>     -            && !(a->format == LEX_F_HEXADECIMAL
>     -                 && b->format == LEX_F_DECIMAL
>     -                 && a->value.integer == 0)) {
>     -            fprintf(stderr, "format differs: %d -> %d\n",
>     -                    a->format, b->format);
>     -        }
>     -    }
>     -}
>     -
>     -static void
>     -test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    struct ds input;
>     -    struct ds output;
>     -
>     -    ds_init(&input);
>     -    ds_init(&output);
>     -    while (!ds_get_test_line(&input, stdin)) {
>     -        struct lexer lexer;
>     -
>     -        lexer_init(&lexer, ds_cstr(&input));
>     -        ds_clear(&output);
>     -        while (lexer_get(&lexer) != LEX_T_END) {
>     -            size_t len = output.length;
>     -            lex_token_format(&lexer.token, &output);
>     -
>     -            /* Check that the formatted version can really be
>     parsed back
>     -             * losslessly. */
>     -            if (lexer.token.type != LEX_T_ERROR) {
>     -                const char *s = ds_cstr(&output) + len;
>     -                struct lexer l2;
>     -
>     -                lexer_init(&l2, s);
>     -                lexer_get(&l2);
>     -                compare_token(&lexer.token, &l2.token);
>     -                lexer_destroy(&l2);
>     -            }
>     -            ds_put_char(&output, ' ');
>     -        }
>     -        lexer_destroy(&lexer);
>     -
>     -        ds_chomp(&output, ' ');
>     -        puts(ds_cstr(&output));
>     -    }
>     -    ds_destroy(&input);
>     -    ds_destroy(&output);
>     -}
>     -
>     -static void
>     -create_symtab(struct shash *symtab)
>     -{
>     -    ovn_init_symtab(symtab);
>     -
>     -    /* For negative testing. */
>     -    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0,
>     "xyzzy", false);
>     -    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
>     -                          "self_recurse != 0", false);
>     -    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
>     -                          "mutual_recurse_2 != 0", false);
>     -    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
>     -                          "mutual_recurse_1 != 0", false);
>     -    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
>     -}
>     -
>     -static void
>     -create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
>     -                struct hmap *nd_ra_opts,
>     -                struct controller_event_options *event_opts)
>     -{
>     -    hmap_init(dhcp_opts);
>     -    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
>     -    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
>     -    dhcp_opt_add(dhcp_opts, "classless_static_route", 121,
>     "static_routes");
>     -    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
>     -    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
>     -    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
>     -    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
>     -    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
>     -    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
>     -    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
>     -    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
>     -    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
>     -    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
>     -    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
>     -
>     -    /* DHCPv6 options. */
>     -    hmap_init(dhcpv6_opts);
>     -    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
>     -    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
>     -    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
>     -    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
>     -
>     -    /* IPv6 ND RA options. */
>     -    hmap_init(nd_ra_opts);
>     -    nd_ra_opts_init(nd_ra_opts);
>     -
>     -    /* OVN controller events options. */
>     -    controller_event_opts_init(event_opts);
>     -}
>     -
>     -static void
>     -create_addr_sets(struct shash *addr_sets)
>     -{
>     -    shash_init(addr_sets);
>     -
>     -    static const char *const addrs1[] = {
>     -        "10.0.0.1", "10.0.0.2", "10.0.0.3",
>     -    };
>     -    static const char *const addrs2[] = {
>     -        "::1", "::2", "::3",
>     -    };
>     -    static const char *const addrs3[] = {
>     -        "00:00:00:00:00:01", "00:00:00:00:00:02",
>     "00:00:00:00:00:03",
>     -    };
>     -    static const char *const addrs4[] = { NULL };
>     -
>     -    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
>     -    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
>     -    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
>     -    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
>     -}
>     -
>     -static void
>     -create_port_groups(struct shash *port_groups)
>     -{
>     -    shash_init(port_groups);
>     -
>     -    static const char *const pg1[] = {
>     -        "lsp1", "lsp2", "lsp3",
>     -    };
>     -    static const char *const pg2[] = { NULL };
>     -
>     -    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
>     -    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
>     -}
>     -
>     -static bool
>     -lookup_port_cb(const void *ports_, const char *port_name,
>     unsigned int *portp)
>     -{
>     -    const struct simap *ports = ports_;
>     -    const struct simap_node *node = simap_find(ports, port_name);
>     -    if (!node) {
>     -        return false;
>     -    }
>     -    *portp = node->data;
>     -    return true;
>     -}
>     -
>     -static bool
>     -is_chassis_resident_cb(const void *ports_, const char *port_name)
>     -{
>     -    const struct simap *ports = ports_;
>     -    const struct simap_node *node = simap_find(ports, port_name);
>     -    if (node) {
>     -        return true;
>     -    }
>     -    return false;
>     -}
>     -
>     -static void
>     -test_parse_expr__(int steps)
>     -{
>     -    struct shash symtab;
>     -    struct shash addr_sets;
>     -    struct shash port_groups;
>     -    struct simap ports;
>     -    struct ds input;
>     -
>     -    create_symtab(&symtab);
>     -    create_addr_sets(&addr_sets);
>     -    create_port_groups(&port_groups);
>     -
>     -    simap_init(&ports);
>     -    simap_put(&ports, "eth0", 5);
>     -    simap_put(&ports, "eth1", 6);
>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>     -    simap_put(&ports, "lsp1", 0x11);
>     -    simap_put(&ports, "lsp2", 0x12);
>     -    simap_put(&ports, "lsp3", 0x13);
>     -
>     -    ds_init(&input);
>     -    while (!ds_get_test_line(&input, stdin)) {
>     -        struct expr *expr;
>     -        char *error;
>     -
>     -        expr = expr_parse_string(ds_cstr(&input), &symtab,
>     &addr_sets,
>     -                                 &port_groups, NULL, &error);
>     -        if (!error && steps > 0) {
>     -            expr = expr_annotate(expr, &symtab, &error);
>     -        }
>     -        if (!error) {
>     -            if (steps > 1) {
>     -                expr = expr_simplify(expr,
>     is_chassis_resident_cb, &ports);
>     -            }
>     -            if (steps > 2) {
>     -                expr = expr_normalize(expr);
>     -                ovs_assert(expr_is_normalized(expr));
>     -            }
>     -        }
>     -        if (!error) {
>     -            if (steps > 3) {
>     -                struct hmap matches;
>     -
>     -                expr_to_matches(expr, lookup_port_cb, &ports,
>     &matches);
>     -                expr_matches_print(&matches, stdout);
>     -                expr_matches_destroy(&matches);
>     -            } else {
>     -                struct ds output = DS_EMPTY_INITIALIZER;
>     -                expr_format(expr, &output);
>     -                puts(ds_cstr(&output));
>     -                ds_destroy(&output);
>     -            }
>     -        } else {
>     -            puts(error);
>     -            free(error);
>     -        }
>     -        expr_destroy(expr);
>     -    }
>     -    ds_destroy(&input);
>     -
>     -    simap_destroy(&ports);
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -    expr_const_sets_destroy(&addr_sets);
>     -    shash_destroy(&addr_sets);
>     -    expr_const_sets_destroy(&port_groups);
>     -    shash_destroy(&port_groups);
>     -}
>     -
>     -static void
>     -test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    test_parse_expr__(0);
>     -}
>     -
>     -static void
>     -test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    test_parse_expr__(1);
>     -}
>     -
>     -static void
>     -test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    test_parse_expr__(2);
>     -}
>     -
>     -static void
>     -test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    test_parse_expr__(3);
>     -}
>     -
>     -static void
>     -test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    test_parse_expr__(4);
>     -}
>     -
>     -/* Print the symbol table. */
>     -
>     -static void
>     -test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    struct shash symtab;
>     -    create_symtab(&symtab);
>     -
>     -    const struct shash_node **nodes = shash_sort(&symtab);
>     -    for (size_t i = 0; i < shash_count(&symtab); i++) {
>     -        const struct expr_symbol *symbol = nodes[i]->data;
>     -        struct ds s = DS_EMPTY_INITIALIZER;
>     -        expr_symbol_format(symbol, &s);
>     -        puts(ds_cstr(&s));
>     -        ds_destroy(&s);
>     -    }
>     -
>     -    free(nodes);
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -}
>     -
>     -/* Evaluate an expression. */
>     -
>     -static bool
>     -lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
>     -               unsigned int *portp)
>     -{
>     -    *portp = atoi(port_name);
>     -    return true;
>     -}
>     -
>     -static void
>     -test_evaluate_expr(struct ovs_cmdl_context *ctx)
>     -{
>     -    struct shash symtab;
>     -    struct ds input;
>     -
>     -    ovn_init_symtab(&symtab);
>     -
>     -    struct flow uflow;
>     -    char *error = expr_parse_microflow(ctx->argv[1], &symtab,
>     NULL, NULL,
>     -                                       lookup_atoi_cb, NULL, &uflow);
>     -    if (error) {
>     -        ovs_fatal(0, "%s", error);
>     -    }
>     -
>     -    ds_init(&input);
>     -    while (!ds_get_test_line(&input, stdin)) {
>     -        struct expr *expr;
>     -
>     -        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL,
>     NULL, NULL,
>     -                                 &error);
>     -        if (!error) {
>     -            expr = expr_annotate(expr, &symtab, &error);
>     -        }
>     -        if (!error) {
>     -            printf("%d\n", expr_evaluate(expr, &uflow,
>     lookup_atoi_cb, NULL));
>     -        } else {
>     -            puts(error);
>     -            free(error);
>     -        }
>     -        expr_destroy(expr);
>     -    }
>     -    ds_destroy(&input);
>     -
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -}
>     -
>     -/* Compositions.
>     - *
>     - * The "compositions" of a positive integer N are all of the ways
>     that one can
>     - * add up positive integers to sum to N.  For example, the
>     compositions of 3
>     - * are 3, 2+1, 1+2, and 1+1+1.
>     - *
>     - * We use compositions to find all the ways to break up N terms
>     of a Boolean
>     - * expression into subexpressions.  Suppose we want to generate
>     all expressions
>     - * with 3 terms.  The compositions of 3 (ignoring 3 itself)
>     provide the
>     - * possibilities (x && x) || x, x || (x && x), and x || x || x. 
>     (Of course one
>     - * can exchange && for || in each case.)  One must recursively
>     compose the
>     - * sub-expressions whose values are 3 or greater; that is what
>     the "tree shape"
>     - * concept later covers.
>     - *
>     - * To iterate through all compositions of, e.g., 5:
>     - *
>     - *     unsigned int state;
>     - *     int s[5];
>     - *     int n;
>     - *
>     - *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
>     - *          n = next_composition(&state, s, n)) {
>     - *          // Do something with composition 's' with 'n' elements.
>     - *     }
>     - *
>     - * Algorithm from D. E. Knuth, _The Art of Computer Programming,
>     Vol. 4A:
>     - * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to
>     exercise
>     - * 12(a).
>     - */
>     -
>     -/* Begins iteration through the compositions of 'n'. Initializes
>     's' to the
>     - * number of elements in the first composition of 'n' and returns
>     that number
>     - * of elements.  The first composition in fact is always 'n'
>     itself, so the
>     - * return value will be 1.
>     - *
>     - * Initializes '*state' to some internal state information.  The
>     caller must
>     - * maintain this state (and 's') for use by next_composition().
>     - *
>     - * 's' must have room for at least 'n' elements. */
>     -static int
>     -first_composition(int n, unsigned int *state, int s[])
>     -{
>     -    *state = 0;
>     -    s[0] = n;
>     -    return 1;
>     -}
>     -
>     -/* Advances 's', with 'sn' elements, to the next composition and
>     returns the
>     - * number of elements in this new composition, or 0 if no
>     compositions are
>     - * left.  'state' is the same internal state passed to
>     first_composition(). */
>     -static int
>     -next_composition(unsigned int *state, int s[], int sn)
>     -{
>     -    int j = sn - 1;
>     -    if (++*state & 1) {
>     -        if (s[j] > 1) {
>     -            s[j]--;
>     -            s[j + 1] = 1;
>     -            j++;
>     -        } else {
>     -            j--;
>     -            s[j]++;
>     -        }
>     -    } else {
>     -        if (s[j - 1] > 1) {
>     -            s[j - 1]--;
>     -            s[j + 1] = s[j];
>     -            s[j] = 1;
>     -            j++;
>     -        } else {
>     -            j--;
>     -            if (!j) {
>     -                return 0;
>     -            }
>     -            s[j] = s[j + 1];
>     -            s[j - 1]++;
>     -        }
>     -    }
>     -    return j + 1;
>     -}
>     -
>     -static void
>     -test_composition(struct ovs_cmdl_context *ctx)
>     -{
>     -    int n = atoi(ctx->argv[1]);
>     -    unsigned int state;
>     -    int s[50];
>     -
>     -    for (int sn = first_composition(n, &state, s); sn;
>     -         sn = next_composition(&state, s, sn)) {
>     -        for (int i = 0; i < sn; i++) {
>     -            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
>     -        }
>     -    }
>     -}
>     -
>     -/* Tree shapes.
>     - *
>     - * This code generates all possible Boolean expressions with a
>     specified number
>     - * of terms N (equivalent to the number of external nodes in a tree).
>     - *
>     - * See test_tree_shape() for a simple example. */
>     -
>     -/* An array of these structures describes the shape of a tree.
>     - *
>     - * A single element of struct tree_shape describes a single node
>     in the tree.
>     - * The node has 'sn' direct children.  From left to right, for i
>     in 0...sn-1,
>     - * s[i] is 1 if the child is a leaf node, otherwise the child is
>     a subtree and
>     - * s[i] is the number of leaf nodes within that subtree. In the
>     latter case,
>     - * the subtree is described by another struct tree_shape within
>     the enclosing
>     - * array.  The tree_shapes are ordered in the array in in-order.
>     - */
>     -struct tree_shape {
>     -    unsigned int state;
>     -    int s[50];
>     -    int sn;
>     -};
>     -
>     -static int
>     -init_tree_shape__(struct tree_shape ts[], int n)
>     -{
>     -    if (n <= 2) {
>     -        return 0;
>     -    }
>     -
>     -    int n_tses = 1;
>     -    /* Skip the first composition intentionally. */
>     -    ts->sn = first_composition(n, &ts->state, ts->s);
>     -    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
>     -    for (int i = 0; i < ts->sn; i++) {
>     -        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
>     -    }
>     -    return n_tses;
>     -}
>     -
>     -/* Initializes 'ts[]' as the first in the set of all of possible
>     shapes of
>     - * trees with 'n' leaves.  Returns the number of "struct
>     tree_shape"s in the
>     - * first tree shape. */
>     -static int
>     -init_tree_shape(struct tree_shape ts[], int n)
>     -{
>     -    switch (n) {
>     -    case 1:
>     -        ts->sn = 1;
>     -        ts->s[0] = 1;
>     -        return 1;
>     -    case 2:
>     -        ts->sn = 2;
>     -        ts->s[0] = 1;
>     -        ts->s[1] = 1;
>     -        return 1;
>     -    default:
>     -        return init_tree_shape__(ts, n);
>     -    }
>     -}
>     -
>     -/* Advances 'ts', which currently has 'n_tses' elements, to the
>     next possible
>     - * tree shape with the number of leaves passed to
>     init_tree_shape().  Returns
>     - * the number of "struct tree_shape"s in the next shape, or 0 if
>     all tree
>     - * shapes have been visited. */
>     -static int
>     -next_tree_shape(struct tree_shape ts[], int n_tses)
>     -{
>     -    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1]
>     == 1) {
>     -        return 0;
>     -    }
>     -    while (n_tses > 0) {
>     -        struct tree_shape *p = &ts[n_tses - 1];
>     -        p->sn = p->sn > 1 ? next_composition(&p->state, p->s,
>     p->sn) : 0;
>     -        if (p->sn) {
>     -            for (int i = 0; i < p->sn; i++) {
>     -                n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
>     -            }
>     -            break;
>     -        }
>     -        n_tses--;
>     -    }
>     -    return n_tses;
>     -}
>     -
>     -static void
>     -print_tree_shape(const struct tree_shape ts[], int n_tses)
>     -{
>     -    for (int i = 0; i < n_tses; i++) {
>     -        if (i) {
>     -            printf(", ");
>     -        }
>     -        for (int j = 0; j < ts[i].sn; j++) {
>     -            int k = ts[i].s[j];
>     -            if (k > 9) {
>     -                printf("(%d)", k);
>     -            } else {
>     -                printf("%d", k);
>     -            }
>     -        }
>     -    }
>     -}
>     -
>     -static void
>     -test_tree_shape(struct ovs_cmdl_context *ctx)
>     -{
>     -    int n = atoi(ctx->argv[1]);
>     -    struct tree_shape ts[50];
>     -    int n_tses;
>     -
>     -    for (n_tses = init_tree_shape(ts, n); n_tses;
>     -         n_tses = next_tree_shape(ts, n_tses)) {
>     -        print_tree_shape(ts, n_tses);
>     -        putchar('\n');
>     -    }
>     -}
>     -
>     -/* Iteration through all possible terminal expressions (e.g.
>     EXPR_T_CMP and
>     - * EXPR_T_BOOLEAN expressions).
>     - *
>     - * Given a tree shape, this allows the code to try all possible
>     ways to plug in
>     - * terms.
>     - *
>     - * Example use:
>     - *
>     - *     struct expr terminal;
>     - *     const struct expr_symbol *vars = ...;
>     - *     int n_vars = ...;
>     - *     int n_bits = ...;
>     - *
>     - *     init_terminal(&terminal, vars[0]);
>     - *     do {
>     - *         // Something with 'terminal'.
>     - *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
>     - */
>     -
>     -/* Sets 'expr' to the first possible terminal expression. 'var'
>     should be the
>     - * first variable in the ones to be tested. */
>     -static void
>     -init_terminal(struct expr *expr, int phase,
>     -              const struct expr_symbol *nvars[], int n_nvars,
>     -              const struct expr_symbol *svars[], int n_svars)
>     -{
>     -    if (phase < 1 && n_nvars) {
>     -        expr->type = EXPR_T_CMP;
>     -        expr->cmp.symbol = nvars[0];
>     -        expr->cmp.relop = rightmost_1bit_idx(test_relops);
>     -        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
>     -        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
>     -        expr->cmp.value.integer = htonll(0);
>     -        expr->cmp.mask.integer = htonll(0);
>     -        return;
>     -    }
>     -
>     -    if (phase < 2 && n_svars) {
>     -        expr->type = EXPR_T_CMP;
>     -        expr->cmp.symbol = svars[0];
>     -        expr->cmp.relop = EXPR_R_EQ;
>     -        expr->cmp.string = xstrdup("0");
>     -        return;
>     -    }
>     -
>     -    expr->type = EXPR_T_BOOLEAN;
>     -    expr->boolean = false;
>     -}
>     -
>     -/* Returns 'x' with the rightmost contiguous string of 1s changed
>     to 0s,
>     - * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's
>     Delight_, 2nd
>     - * ed., section 2-1. */
>     -static unsigned int
>     -turn_off_rightmost_1s(unsigned int x)
>     -{
>     -    return ((x & -x) + x) & x;
>     -}
>     -
>     -static const struct expr_symbol *
>     -next_var(const struct expr_symbol *symbol,
>     -         const struct expr_symbol *vars[], int n_vars)
>     -{
>     -    for (int i = 0; i < n_vars; i++) {
>     -        if (symbol == vars[i]) {
>     -            return i + 1 >= n_vars ? NULL : vars[i + 1];
>     -        }
>     -    }
>     -    OVS_NOT_REACHED();
>     -}
>     -
>     -static enum expr_relop
>     -next_relop(enum expr_relop relop)
>     -{
>     -    unsigned int remaining_relops = test_relops & ~((1u << (relop
>     + 1)) - 1);
>     -    return (remaining_relops
>     -            ? rightmost_1bit_idx(remaining_relops)
>     -            : rightmost_1bit_idx(test_relops));
>     -}
>     -
>     -/* Advances 'expr' to the next possible terminal expression
>     within the 'n_vars'
>     - * variables of 'n_bits' bits each in 'vars[]'. */
>     -static bool
>     -next_terminal(struct expr *expr,
>     -              const struct expr_symbol *nvars[], int n_nvars, int
>     n_bits,
>     -              const struct expr_symbol *svars[], int n_svars)
>     -{
>     -    if (expr->type == EXPR_T_BOOLEAN) {
>     -        if (expr->boolean) {
>     -            return false;
>     -        } else {
>     -            expr->boolean = true;
>     -            return true;
>     -        }
>     -    }
>     -
>     -    if (!expr->cmp.symbol->width) {
>     -        int next_value = atoi(expr->cmp.string) + 1;
>     -        free(expr->cmp.string);
>     -        if (next_value > 1) {
>     -            expr->cmp.symbol = next_var(expr->cmp.symbol, svars,
>     n_svars);
>     -            if (!expr->cmp.symbol) {
>     -                init_terminal(expr, 2, nvars, n_nvars, svars,
>     n_svars);
>     -                return true;
>     -            }
>     -            next_value = 0;
>     -        }
>     -        expr->cmp.string = xasprintf("%d", next_value);
>     -        return true;
>     -    }
>     -
>     -    unsigned int next;
>     -
>     -    next = (ntohll(expr->cmp.value.integer)
>     -            + (ntohll(expr->cmp.mask.integer) << n_bits));
>     -    for (;;) {
>     -        next++;
>     -        unsigned m = next >> n_bits;
>     -        unsigned v = next & ((1u << n_bits) - 1);
>     -        if (next >= (1u << (2 * n_bits))) {
>     -            enum expr_relop old_relop = expr->cmp.relop;
>     -            expr->cmp.relop = next_relop(old_relop);
>     -            if (expr->cmp.relop <= old_relop) {
>     -                expr->cmp.symbol = next_var(expr->cmp.symbol,
>     nvars, n_nvars);
>     -                if (!expr->cmp.symbol) {
>     -                    init_terminal(expr, 1, nvars, n_nvars, svars,
>     n_svars);
>     -                    return true;
>     -                }
>     -            }
>     -            next = UINT_MAX;
>     -        } else if (v & ~m) {
>     -            /* Skip: 1-bits in value correspond to 0-bits in mask. */
>     -        } else if ((!m || turn_off_rightmost_1s(m))
>     -                   && (expr->cmp.relop != EXPR_R_EQ &&
>     -                       expr->cmp.relop != EXPR_R_NE)) {
>     -            /* Skip: can't have discontiguous or all-0 mask for >
>     >= < <=. */
>     -        } else {
>     -            expr->cmp.value.integer = htonll(v);
>     -            expr->cmp.mask.integer = htonll(m);
>     -            return true;
>     -        }
>     -    }
>     -}
>     -
>     -static struct expr *
>     -make_terminal(struct expr ***terminalp)
>     -{
>     -    struct expr *e = expr_create_boolean(true);
>     -    **terminalp = e;
>     -    (*terminalp)++;
>     -    return e;
>     -}
>     -
>     -static struct expr *
>     -build_simple_tree(enum expr_type type, int n, struct expr
>     ***terminalp)
>     -{
>     -    if (n == 2) {
>     -        struct expr *e = expr_create_andor(type);
>     -        for (int i = 0; i < 2; i++) {
>     -            struct expr *sub = make_terminal(terminalp);
>     -            ovs_list_push_back(&e->andor, &sub->node);
>     -        }
>     -        return e;
>     -    } else if (n == 1) {
>     -        return make_terminal(terminalp);
>     -    } else {
>     -        OVS_NOT_REACHED();
>     -    }
>     -}
>     -
>     -static struct expr *
>     -build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
>     -                 struct expr ***terminalp)
>     -{
>     -    const struct tree_shape *ts = *tsp;
>     -    (*tsp)++;
>     -
>     -    struct expr *e = expr_create_andor(type);
>     -    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
>     -    for (int i = 0; i < ts->sn; i++) {
>     -        struct expr *sub = (ts->s[i] > 2
>     -                            ? build_tree_shape(t, tsp, terminalp)
>     -                            : build_simple_tree(t, ts->s[i],
>     terminalp));
>     -        ovs_list_push_back(&e->andor, &sub->node);
>     -    }
>     -    return e;
>     -}
>     -
>     -struct test_rule {
>     -    struct cls_rule cr;
>     -};
>     -
>     -static void
>     -free_rule(struct test_rule *test_rule)
>     -{
>     -    cls_rule_destroy(&test_rule->cr);
>     -    free(test_rule);
>     -}
>     -
>     -static bool
>     -tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
>     -                                  const char *port_name OVS_UNUSED)
>     -{
>     -    return true;
>     -}
>     -
>     -static int
>     -test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab,
>     -                             struct expr *terminals[], int
>     n_terminals,
>     -                             const struct expr_symbol *nvars[],
>     int n_nvars,
>     -                             int n_bits,
>     -                             const struct expr_symbol *svars[],
>     int n_svars)
>     -{
>     -    int n_tested = 0;
>     -
>     -    const unsigned int var_mask = (1u << n_bits) - 1;
>     -    for (int i = 0; i < n_terminals; i++) {
>     -        init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>     n_svars);
>     -    }
>     -
>     -    struct ds s = DS_EMPTY_INITIALIZER;
>     -    struct flow f;
>     -    memset(&f, 0, sizeof f);
>     -    for (;;) {
>     -        for (int i = n_terminals - 1; ; i--) {
>     -            if (!i) {
>     -                ds_destroy(&s);
>     -                return n_tested;
>     -            }
>     -            if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
>     -                              svars, n_svars)) {
>     -                break;
>     -            }
>     -            init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>     n_svars);
>     -        }
>     -        ovs_assert(expr_honors_invariants(expr));
>     -
>     -        n_tested++;
>     -
>     -        struct expr *modified;
>     -        if (operation == OP_CONVERT) {
>     -            ds_clear(&s);
>     -            expr_format(expr, &s);
>     -
>     -            char *error;
>     -            modified = expr_parse_string(ds_cstr(&s), symtab, NULL,
>     -                                         NULL, NULL, &error);
>     -            if (error) {
>     -                fprintf(stderr, "%s fails to parse (%s)\n",
>     -                        ds_cstr(&s), error);
>     -                exit(EXIT_FAILURE);
>     -            }
>     -        } else if (operation >= OP_SIMPLIFY) {
>     -            modified = expr_simplify(expr_clone(expr),
>     -  tree_shape_is_chassis_resident_cb,
>     -                                     NULL);
>     -            ovs_assert(expr_honors_invariants(modified));
>     -
>     -            if (operation >= OP_NORMALIZE) {
>     -                modified = expr_normalize(modified);
>     - ovs_assert(expr_honors_invariants(modified));
>     -                ovs_assert(expr_is_normalized(modified));
>     -            }
>     -        }
>     -
>     -        struct hmap matches;
>     -        struct classifier cls;
>     -        if (operation >= OP_FLOW) {
>     -            struct expr_match *m;
>     -            struct test_rule *test_rule;
>     -
>     -            expr_to_matches(modified, lookup_atoi_cb, NULL,
>     &matches);
>     -
>     -            classifier_init(&cls, NULL);
>     -            HMAP_FOR_EACH (m, hmap_node, &matches) {
>     -                test_rule = xmalloc(sizeof *test_rule);
>     -                cls_rule_init(&test_rule->cr, &m->match, 0);
>     -                classifier_insert(&cls, &test_rule->cr,
>     OVS_VERSION_MIN,
>     -                                  m->conjunctions, m->n);
>     -            }
>     -        }
>     -        for (int subst = 0; subst < 1 << (n_bits * n_nvars +
>     n_svars);
>     -             subst++) {
>     -            for (int i = 0; i < n_nvars; i++) {
>     -                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
>     -            }
>     -            for (int i = 0; i < n_svars; i++) {
>     -                f.regs[n_nvars + i] = ((subst >> (n_nvars *
>     n_bits + i))
>     -                                       & 1);
>     -            }
>     -
>     -            bool expected = expr_evaluate(expr, &f,
>     lookup_atoi_cb, NULL);
>     -            bool actual = expr_evaluate(modified, &f,
>     lookup_atoi_cb, NULL);
>     -            if (actual != expected) {
>     -                struct ds expr_s, modified_s;
>     -
>     -                ds_init(&expr_s);
>     -                expr_format(expr, &expr_s);
>     -
>     -                ds_init(&modified_s);
>     -                expr_format(modified, &modified_s);
>     -
>     -                fprintf(stderr,
>     -                        "%s evaluates to %d, but %s evaluates to
>     %d, for",
>     -                        ds_cstr(&expr_s), expected,
>     -                        ds_cstr(&modified_s), actual);
>     -                for (int i = 0; i < n_nvars; i++) {
>     -                    if (i > 0) {
>     -                        fputs(",", stderr);
>     -                    }
>     -                    fprintf(stderr, " n%d = 0x%x", i,
>     -                            (subst >> (n_bits * i)) & var_mask);
>     -                }
>     -                for (int i = 0; i < n_svars; i++) {
>     -                    fprintf(stderr, ", s%d = \"%d\"", i,
>     -                            (subst >> (n_bits * n_nvars + i)) & 1);
>     -                }
>     -                putc('\n', stderr);
>     -                exit(EXIT_FAILURE);
>     -            }
>     -
>     -            if (operation >= OP_FLOW) {
>     -                bool found = classifier_lookup(&cls, OVS_VERSION_MIN,
>     -                                               &f, NULL) != NULL;
>     -                if (expected != found) {
>     -                    struct ds expr_s, modified_s;
>     -
>     -                    ds_init(&expr_s);
>     -                    expr_format(expr, &expr_s);
>     -
>     -                    ds_init(&modified_s);
>     -                    expr_format(modified, &modified_s);
>     -
>     -                    fprintf(stderr,
>     -                            "%s and %s evaluate to %d, for",
>     -                            ds_cstr(&expr_s),
>     ds_cstr(&modified_s), expected);
>     -                    for (int i = 0; i < n_nvars; i++) {
>     -                        if (i > 0) {
>     -                            fputs(",", stderr);
>     -                        }
>     -                        fprintf(stderr, " n%d = 0x%x", i,
>     -                                (subst >> (n_bits * i)) & var_mask);
>     -                    }
>     -                    for (int i = 0; i < n_svars; i++) {
>     -                        fprintf(stderr, ", s%d = \"%d\"", i,
>     -                                (subst >> (n_bits * n_nvars + i))
>     & 1);
>     -                    }
>     -                    fputs(".\n", stderr);
>     -
>     -                    fprintf(stderr, "Converted to classifier:\n");
>     -                    expr_matches_print(&matches, stderr);
>     -                    fprintf(stderr,
>     -                            "However, %s flow was found in the
>     classifier.\n",
>     -                            found ? "a" : "no");
>     -                    exit(EXIT_FAILURE);
>     -                }
>     -            }
>     -        }
>     -        if (operation >= OP_FLOW) {
>     -            struct test_rule *test_rule;
>     -
>     -            CLS_FOR_EACH (test_rule, cr, &cls) {
>     -                classifier_remove_assert(&cls, &test_rule->cr);
>     -                ovsrcu_postpone(free_rule, test_rule);
>     -            }
>     -            classifier_destroy(&cls);
>     -            ovsrcu_quiesce();
>     -
>     -            expr_matches_destroy(&matches);
>     -        }
>     -        expr_destroy(modified);
>     -    }
>     -}
>     -
>     -#ifndef _WIN32
>     -static void
>     -wait_pid(pid_t *pids, int *n)
>     -{
>     -    int status;
>     -    pid_t pid;
>     -
>     -    pid = waitpid(-1, &status, 0);
>     -    if (pid < 0) {
>     -        ovs_fatal(errno, "waitpid failed");
>     -    } else if (WIFEXITED(status)) {
>     -        if (WEXITSTATUS(status)) {
>     -            exit(WEXITSTATUS(status));
>     -        }
>     -    } else if (WIFSIGNALED(status)) {
>     -        raise(WTERMSIG(status));
>     -        exit(1);
>     -    } else {
>     -        OVS_NOT_REACHED();
>     -    }
>     -
>     -    for (int i = 0; i < *n; i++) {
>     -        if (pids[i] == pid) {
>     -            pids[i] = pids[--*n];
>     -            return;
>     -        }
>     -    }
>     -    ovs_fatal(0, "waitpid returned unknown child");
>     -}
>     -#endif
>     -
>     -static void
>     -test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    int n_terminals = atoi(ctx->argv[1]);
>     -    struct tree_shape ts[50];
>     -    int n_tses;
>     -
>     -    struct shash symtab;
>     -    const struct expr_symbol *nvars[4];
>     -    const struct expr_symbol *svars[4];
>     -
>     -    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
>     -    ovs_assert(test_svars <= ARRAY_SIZE(svars));
>     -    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
>     -
>     -    shash_init(&symtab);
>     -    for (int i = 0; i < test_nvars; i++) {
>     -        char *name = xasprintf("n%d", i);
>     -        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0
>     + i, NULL,
>     -                                         false);
>     -        free(name);
>     -    }
>     -    for (int i = 0; i < test_svars; i++) {
>     -        char *name = xasprintf("s%d", i);
>     -        svars[i] = expr_symtab_add_string(&symtab, name,
>     -                                          MFF_REG0 + test_nvars +
>     i, NULL);
>     -        free(name);
>     -    }
>     -
>     -#ifndef _WIN32
>     -    pid_t *children = xmalloc(test_parallel * sizeof *children);
>     -    int n_children = 0;
>     -#endif
>     -
>     -    int n_tested = 0;
>     -    for (int i = 0; i < 2; i++) {
>     -        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
>     -
>     -        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
>     -             n_tses = next_tree_shape(ts, n_tses)) {
>     -            const struct tree_shape *tsp = ts;
>     -            struct expr *terminals[50];
>     -            struct expr **terminalp = terminals;
>     -            struct expr *expr = build_tree_shape(base_type, &tsp,
>     &terminalp);
>     -            ovs_assert(terminalp == &terminals[n_terminals]);
>     -
>     -            if (verbosity > 0) {
>     -                print_tree_shape(ts, n_tses);
>     -                printf(": ");
>     -                struct ds s = DS_EMPTY_INITIALIZER;
>     -                expr_format(expr, &s);
>     -                puts(ds_cstr(&s));
>     -                ds_destroy(&s);
>     -            }
>     -
>     -#ifndef _WIN32
>     -            if (test_parallel > 1) {
>     -                pid_t pid = xfork();
>     -                if (!pid) {
>     -                    test_tree_shape_exhaustively(expr, &symtab,
>     -                                                 terminals,
>     n_terminals,
>     -                                                 nvars,
>     test_nvars, test_bits,
>     -                                                 svars, test_svars);
>     -                    expr_destroy(expr);
>     -                    exit(0);
>     -                } else {
>     -                    if (n_children >= test_parallel) {
>     -                        wait_pid(children, &n_children);
>     -                    }
>     -                    children[n_children++] = pid;
>     -                }
>     -            } else
>     -#endif
>     -            {
>     -                n_tested += test_tree_shape_exhaustively(
>     -                    expr, &symtab, terminals, n_terminals,
>     -                    nvars, test_nvars, test_bits,
>     -                    svars, test_svars);
>     -            }
>     -            expr_destroy(expr);
>     -        }
>     -    }
>     -#ifndef _WIN32
>     -    while (n_children > 0) {
>     -        wait_pid(children, &n_children);
>     -    }
>     -    free(children);
>     -#endif
>     -
>     -    printf("Tested ");
>     -    switch (operation) {
>     -    case OP_CONVERT:
>     -        printf("converting");
>     -        break;
>     -    case OP_SIMPLIFY:
>     -        printf("simplifying");
>     -        break;
>     -    case OP_NORMALIZE:
>     -        printf("normalizing");
>     -        break;
>     -    case OP_FLOW:
>     -        printf("converting to flows");
>     -        break;
>     -    }
>     -    if (n_tested) {
>     -        printf(" %d expressions of %d terminals", n_tested,
>     n_terminals);
>     -    } else {
>     -        printf(" all %d-terminal expressions", n_terminals);
>     -    }
>     -    if (test_nvars || test_svars) {
>     -        printf(" with");
>     -        if (test_nvars) {
>     -            printf(" %d numeric vars (each %d bits) in terms of
>     operators",
>     -                   test_nvars, test_bits);
>     -            for (unsigned int relops = test_relops; relops;
>     -                 relops = zero_rightmost_1bit(relops)) {
>     -                enum expr_relop r = rightmost_1bit_idx(relops);
>     -                printf(" %s", expr_relop_to_string(r));
>     -            }
>     -        }
>     -        if (test_nvars && test_svars) {
>     -            printf (" and");
>     -        }
>     -        if (test_svars) {
>     -            printf(" %d string vars", test_svars);
>     -        }
>     -    } else {
>     -        printf(" in terms of Boolean constants only");
>     -    }
>     -    printf(".\n");
>     -
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -}
>     -
>     -static void
>     -test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    struct shash symtab;
>     -    struct ds input;
>     -
>     -    create_symtab(&symtab);
>     -
>     -    ds_init(&input);
>     -    while (!ds_get_test_line(&input, stdin)) {
>     -        struct flow uflow;
>     -        char *error = expr_parse_microflow(ds_cstr(&input),
>     &symtab, NULL,
>     -                                           NULL, lookup_atoi_cb,
>     NULL, &uflow);
>     -        if (error) {
>     -            puts(error);
>     -            free(error);
>     -            continue;
>     -        }
>     -
>     -        uint64_t packet_stub[128 / 8];
>     -        struct dp_packet packet;
>     -        dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
>     -        flow_compose(&packet, &uflow, NULL, 64);
>     -
>     -        struct ds output = DS_EMPTY_INITIALIZER;
>     -        const uint8_t *buf = dp_packet_data(&packet);
>     -        for (int i = 0; i < dp_packet_size(&packet); i++) {
>     -            uint8_t val = buf[i];
>     -            ds_put_format(&output, "%02"PRIx8, val);
>     -        }
>     -        puts(ds_cstr(&output));
>     -        ds_destroy(&output);
>     -
>     -        dp_packet_uninit(&packet);
>     -    }
>     -    ds_destroy(&input);
>     -
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -}
>     -
>     -/* Actions. */
>     -
>     -static void
>     -test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
>     -{
>     -    struct shash symtab;
>     -    struct hmap dhcp_opts;
>     -    struct hmap dhcpv6_opts;
>     -    struct hmap nd_ra_opts;
>     -    struct controller_event_options event_opts;
>     -    struct simap ports;
>     -    struct ds input;
>     -    bool ok = true;
>     -
>     -    create_symtab(&symtab);
>     -    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
>     &event_opts);
>     -
>     -    /* Initialize group ids. */
>     -    struct ovn_extend_table group_table;
>     -    ovn_extend_table_init(&group_table);
>     -
>     -    /* Initialize meter ids for QoS. */
>     -    struct ovn_extend_table meter_table;
>     -    ovn_extend_table_init(&meter_table);
>     -
>     -    simap_init(&ports);
>     -    simap_put(&ports, "eth0", 5);
>     -    simap_put(&ports, "eth1", 6);
>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>     -
>     -    ds_init(&input);
>     -    while (!ds_get_test_line(&input, stdin)) {
>     -        struct ofpbuf ovnacts;
>     -        struct expr *prereqs;
>     -        char *error;
>     -
>     -        puts(ds_cstr(&input));
>     -
>     -        ofpbuf_init(&ovnacts, 0);
>     -
>     -        const struct ovnact_parse_params pp = {
>     -            .symtab = &symtab,
>     -            .dhcp_opts = &dhcp_opts,
>     -            .dhcpv6_opts = &dhcpv6_opts,
>     -            .nd_ra_opts = &nd_ra_opts,
>     -            .controller_event_opts = &event_opts,
>     -            .n_tables = 24,
>     -            .cur_ltable = 10,
>     -        };
>     -        error = ovnacts_parse_string(ds_cstr(&input), &pp,
>     &ovnacts, &prereqs);
>     -        if (!error) {
>     -            /* Convert the parsed representation back to a string
>     and print it,
>     -             * if it's different from the input. */
>     -            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
>     -            ovnacts_format(ovnacts.data, ovnacts.size, &ovnacts_s);
>     -            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
>     -                printf("    formats as %s\n", ds_cstr(&ovnacts_s));
>     -            }
>     -
>     -            /* Encode the actions into OpenFlow and print. */
>     -            const struct ovnact_encode_params ep = {
>     -                .lookup_port = lookup_port_cb,
>     -                .aux = &ports,
>     -                .is_switch = true,
>     -                .group_table = &group_table,
>     -                .meter_table = &meter_table,
>     -
>     -                .pipeline = OVNACT_P_INGRESS,
>     -                .ingress_ptable = 8,
>     -                .egress_ptable = 40,
>     -                .output_ptable = 64,
>     -                .mac_bind_ptable = 65,
>     -            };
>     -            struct ofpbuf ofpacts;
>     -            ofpbuf_init(&ofpacts, 0);
>     -            ovnacts_encode(ovnacts.data, ovnacts.size, &ep,
>     &ofpacts);
>     -            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
>     -            struct ofpact_format_params fp = { .s = &ofpacts_s };
>     -            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
>     -            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
>     -            ds_destroy(&ofpacts_s);
>     -            ofpbuf_uninit(&ofpacts);
>     -
>     -            /* Print prerequisites if any. */
>     -            if (prereqs) {
>     -                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
>     -                expr_format(prereqs, &prereqs_s);
>     -                printf("    has prereqs %s\n", ds_cstr(&prereqs_s));
>     -                ds_destroy(&prereqs_s);
>     -            }
>     -
>     -            /* Now re-parse and re-format the string to verify
>     that it's
>     -             * round-trippable. */
>     -            struct ofpbuf ovnacts2;
>     -            struct expr *prereqs2;
>     -            ofpbuf_init(&ovnacts2, 0);
>     -            error = ovnacts_parse_string(ds_cstr(&ovnacts_s),
>     &pp, &ovnacts2,
>     -                                         &prereqs2);
>     -            if (!error) {
>     -                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
>     -                ovnacts_format(ovnacts2.data, ovnacts2.size,
>     &ovnacts2_s);
>     -                if (strcmp(ds_cstr(&ovnacts_s),
>     ds_cstr(&ovnacts2_s))) {
>     -                    printf("    bad reformat: %s\n",
>     ds_cstr(&ovnacts2_s));
>     -                    ok = false;
>     -                }
>     -                ds_destroy(&ovnacts2_s);
>     -            } else {
>     -                printf("    reparse error: %s\n", error);
>     -                free(error);
>     -                ok = false;
>     -            }
>     -            expr_destroy(prereqs2);
>     -
>     -            ovnacts_free(ovnacts2.data, ovnacts2.size);
>     -            ofpbuf_uninit(&ovnacts2);
>     -            ds_destroy(&ovnacts_s);
>     -        } else {
>     -            printf("    %s\n", error);
>     -            free(error);
>     -        }
>     -
>     -        expr_destroy(prereqs);
>     -        ovnacts_free(ovnacts.data, ovnacts.size);
>     -        ofpbuf_uninit(&ovnacts);
>     -    }
>     -    ds_destroy(&input);
>     -
>     -    simap_destroy(&ports);
>     -    expr_symtab_destroy(&symtab);
>     -    shash_destroy(&symtab);
>     -    dhcp_opts_destroy(&dhcp_opts);
>     -    dhcp_opts_destroy(&dhcpv6_opts);
>     -    nd_ra_opts_destroy(&nd_ra_opts);
>     -    controller_event_opts_destroy(&event_opts);
>     -    ovn_extend_table_destroy(&group_table);
>     -    ovn_extend_table_destroy(&meter_table);
>     -    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
>     -}
>     -
>     -static unsigned int
>     -parse_relops(const char *s)
>     -{
>     -    unsigned int relops = 0;
>     -    struct lexer lexer;
>     -
>     -    lexer_init(&lexer, s);
>     -    lexer_get(&lexer);
>     -    do {
>     -        enum expr_relop relop;
>     -
>     -        if (expr_relop_from_token(lexer.token.type, &relop)) {
>     -            relops |= 1u << relop;
>     -            lexer_get(&lexer);
>     -        } else {
>     -            ovs_fatal(0, "%s: relational operator expected at
>     `%.*s'",
>     -                      s, (int) (lexer.input - lexer.start),
>     lexer.start);
>     -        }
>     -        lexer_match(&lexer, LEX_T_COMMA);
>     -    } while (lexer.token.type != LEX_T_END);
>     -    lexer_destroy(&lexer);
>     -
>     -    return relops;
>     -}
>     -
>     -static void
>     -usage(void)
>     -{
>     -    printf("\
>     -%s: OVN test utility\n\
>     -usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
>     -\n\
>     -lex\n\
>     -  Lexically analyzes OVN input from stdin and print them back on
>     stdout.\n\
>     -\n\
>     -parse-expr\n\
>     -annotate-expr\n\
>     -simplify-expr\n\
>     -normalize-expr\n\
>     -expr-to-flows\n\
>     -  Parses OVN expressions from stdin and prints them back on
>     stdout after\n\
>     -  differing degrees of analysis.  Available fields are based on
>     packet\n\
>     -  headers.\n\
>     -\n\
>     -expr-to-packets\n\
>     -  Parses OVN expressions from stdin and prints out matching
>     packets in\n\
>     -  hexadecimal on stdout.\n\
>     -\n\
>     -evaluate-expr MICROFLOW\n\
>     -  Parses OVN expressions from stdin and evaluates them against
>     the flow\n\
>     -  specified in MICROFLOW, which must be an expression that
>     constrains\n\
>     -  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with
>     source\n\
>     -  port 80, and prints the results on stdout, either 1 for true or
>     0 for\n\
>     -  false.  Use quoted integers, e.g. \"123\", for string fields.\n\
>     -\n\
>     -  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type
>     == 0x800\"\n\
>     -  evaluates to true, \"udp\" evaluates to false, and \"udp ||
>     tcp\"\n\
>     -  evaluates to true.\n\
>     -\n\
>     -composition N\n\
>     -  Prints all the compositions of N on stdout.\n\
>     -\n\
>     -tree-shape N\n\
>     -  Prints all the tree shapes with N terminals on stdout.\n\
>     -\n\
>     -exhaustive N\n\
>     -  Tests that all possible Boolean expressions with N terminals
>     are properly\n\
>     -  simplified, normalized, and converted to flows. Available
>     options:\n\
>     -   Overall options:\n\
>     -    --operation=OPERATION  Operation to test, one of: convert,
>     simplify,\n\
>     -        normalize, flow.  Default: flow.  'normalize' includes
>     'simplify',\n\
>     -        'flow' includes 'simplify' and 'normalize'.\n\
>     -    --parallel=N  Number of processes to use in parallel, default
>     1.\n\
>     -   Numeric vars:\n\
>     -    --nvars=N  Number of numeric vars to test, in range 0...4,
>     default 2.\n\
>     -    --bits=N  Number of bits per variable, in range 1...3,
>     default 3.\n\
>     -    --relops=OPERATORS   Test only the specified Boolean
>     operators.\n\
>     -                         OPERATORS may include == != < <= > >=,
>     space or\n\
>     -                         comma separated.  Default is all
>     operators.\n\
>     -   String vars:\n\
>     -    --svars=N  Number of string vars to test, in range 0...4,
>     default 2.\n\
>     -\n\
>     -parse-actions\n\
>     -  Parses OVN actions from stdin and prints the equivalent
>     OpenFlow actions\n\
>     -  on stdout.\n\
>     -",
>     -           program_name, program_name);
>     -    exit(EXIT_SUCCESS);
>     -}
>     -
>     -static void
>     -test_ovn_main(int argc, char *argv[])
>     -{
>     -    enum {
>     -        OPT_RELOPS = UCHAR_MAX + 1,
>     -        OPT_NVARS,
>     -        OPT_SVARS,
>     -        OPT_BITS,
>     -        OPT_OPERATION,
>     -        OPT_PARALLEL
>     -    };
>     -    static const struct option long_options[] = {
>     -        {"relops", required_argument, NULL, OPT_RELOPS},
>     -        {"nvars", required_argument, NULL, OPT_NVARS},
>     -        {"svars", required_argument, NULL, OPT_SVARS},
>     -        {"bits", required_argument, NULL, OPT_BITS},
>     -        {"operation", required_argument, NULL, OPT_OPERATION},
>     -        {"parallel", required_argument, NULL, OPT_PARALLEL},
>     -        {"more", no_argument, NULL, 'm'},
>     -        {"help", no_argument, NULL, 'h'},
>     -        {NULL, 0, NULL, 0},
>     -    };
>     -    char *short_options =
>     ovs_cmdl_long_options_to_short_options(long_options);
>     -
>     -    set_program_name(argv[0]);
>     -
>     -    test_relops = parse_relops("== != < <= > >=");
>     -    for (;;) {
>     -        int option_index = 0;
>     -        int c = getopt_long (argc, argv, short_options, long_options,
>     -                             &option_index);
>     -
>     -        if (c == -1) {
>     -            break;
>     -        }
>     -        switch (c) {
>     -        case OPT_RELOPS:
>     -            test_relops = parse_relops(optarg);
>     -            break;
>     -
>     -        case OPT_NVARS:
>     -            test_nvars = atoi(optarg);
>     -            if (test_nvars < 0 || test_nvars > 4) {
>     -                ovs_fatal(0, "number of numeric variables must be "
>     -                          "between 0 and 4");
>     -            }
>     -            break;
>     -
>     -        case OPT_SVARS:
>     -            test_svars = atoi(optarg);
>     -            if (test_svars < 0 || test_svars > 4) {
>     -                ovs_fatal(0, "number of string variables must be "
>     -                          "between 0 and 4");
>     -            }
>     -            break;
>     -
>     -        case OPT_BITS:
>     -            test_bits = atoi(optarg);
>     -            if (test_bits < 1 || test_bits > 3) {
>     -                ovs_fatal(0, "number of bits must be between 1
>     and 3");
>     -            }
>     -            break;
>     -
>     -        case OPT_OPERATION:
>     -            if (!strcmp(optarg, "convert")) {
>     -                operation = OP_CONVERT;
>     -            } else if (!strcmp(optarg, "simplify")) {
>     -                operation = OP_SIMPLIFY;
>     -            } else if (!strcmp(optarg, "normalize")) {
>     -                operation = OP_NORMALIZE;
>     -            } else if (!strcmp(optarg, "flow")) {
>     -                operation = OP_FLOW;
>     -            } else {
>     -                ovs_fatal(0, "%s: unknown operation", optarg);
>     -            }
>     -            break;
>     -
>     -        case OPT_PARALLEL:
>     -            test_parallel = atoi(optarg);
>     -            break;
>     -
>     -        case 'm':
>     -            verbosity++;
>     -            break;
>     -
>     -        case 'h':
>     -            usage();
>     -            /* fall through */
>     -
>     -        case '?':
>     -            exit(1);
>     -
>     -        default:
>     -            abort();
>     -        }
>     -    }
>     -    free(short_options);
>     -
>     -    static const struct ovs_cmdl_command commands[] = {
>     -        /* Lexer. */
>     -        {"lex", NULL, 0, 0, test_lex, OVS_RO},
>     -
>     -        /* Symbol table. */
>     -        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
>     -
>     -        /* Expressions. */
>     -        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
>     -        {"annotate-expr", NULL, 0, 0, test_annotate_expr, OVS_RO},
>     -        {"simplify-expr", NULL, 0, 0, test_simplify_expr, OVS_RO},
>     -        {"normalize-expr", NULL, 0, 0, test_normalize_expr, OVS_RO},
>     -        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, OVS_RO},
>     -        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, OVS_RO},
>     -        {"composition", NULL, 1, 1, test_composition, OVS_RO},
>     -        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
>     -        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
>     -        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets,
>     OVS_RO},
>     -
>     -        /* Actions. */
>     -        {"parse-actions", NULL, 0, 0, test_parse_actions, OVS_RO},
>     -
>     -        {NULL, NULL, 0, 0, NULL, OVS_RO},
>     -    };
>     -    struct ovs_cmdl_context ctx;
>     -    ctx.argc = argc - optind;
>     -    ctx.argv = argv + optind;
>     -    ovs_cmdl_run_command(&ctx, commands);
>     -}
>     -
>     -OVSTEST_REGISTER("test-ovn", test_ovn_main);
>     diff --git a/tests/testsuite.at <http://testsuite.at>
>     b/tests/testsuite.at <http://testsuite.at>
>     index 4d5e816..e759123 100644
>     --- a/tests/testsuite.at <http://testsuite.at>
>     +++ b/tests/testsuite.at <http://testsuite.at>
>     @@ -19,7 +19,6 @@ m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
>      m4_include([tests/ovs-macros.at <http://ovs-macros.at>])
>      m4_include([tests/ovsdb-macros.at <http://ovsdb-macros.at>])
>      m4_include([tests/ofproto-macros.at <http://ofproto-macros.at>])
>     -m4_include([tests/ovn-macros.at <http://ovn-macros.at>])
>
>      m4_include([tests/completion.at <http://completion.at>])
>      m4_include([tests/checkpatch.at <http://checkpatch.at>])
>     @@ -74,13 +73,6 @@ m4_include([tests/rstp.at <http://rstp.at>])
>      m4_include([tests/vlog.at <http://vlog.at>])
>      m4_include([tests/vtep-ctl.at <http://vtep-ctl.at>])
>      m4_include([tests/auto-attach.at <http://auto-attach.at>])
>     -m4_include([tests/ovn.at <http://ovn.at>])
>     -m4_include([tests/ovn-northd.at <http://ovn-northd.at>])
>     -m4_include([tests/ovn-nbctl.at <http://ovn-nbctl.at>])
>     -m4_include([tests/ovn-sbctl.at <http://ovn-sbctl.at>])
>     -m4_include([tests/ovn-controller.at <http://ovn-controller.at>])
>     -m4_include([tests/ovn-controller-vtep.at
>     <http://ovn-controller-vtep.at>])
>      m4_include([tests/mcast-snooping.at <http://mcast-snooping.at>])
>      m4_include([tests/packet-type-aware.at
>     <http://packet-type-aware.at>])
>      m4_include([tests/nsh.at <http://nsh.at>])
>     -m4_include([tests/ovn-performance.at <http://ovn-performance.at>])
>     -- 
>     1.8.3.1
>
>     _______________________________________________
>     dev mailing list
>     dev@openvswitch.org <mailto:dev@openvswitch.org>
>     https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Mark Michelson Sept. 6, 2019, 7:10 p.m. UTC | #3
On 9/5/19 5:30 PM, Gregory Rose wrote:
> 
> On 9/5/2019 12:00 PM, Numan Siddique wrote:
>>
>> [snip]
>> Hi Greg,
>>
>> This seems reasonable to me. Mark has already submitted a patch to delete
>> the OVN folder. But we may have to keep ovn-nbctl/ovn-sbctl utilities
>> and OVN schema files for ovsdb-server RAFT tests.
>>
>> Until that patch is merged, this seems fine to me.
> 
> I should have a look at Mark's patch - this work probably needs integration
> with that.

FYI, I've just submitted a new version of that patch[1]. The version 
keeps the ovn-nbctl and ovn-sbctl utilities for the ovsdb-clustering 
tests. However, all other OVN tests have been removed. Like Numan was
suggesting, this may be a problem that requires fixing in the OVN repo.

[1] http://patchwork.ozlabs.org/patch/1159033/

> 
>>
>> Can you please provide the steps you use to run the system tests ?
>> I will try to run in the new ovn repo and see if we see failures there.
>> I tried sometime back and all the tests fail for me. Probably I wasn't
>> running as expected.
> 
> Build OVS using the '--with-linux=/lib/modules/$(uname -r)/build 
> --enable-Werror'
> to get the kernel datapath and then in the directory where you built OVS 
> run this
> command:
> 
> 'sudo make check-kmod'
> 
> To only run the ovn tests:
> 
> 'sudo make check-kmod TESTSUITEFLAGS="-k ovn"'
> 
> Thanks!
> 
> - Greg
> 
>>     ---
>>      tests/automake.mk <http://automake.mk>         |    23 +-
>>      tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at> |
>>      467 --
>>      tests/ovn-controller.at <http://ovn-controller.at>     |   294 -
>>      tests/ovn-macros.at <http://ovn-macros.at>         |   180 -
>>      tests/ovn-nbctl.at <http://ovn-nbctl.at>        |  1660 -----
>>      tests/ovn-northd.at <http://ovn-northd.at>         |   900 ---
>>      tests/ovn-performance.at <http://ovn-performance.at>    |   424 --
>>      tests/ovn-sbctl.at <http://ovn-sbctl.at>        |   150 -
>>      tests/ovn.at <http://ovn.at>        | 14702
>>     -----------------------------------------
>>      tests/system-ovn.at <http://system-ovn.at>         |  1667 -----
>>      tests/test-ovn.c             |  1584 -----
>>      tests/testsuite.at <http://testsuite.at>        |     8 -
>>      12 files changed, 4 insertions(+), 22055 deletions(-)
>>      delete mode 100644 tests/ovn-controller-vtep.at
>>     <http://ovn-controller-vtep.at>
>>      delete mode 100644 tests/ovn-controller.at 
>> <http://ovn-controller.at>
>>      delete mode 100644 tests/ovn-macros.at <http://ovn-macros.at>
>>      delete mode 100644 tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>      delete mode 100644 tests/ovn-northd.at <http://ovn-northd.at>
>>      delete mode 100644 tests/ovn-performance.at
>>     <http://ovn-performance.at>
>>      delete mode 100644 tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>      delete mode 100644 tests/ovn.at <http://ovn.at>
>>      delete mode 100644 tests/system-ovn.at <http://system-ovn.at>
>>      delete mode 100644 tests/test-ovn.c
>>
>>     diff --git a/tests/automake.mk <http://automake.mk>
>>     b/tests/automake.mk <http://automake.mk>
>>     index d6ab517..decca46 100644
>>     --- a/tests/automake.mk <http://automake.mk>
>>     +++ b/tests/automake.mk <http://automake.mk>
>>     @@ -23,8 +23,7 @@ EXTRA_DIST += \
>>      COMMON_MACROS_AT = \
>>             tests/ovsdb-macros.at <http://ovsdb-macros.at> \
>>             tests/ovs-macros.at <http://ovs-macros.at> \
>>     -       tests/ofproto-macros.at <http://ofproto-macros.at> \
>>     -       tests/ovn-macros.at <http://ovn-macros.at>
>>     +       tests/ofproto-macros.at <http://ofproto-macros.at>
>>
>>      TESTSUITE_AT = \
>>             tests/testsuite.at <http://testsuite.at> \
>>     @@ -104,16 +103,9 @@ TESTSUITE_AT = \
>>             tests/vlog.at <http://vlog.at> \
>>             tests/vtep-ctl.at <http://vtep-ctl.at> \
>>             tests/auto-attach.at <http://auto-attach.at> \
>>     -       tests/ovn.at <http://ovn.at> \
>>     -       tests/ovn-northd.at <http://ovn-northd.at> \
>>     -       tests/ovn-nbctl.at <http://ovn-nbctl.at> \
>>     -       tests/ovn-sbctl.at <http://ovn-sbctl.at> \
>>     -       tests/ovn-controller.at <http://ovn-controller.at> \
>>     -       tests/ovn-controller-vtep.at 
>> <http://ovn-controller-vtep.at> \
>>             tests/mcast-snooping.at <http://mcast-snooping.at> \
>>             tests/packet-type-aware.at <http://packet-type-aware.at> \
>>     -       tests/nsh.at <http://nsh.at> \
>>     -       tests/ovn-performance.at <http://ovn-performance.at>
>>     +       tests/nsh.at <http://nsh.at>
>>
>>      EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
>>      FUZZ_REGRESSION_TESTS = \
>>     @@ -158,7 +150,6 @@ SYSTEM_KMOD_TESTSUITE_AT = \
>>
>>      SYSTEM_USERSPACE_TESTSUITE_AT = \
>>             tests/system-userspace-testsuite.at
>>     <http://system-userspace-testsuite.at> \
>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>             tests/system-userspace-macros.at
>>     <http://system-userspace-macros.at> \
>>             tests/system-userspace-packet-type-aware.at
>>     <http://system-userspace-packet-type-aware.at>
>>
>>     @@ -169,7 +160,6 @@ SYSTEM_AFXDP_TESTSUITE_AT = \
>>
>>      SYSTEM_TESTSUITE_AT = \
>>             tests/system-common-macros.at
>>     <http://system-common-macros.at> \
>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>             tests/system-layer3-tunnels.at
>>     <http://system-layer3-tunnels.at> \
>>             tests/system-traffic.at <http://system-traffic.at> \
>>             tests/system-interface.at <http://system-interface.at>
>>     @@ -197,7 +187,7 @@ SYSTEM_DPDK_TESTSUITE =
>>     $(srcdir)/tests/system-dpdk-testsuite
>>      OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
>>      DISTCLEANFILES += tests/atconfig tests/atlocal
>>
>>     -AUTOTEST_PATH =
>>     
>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller 
>>
>>     +AUTOTEST_PATH =
>>     
>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR)
>>
>>      check-local:
>>             set $(SHELL) '$(TESTSUITE)' -C tests
>>     AUTOTEST_PATH=$(AUTOTEST_PATH); \
>>     @@ -238,10 +228,6 @@ check-lcov: all $(check_DATA) clean-lcov
>>      # valgrind support
>>
>>      valgrind_wrappers = \
>>     -       tests/valgrind/ovn-controller \
>>     -       tests/valgrind/ovn-nbctl \
>>     -       tests/valgrind/ovn-northd \
>>     -       tests/valgrind/ovn-sbctl \
>>             tests/valgrind/ovs-appctl \
>>             tests/valgrind/ovs-ofctl \
>>             tests/valgrind/ovs-vsctl \
>>     @@ -446,7 +432,6 @@ tests_ovstest_SOURCES = \
>>             tests/test-netflow.c \
>>             tests/test-odp.c \
>>             tests/test-ofpbuf.c \
>>     -       tests/test-ovn.c \
>>             tests/test-packets.c \
>>             tests/test-random.c \
>>             tests/test-rcu.c \
>>     @@ -474,7 +459,7 @@ tests_ovstest_SOURCES += \
>>             tests/test-netlink-conntrack.c
>>      endif
>>
>>     -tests_ovstest_LDADD = lib/libopenvswitch.la
>>     <http://libopenvswitch.la> ovn/lib/libovn.la <http://libovn.la>
>>     +tests_ovstest_LDADD = lib/libopenvswitch.la
>>     <http://libopenvswitch.la>
>>
>>      noinst_PROGRAMS += tests/test-stream
>>      tests_test_stream_SOURCES = tests/test-stream.c
>>     diff --git a/tests/ovn-controller-vtep.at
>>     <http://ovn-controller-vtep.at> b/tests/ovn-controller-vtep.at
>>     <http://ovn-controller-vtep.at>
>>     deleted file mode 100644
>>     index a3fe8cb..0000000
>>     --- a/tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at>
>>     +++ /dev/null
>>     @@ -1,467 +0,0 @@
>>     -AT_BANNER([ovn_controller_vtep])
>>     -
>>     -# OVN_CONTROLLER_VTEP_START
>>     -#
>>     -# Starts the test with a setup with vtep device.  Each test case
>>     must first
>>     -# call this macro.
>>     -#
>>     -# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two
>>     physical ports
>>     -# 'p0', 'p1'.
>>     -#
>>     -# Configures ovn-nb with a logical switch 'br-test'.
>>     -#
>>     -#
>>     -m4_define([OVN_CONTROLLER_VTEP_START],
>>     -  [
>>     -   AT_KEYWORDS([ovn])
>>     -   # this will cause skip when 'make check' using Windows setup.
>>     -   AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -
>>     -   dnl Create databases (ovn-nb, ovn-sb, vtep).
>>     -   AT_CHECK([ovsdb-tool create vswitchd.db
>>     $abs_top_srcdir/vswitchd/vswitch.ovsschema])
>>     -   for daemon in ovn-nb ovn-sb vtep; do
>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>     -   done
>>     -
>>     -   dnl Start ovsdb-server.
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>     --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db
>>     vtep.db], [0], [], [stderr])
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>     --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log
>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>     [stderr])
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>     --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log
>>     --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db],
>>     [0], [], [stderr])
>>     -   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid`
>>     `cat ovsdb-sb-server.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d
>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>     -
>>     -   dnl Start ovs-vswitchd.
>>     -   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system
>>     --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif],
>>     [0], [], [stderr])
>>     -   AT_CAPTURE_FILE([ovs-vswitchd.log])
>>     -   on_exit "kill `cat ovs-vswitchd.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/ovs_numa|INFO|Discovered /d
>>     -/vlog|INFO|opened log file/d
>>     -/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
>>     -/reconnect|INFO|/d
>>     -/ofproto|INFO|using datapath ID/d
>>     -/netlink_socket|INFO|netlink: could not enable listening to all
>>     nsid/d
>>     -/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
>>     -   AT_CHECK([ovs-vsctl -- add-br br-vtep \
>>     -              -- set bridge br-vtep datapath-type=dummy
>>     other-config:datapath-id=fedcba9876543210
>>     other-config:hwaddr=aa:55:aa:55:00:00
>>     
>> protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] 
>>
>>     fail-mode=secure \
>>     -              -- add-port br-vtep p0 -- set Interface p0
>>     type=dummy ofport_request=1 \
>>     -              -- add-port br-vtep p1 -- set Interface p1
>>     type=dummy ofport_request=2])
>>     -
>>     -   dnl Start ovs-vtep.
>>     -   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch
>>     br-vtep tunnel_ips=1.2.3.4])
>>     -   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log
>>     --pidfile=ovs-vtep.pid --detach --no-chdir br-vtep \], [0], [],
>>     [stderr])
>>     -   on_exit "kill `cat ovs-vtep.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d']])
>>     -   # waits until ovs-vtep starts up.
>>     -   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])
>>     -
>>     -   dnl Start ovn-northd.
>>     -   AT_CHECK([ovn-nbctl ls-add br-test])
>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile
>>     --log-file], [0], [], [stderr])
>>     -   on_exit "kill `cat ovn-northd.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d']])
>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>     -
>>     -   dnl Start ovn-controllger-vtep.
>>     -   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile
>>     --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock
>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>     -   AT_CAPTURE_FILE([ovn-controller-vtep.log])
>>     -   on_exit "kill `cat ovn-controller-vtep.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d
>>     -/reconnect|INFO|/d']])
>>     -])
>>     -
>>     -# OVN_CONTROLLER_VTEP_STOP
>>     -#
>>     -# So many exits... Yeah, we started a lot daemons~
>>     -#
>>     -m4_define([OVN_CONTROLLER_VTEP_STOP],
>>     -  [AT_CHECK([check_logs "$1"])
>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>     -   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
>>     -
>>     -# Adds logical port for a vtep gateway chassis in ovn-nb database.
>>     -#
>>     -# $1: logical switch name in ovn-nb database
>>     -# $2: logical port name
>>     -# $3: physical vtep gateway name
>>     -# $4: logical switch name on vtep gateway chassis
>>     -m4_define([OVN_NB_ADD_VTEP_PORT], [
>>     -AT_CHECK([ovn-nbctl lsp-add $1 $2])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
>>     -AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3
>>     vtep-logical-switch=$4])
>>     -])
>>     -
>>     -##############################################
>>     -
>>     -# tests chassis related updates.
>>     -AT_SETUP([ovn-controller-vtep - chassis])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# verifies the initial ovn-sb db configuration.
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>     -Chassis br-vtep
>>     -    Encap vxlan
>>     -        ip: "1.2.3.4"
>>     -        options: {csum="false"}
>>     -])
>>     -
>>     -# deletes the chassis via ovn-sbctl and check that it is readded 
>> back
>>     -# with the log.
>>     -AT_CHECK([ovn-sbctl chassis-del br-vtep])
>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>     ovn-controller-vtep.log], [0], [dnl
>>     -|WARN|Chassis for VTEP physical switch (br-vtep) disappears,
>>     maybe deleted by ovn-sbctl, adding it back
>>     -])
>>     -
>>     -# changes the tunnel_ip on physical switch, watches the update of
>>     chassis's
>>     -# encap.
>>     -AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
>>     -AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr
>>     -d ' '], [0], [dnl
>>     -"1.2.3.5"
>>     -])
>>     -
>>     -# adds vlan_bindings to physical ports.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1
>>     300 lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>     lswitch0`"])
>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>     -[[lswitch0]]
>>     -])
>>     -
>>     -# adds another logical switch and new vlan_bindings.
>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300
>>     lswitch1])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>     lswitch1`"])
>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -[[lswitch0,lswitch1]]
>>     -])
>>     -
>>     -# unbinds one port from lswitch0, nothing should change.
>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list
>>     physical_port p0 | grep -- '200='`"])
>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>     -[[lswitch0,lswitch1]]
>>     -])
>>     -
>>     -# unbinds all ports from lswitch0.
>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep
>>     p1 300])
>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>     br-vtep_lswitch0`"])
>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>     -[[lswitch1]]
>>     -])
>>     -
>>     -# unbinds all ports from lswitch1.
>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>     br-vtep_lswitch1`"])
>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -[[]]
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch
>>     (br-vtep) disappears/d])
>>     -AT_CLEANUP
>>     -
>>     -
>>     -# Tests binding updates.
>>     -AT_SETUP([ovn-controller-vtep - binding 1])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
>>     -# adds logical switch port in ovn-nb database, and sets the type
>>     and options.
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>     [lswitch0])
>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>     chassis!='[[]]'
>>     -# should see one binding, associated to chassis of 'br-vtep'.
>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>     cut -d ':' -f2 | tr -d ' ')
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -${chassis_uuid}
>>     -])
>>     -
>>     -# adds another logical switch 'lswitch1' and vlan_bindings.
>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>     lswitch1])
>>     -# adds logical switch port in ovn-nb database for lswitch1.
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep],
>>     [lswitch1])
>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1
>>     chassis!='[[]]'
>>     -# This is allowed, but not recommended, to have two vlan_bindings
>>     (to different vtep logical switches)
>>     -# from one vtep gateway physical port in one ovn-nb logical swithch.
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>     -
>>     -${chassis_uuid}
>>     -${chassis_uuid}
>>     -])
>>     -
>>     -# adds another logical switch port in ovn-nb database for lswitch0.
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup],
>>     [br-vtep], [lswitch0])
>>     -ovn-sbctl --timeout=10 wait-until Port_Binding
>>     br-vtep_lswitch0_dup chassis!='[[]]'
>>     -# it is not allowed to have more than one ovn-nb logical port for
>>     the same
>>     -# vtep logical switch on a vtep gateway chassis, so should still
>>     see only
>>     -# two port_binding entries bound.
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>     | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
>>     -
>>     -
>>     -[[]]
>>     -${chassis_uuid}
>>     -${chassis_uuid}
>>     -])
>>     -# confirms the warning log.
>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>     ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g'
>>     | uniq], [0], [dnl
>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>     been associated with logical port (), ignore logical port ()
>>     -])
>>     -
>>     -# deletes physical ports from vtep.
>>     -AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>     br-vtep_lswitch`"])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
>>     -# should see empty chassis column in both binding entries.
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>     -
>>     -
>>     -[[]]
>>     -[[]]
>>     -[[]]
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>     logical port/d])
>>     -AT_CLEANUP
>>     -
>>     -
>>     -# Tests corner case: Binding the vtep logical switch from two
>>     different
>>     -# datapath.
>>     -AT_SETUP([ovn-controller-vtep - binding 2])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0])
>>     -# adds logical switch port in ovn-nb database, and sets the type
>>     and options.
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>     [lswitch0])
>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>     chassis!='[[]]'
>>     -
>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>     p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
>>     -# adds a conflicting logical port (both br-vtep_lswitch0 and
>>     br-vtep-void_lswitch0
>>     -# are bound to the same logical switch, but they are on different
>>     datapath).
>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0],
>>     [br-vtep-void], [lswitch0])
>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>     -# confirms the warning log.
>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>     ovn-controller-vtep.log | sed
>>     's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key
>>     [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>     been associated with logical datapath (), ignore logical port ()
>>     which belongs to logical datapath ()
>>     -])
>>     -
>>     -# then deletes 'br-void' and 'br-vtep-void', should see
>>     'br-vtep_lswitch0'
>>     -# bound correctly.
>>     -AT_CHECK([ovn-nbctl ls-del br-void])
>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep
>>     br-vtep-void_lswitch0`"])
>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>     cut -d ':' -f2 | tr -d ' ')
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -${chassis_uuid}
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>     logical datapath/d])
>>     -AT_CLEANUP
>>     -
>>     -
>>     -# Tests vtep module vtep logical switch tunnel key update.
>>     -AT_SETUP([ovn-controller-vtep - vtep-lswitch])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# creates the logical switch in vtep and adds the corresponding
>>     logical
>>     -# port to 'br-test'.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0])
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>     [lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>>     br-vtep_lswitch0`"])
>>     -
>>     -# retrieves the expected tunnel key.
>>     -datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding
>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
>>     -tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding
>>     ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>     Logical_Switch | grep 0`"])
>>     -# checks the vtep logical switch tunnel key configuration.
>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -${tunnel_key}
>>     -])
>>     -
>>     -# creates a second physical switch in vtep database, and binds
>>     its p0 vlan-100
>>     -# to the same logical switch 'lswitch0'.
>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>     p0 -- bind-ls br-vtep-void p0 100 lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis
>>     | grep -- br-vtep-void`"])
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0],
>>     [br-vtep-void], [lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>>     br-vtep-void_lswitch0`"])
>>     -
>>     -# checks the vtep logical switch tunnel key configuration.
>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -${tunnel_key}
>>     -])
>>     -
>>     -# now, deletes br-vtep-void.
>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis
>>     | grep -- br-vtep-void`"])
>>     -# checks the vtep logical switch tunnel key configuration.
>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -${tunnel_key}
>>     -])
>>     -
>>     -# changes the ovn-nb logical port type so that it is no longer
>>     -# vtep port.
>>     -AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>     Logical_Switch | grep 1`"])
>>     -# now should see the tunnel key reset.
>>     -AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut
>>     -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -0
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP
>>     -AT_CLEANUP
>>     -
>>     -
>>     -# Tests vtep module 'Ucast_Macs_Remote's.
>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 1])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# creates a simple logical network with the vtep device and a
>>     fake hv chassis
>>     -# 'ch0'.
>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>     -
>>     -# creates the logical switch in vtep and adds the corresponding
>>     logical
>>     -# port to 'br-test'.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0])
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>     [lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>     br-vtep_lswitch0`"])
>>     -
>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>     -# adds fake hv chassis 'ch1'.
>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>     -
>>     -# checks Ucast_Macs_Remote creation.
>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>     _uuid`"])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' '], [0], [dnl
>>     -"f0:ab:cd:ef:01:02"
>>     -])
>>     -
>>     -# checks physical locator creation.
>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep
>>     _uuid`"])
>>     -AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut
>>     -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
>>     -"1.2.3.5"
>>     -])
>>     -
>>     -# checks tunnel creation by ovs-vtep.
>>     -OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
>>     -AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 |
>>     cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>     -{remote_ip="1.2.3.5"}
>>     -])
>>     -
>>     -# adds another mac to logical switch port.
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02
>>     f0:ab:cd:ef:01:03])
>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>     03`"])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>     -
>>     -"f0:ab:cd:ef:01:02"
>>     -"f0:ab:cd:ef:01:03"
>>     -])
>>     -
>>     -# removes one mac to logical switch port.
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>     Ucast_Macs_Remote | grep 02`"])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>     -"f0:ab:cd:ef:01:03"
>>     -])
>>     -
>>     -# migrates mac to logical switch port vif1 on 'br-void'.
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>     Ucast_Macs_Remote | grep 03`"])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP
>>     -AT_CLEANUP
>>     -
>>     -
>>     -# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 2])
>>     -OVN_CONTROLLER_VTEP_START
>>     -
>>     -# creates a simple logical network with the vtep device and a
>>     fake hv chassis
>>     -# 'ch0'.
>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>     -
>>     -# creates another vif in the same logical switch with duplicate mac.
>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>     -
>>     -# creates the logical switch in vtep and adds the corresponding
>>     logical
>>     -# port to 'br-test'.
>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>     lswitch0])
>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>     [lswitch0])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>     br-vtep_lswitch0`"])
>>     -
>>     -# checks Ucast_Macs_Remote creation.  Should still only be one
>>     entry, since duplicate
>>     -# mac in the same logical switch is not allowed.
>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>     _uuid`"])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' '], [0], [dnl
>>     -"f0:ab:cd:ef:01:02"
>>     -])
>>     -# confirms the warning log.
>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>     ovn-controller-vtep.log | sed
>>     's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
>>     -|WARN|MAC address () has already been known to be on logical port
>>     () in the same logical datapath, so just ignore this logical port ()
>>     -])
>>     -
>>     -# deletes vif1.
>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>     -
>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>     -# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep 
>> vif1`"])
>>     -
>>     -# creates another logical switch in vtep and adds the
>>     corresponding logical
>>     -# port to 'br-void'.
>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>     lswitch1])
>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep],
>>     [lswitch1])
>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>     br-void_lswitch1`"])
>>     -
>>     -# checks Ucast_Macs_Remote creation.  Should see two entries
>>     since it is allowed
>>     -# to have duplicate macs in different logical switches.
>>     -OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list
>>     Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>     -
>>     -"f0:ab:cd:ef:01:02"
>>     -"f0:ab:cd:ef:01:02"
>>     -])
>>     -
>>     -OVN_CONTROLLER_VTEP_STOP([/has already been known to be on
>>     logical port/d])
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn-controller.at <http://ovn-controller.at>
>>     b/tests/ovn-controller.at <http://ovn-controller.at>
>>     deleted file mode 100644
>>     index 343c2ab..0000000
>>     --- a/tests/ovn-controller.at <http://ovn-controller.at>
>>     +++ /dev/null
>>     @@ -1,294 +0,0 @@
>>     -AT_BANNER([ovn-controller])
>>     -
>>     -AT_SETUP([ovn-controller - ovn-bridge-mappings])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_init_db ovn-sb
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0 \
>>     -    -- add-br br-eth1 \
>>     -    -- add-br br-eth2
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -# Waits until the OVS database contains exactly the specified
>>     patch ports.
>>     -# Each argument should be of the form BRIDGE PORT PEER.
>>     -check_patches () {
>>     -    # Generate code to check that the set of patch ports is
>>     exactly as
>>     -    # specified.
>>     -    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name
>>     find Interface type=patch | sort' > query
>>     -    for patch
>>     -    do
>>     -        echo $patch
>>     -    done | cut -d' ' -f 2 | sort > expout
>>     -
>>     -    # Generate code to verify that the configuration of each patch
>>     -    # port is correct.
>>     -    for patch
>>     -    do
>>     -        set $patch; bridge=$1 port=$2 peer=$3
>>     -        echo >>query "ovs-vsctl iface-to-br $port -- get
>>     Interface $port type options"
>>     -        echo >>expout "$bridge
>>     -patch
>>     -{peer=$peer}"
>>     -    done
>>     -
>>     -    # Run the query until we get the expected result (or until a
>>     timeout).
>>     -    #
>>     -    # (We use sed to drop all "s from output because ovs-vsctl
>>     quotes some
>>     -    # of the port names but not others.)
>>     -    AT_CAPTURE_FILE([query])
>>     -    AT_CAPTURE_FILE([expout])
>>     -    AT_CAPTURE_FILE([stdout])
>>     -    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
>>     -                    diff -u stdout expout >/dev/null])
>>     -}
>>     -
>>     -# Make sure that the configured bridge mappings in the
>>     Open_vSwitch db
>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>     -check_bridge_mappings () {
>>     -    local_mappings=$1
>>     -    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>     -    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get
>>     Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e
>>     's/\"//g')])
>>     -}
>>     -
>>     -# Initially there should be no patch ports.
>>     -check_patches
>>     -
>>     -# Configure two ovn-bridge mappings, but no patch ports should be
>>     created yet
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
>>     -check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
>>     -check_patches
>>     -
>>     -# Create a localnet port, but we should still have no patch
>>     ports, as they
>>     -# won't be created until there's a localnet port on a logical
>>     switch with
>>     -# another logical port bound to this chassis.
>>     -ovn-sbctl \
>>     -    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
>>     -    -- create Port_Binding datapath=@dp101 logical_port=localnet1
>>     tunnel_key=1 \
>>     -        type=localnet options:network_name=physnet1
>>     -check_patches
>>     -
>>     -# Create a localnet port on a logical switch with a port bound to
>>     this chassis.
>>     -# Now we should get some patch ports created.
>>     -ovn-sbctl \
>>     -    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
>>     -    -- create Port_Binding datapath=@dp102 logical_port=localnet2
>>     tunnel_key=1 \
>>     -        type=localnet options:network_name=physnet1 \
>>     -    -- create Port_Binding datapath=@dp102 logical_port=localvif2
>>     tunnel_key=2
>>     -ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
>>     external_ids:iface-id=localvif2
>>     -check_patches \
>>     -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>     -
>>     -# Add logical patch ports to connect new logical datapath.
>>     -#
>>     -# OVN no longer uses OVS patch ports to implement logical patch
>>     ports, so
>>     -# the set of OVS patch ports doesn't change.
>>     -AT_CHECK([ovn-sbctl \
>>     -    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
>>     -    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
>>     -    -- create Port_Binding datapath=@dp1 logical_port=foo
>>     tunnel_key=1 type=patch options:peer=bar \
>>     -    -- create Port_Binding datapath=@dp2 logical_port=bar
>>     tunnel_key=2 type=patch options:peer=foo \
>>     -    -- create Port_Binding datapath=@dp1 logical_port=dp1vif
>>     tunnel_key=3 \
>>     -| uuidfilt], [0], [<0>
>>     -<1>
>>     -<2>
>>     -<3>
>>     -<4>
>>     -])
>>     -ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif
>>     external_ids:iface-id=dp1vif
>>     -check_patches \
>>     -    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>     -
>>     -# Delete the mapping and the ovn-bridge-mapping patch ports
>>     should go away.
>>     -AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids
>>     ovn-bridge-mappings])
>>     -check_bridge_mappings
>>     -check_patches
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP_SBOX([hv])
>>     -OVN_CLEANUP_VSWITCH([main])
>>     -as ovn-sb
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# Checks that ovn-controller populates datapath-type and iface-types
>>     -# correctly in the Chassis external-ids column.
>>     -AT_SETUP([ovn-controller - Chassis external_ids])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_init_db ovn-sb
>>     -
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0 \
>>     -    -- add-br br-eth1 \
>>     -    -- add-br br-eth2
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>     -
>>     -# Make sure that the datapath_type set in the Bridge table
>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>     -check_datapath_type () {
>>     -    datapath_type=$1
>>     -    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid}
>>     external_ids:datapath-type | sed -e 's/"//g') #"
>>     -    test "${datapath_type}" = "${chassis_datapath_type}"
>>     -}
>>     -
>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>     -
>>     -ovs-vsctl set Bridge br-int datapath-type=foo
>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>     -
>>     -# Change "ovn-bridge-mappings" value. It should not change the
>>     "datapath-type".
>>     -ovs-vsctl set Open_vSwitch .
>>     external_ids:ovn-bridge-mappings=foo-mapping
>>     -check_datapath_type foo
>>     -
>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>     -OVS_WAIT_UNTIL([check_datapath_type bar])
>>     -
>>     -ovs-vsctl set Bridge br-int datapath-type=\"\"
>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>     -
>>     -# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
>>     -ovs-vsctl set Open_vSwitch .
>>     external_ids:ovn-bridge-datapath-type=foo
>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>     -
>>     -# Change the br-int's datapath type to bar.
>>     -# It should be reset to foo since ovn-bridge-datapath-type is
>>     configured.
>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>     -OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int
>>     datapath-type`])
>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>     -
>>     -ovs-vsctl set Open_vSwitch .
>>     external_ids:ovn-bridge-datapath-type=foobar
>>     -OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int
>>     datapath-type`])
>>     -OVS_WAIT_UNTIL([check_datapath_type foobar])
>>     -
>>     -expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types |
>>     tr -d '[[]] ""')
>>     -echo "expected_iface_types = ${expected_iface_types}"
>>     -chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>     external_ids:iface-types | sed -e 's/\"//g')
>>     -echo "chassis_iface_types = ${chassis_iface_types}"
>>     -AT_CHECK([test "${expected_iface_types}" = 
>> "${chassis_iface_types}"])
>>     -
>>     -# Change the value of external_ids:iface-types using ovn-sbctl.
>>     -# ovn-controller should again set it back to proper one.
>>     -ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
>>     -OVS_WAIT_UNTIL([
>>     -    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>     external_ids:iface-types | sed -e 's/\"//g')
>>     -    echo "chassis_iface_types = ${chassis_iface_types}"
>>     -    test "${expected_iface_types}" = "${chassis_iface_types}"
>>     -])
>>     -
>>     -# Change the value of external_ids:system-id and make sure it's
>>     mirrored
>>     -# in the Chassis record in the OVN_Southbound database.
>>     -sysid=${sysid}-foo
>>     -ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
>>     -OVS_WAIT_UNTIL([
>>     -    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
>>     -    test "${sysid}" = "${chassis_id}"
>>     -])
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP_SBOX([hv])
>>     -OVN_CLEANUP_VSWITCH([main])
>>     -as ovn-sb
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# Checks that ovn-controller correctly maintains the mapping from
>>     the Encap
>>     -# table in the Southbound database to OVS in the face of changes
>>     on both sides
>>     -AT_SETUP([ovn-controller - change Encap properties])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_init_db ovn-sb
>>     -
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0 \
>>     -    -- add-br br-eth1 \
>>     -    -- add-br br-eth2
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -check_tunnel_property () {
>>     -    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
>>     -}
>>     -
>>     -# Start off with a remote chassis supporting STT
>>     -ovn-sbctl chassis-add fakechassis stt 192.168.0.2
>>     -OVS_WAIT_UNTIL([check_tunnel_property type stt])
>>     -
>>     -# See if we switch to Geneve as the first choice when it is 
>> available
>>     -# With multi-VTEP support we support tunnels with different IPs
>>     to the
>>     -# same chassis, and hence use the IP to annotate the tunnel
>>     (along with
>>     -# the chassis-id in ovn-chassis-id); if we supply a different IP 
>> here
>>     -# we won't be able to co-relate this to the tunnel port that was
>>     created
>>     -# in the previous step and, as a result, will end up creating
>>     another tunnel,
>>     -# ie. we can't just lookup using "ovn-fakech-0". So, need to use
>>     the same IP
>>     -# as above, i.e 192.168.0.2, here.
>>     -encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap --
>>     --id=@encap create encap type=geneve ip="192.168.0.2")
>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>     -
>>     -# Check that changes within an encap row are propagated
>>     -ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
>>     -OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip
>>     "\"192.168.0.2\""])
>>     -
>>     -# Change the type on the OVS side and check than OVN fixes it
>>     -ovs-vsctl set interface ovn-fakech-0 type=vxlan
>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>     -
>>     -# Delete the port entirely and it should be resurrected
>>     -ovs-vsctl del-port ovn-fakech-0
>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP_SBOX([hv])
>>     -OVN_CLEANUP_VSWITCH([main])
>>     -as ovn-sb
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# Check ovn-controller connection status to Southbound database
>>     -AT_SETUP([ovn-controller - check sbdb connection])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_init_db ovn-sb
>>     -
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0 \
>>     -    -- add-br br-eth1 \
>>     -    -- add-br br-eth2
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -check_sbdb_connection () {
>>     -    test "$(ovs-appctl -t ovn-controller connection-status)" = "$1"
>>     -}
>>     -
>>     -OVS_WAIT_UNTIL([check_sbdb_connection connected])
>>     -
>>     -ovs-vsctl set open .
>>     external_ids:ovn-remote=tcp:192.168.0.10:6642
>>     <http://192.168.0.10:6642>
>>     -OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
>>     -
>>     -# reset the remote for clean-up
>>     -ovs-vsctl set open .
>>     external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP_SBOX([hv])
>>     -OVN_CLEANUP_VSWITCH([main])
>>     -as ovn-sb
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn-macros.at <http://ovn-macros.at>
>>     b/tests/ovn-macros.at <http://ovn-macros.at>
>>     deleted file mode 100644
>>     index 7dba42c..0000000
>>     --- a/tests/ovn-macros.at <http://ovn-macros.at>
>>     +++ /dev/null
>>     @@ -1,180 +0,0 @@
>>     -# OVN_CLEANUP_VSWITCH(sim)
>>     -#
>>     -# Gracefully terminate vswitch daemons in the
>>     -# specified sandbox.
>>     -m4_define([OVN_CLEANUP_VSWITCH],[
>>     -    as $1
>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>     -    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -])
>>     -
>>     -# OVN_CLEANUP_SBOX(sbox)
>>     -#
>>     -# Gracefully terminate OVN daemons in the specified
>>     -# sandbox instance. The sandbox name "vtep" is treated
>>     -# as a special case, and is assumed to have ovn-controller-vtep
>>     -# and ovs-vtep daemons running instead of ovn-controller.
>>     -m4_define([OVN_CLEANUP_SBOX],[
>>     -    as $1
>>     -    if test "$1" = "vtep"; then
>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>     -        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>     -    else
>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -    fi
>>     -    OVN_CLEANUP_VSWITCH([$1])
>>     -])
>>     -
>>     -# OVN_CLEANUP(sim [, sim ...])
>>     -#
>>     -# Gracefully terminate all OVN daemons, including those in the
>>     -# specified sandbox instances.
>>     -m4_define([OVN_CLEANUP],[
>>     -    m4_foreach([sbox], [$@], [
>>     -        OVN_CLEANUP_SBOX([sbox])
>>     -    ])
>>     -    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 northd-backup
>>     -    OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>     -
>>     -    OVN_CLEANUP_VSWITCH([main])
>>     -])
>>     -
>>     -m4_divert_push([PREPARE_TESTS])
>>     -
>>     -# ovn_init_db DATABASE
>>     -#
>>     -# Creates and initializes the given DATABASE (one of "ovn-sb" or
>>     "ovn-nb"),
>>     -# starts its ovsdb-server instance, and sets the appropriate
>>     environment
>>     -# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or
>>     ovn-nbctl uses the
>>     -# database by default.
>>     -#
>>     -# Usually invoked from ovn_start.
>>     -ovn_init_db () {
>>     -    echo "creating $1 database"
>>     -    local d=$ovs_base/$1
>>     -    mkdir "$d" || return 1
>>     -    : > "$d"/.$1.db.~lock~
>>     -    as $1 ovsdb-tool create "$d"/$1.db
>>     "$abs_top_srcdir"/ovn/$1.ovsschema
>>     -    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock
>>     "$d"/$1.db
>>     -    local var=`echo $1_db | tr a-z- A-Z_`
>>     -    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
>>     -}
>>     -
>>     -# ovn_start
>>     -#
>>     -# Creates and initializes ovn-sb and ovn-nb databases and starts
>>     their
>>     -# ovsdb-server instance, sets appropriate environment variables
>>     so that
>>     -# ovn-sbctl and ovn-nbctl use them by default, and starts
>>     ovn-northd running
>>     -# against them.
>>     -ovn_start () {
>>     -    ovn_init_db ovn-sb; ovn-sbctl init
>>     -    ovn_init_db ovn-nb; ovn-nbctl init
>>     -
>>     -    echo "starting ovn-northd"
>>     -    mkdir "$ovs_base"/northd
>>     -    as northd start_daemon ovn-northd -v \
>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -
>>     -    echo "starting backup ovn-northd"
>>     -    mkdir "$ovs_base"/northd-backup
>>     -    as northd-backup start_daemon ovn-northd -v \
>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -}
>>     -
>>     -# Interconnection networks.
>>     -#
>>     -# When multiple sandboxed Open vSwitch instances exist, one will
>>     inevitably
>>     -# want to connect them together.  These commands allow for that.
>>     Conceptually,
>>     -# an interconnection network is a switch for which these
>>     functions make it easy
>>     -# to plug into other switches in other sandboxed Open vSwitch
>>     instances.
>>     -# Interconnection networks are implemented as bridges in a switch
>>     named "main",
>>     -# so to use interconnection networks please avoid working with
>>     that switch
>>     -# directly.
>>     -
>>     -# net_add NETWORK
>>     -#
>>     -# Creates a new interconnection network named NETWORK.
>>     -net_add () {
>>     -    test -d "$ovs_base"/main || sim_add main || return 1
>>     -    as main ovs-vsctl add-br "$1"
>>     -}
>>     -
>>     -# net_attach NETWORK BRIDGE
>>     -#
>>     -# Adds a new port to BRIDGE in the default sandbox (as set with
>>     as()) and plugs
>>     -# it into the NETWORK interconnection network.  NETWORK must
>>     already have been
>>     -# created by a previous invocation of net_add.  The default
>>     sandbox must not be
>>     -# "main".
>>     -net_attach () {
>>     -    local net=$1 bridge=$2
>>     -
>>     -    local port=${sandbox}_$bridge
>>     -    as main ovs-vsctl \
>>     -        -- add-port $net $port \
>>     -        -- set Interface $port
>>     options:pstream="punix:$ovs_base/main/$port.sock"
>>     options:rxq_pcap="$ovs_base/main/$port-rx.pcap"
>>     options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
>>     -        || return 1
>>     -
>>     -    ovs-vsctl \
>>     -        -- set Interface $bridge
>>     options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap"
>>     options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
>>     -        -- add-port $bridge ${bridge}_$net \
>>     -        -- set Interface ${bridge}_$net
>>     options:stream="unix:$ovs_base/main/$port.sock"
>>     options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap"
>>     options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
>>     -        || return 1
>>     -}
>>     -
>>     -# ovn_attach NETWORK BRIDGE IP [MASKLEN]
>>     -#
>>     -# First, this command attaches BRIDGE to interconnection network
>>     NETWORK, just
>>     -# like "net_attach NETWORK BRIDGE".  Second, it configures
>>     (simulated) IP
>>     -# address IP (with network mask length MASKLEN, which defaults to
>>     24) on
>>     -# BRIDGE.  Finally, it configures the Open vSwitch database to
>>     work with OVN
>>     -# and starts ovn-controller.
>>     -ovn_attach() {
>>     -    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
>>     -    net_attach $net $bridge || return 1
>>     -
>>     -    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g`
>>     -    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
>>     -    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen
>>     >/dev/null || return 1
>>     -    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null ||
>>     return 1
>>     -    ovs-vsctl \
>>     -        -- set Open_vSwitch . external-ids:system-id=$sandbox \
>>     -        -- set Open_vSwitch .
>>     external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>>     -        -- set Open_vSwitch .
>>     external-ids:ovn-encap-type=geneve,vxlan \
>>     -        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
>>     -        -- add-br br-int \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true \
>>     -        || return 1
>>     -    start_daemon ovn-controller || return 1
>>     -}
>>     -
>>     -# OVN_POPULATE_ARP
>>     -#
>>     -# This pre-populates the ARP tables of all of the OVN instances
>>     that have been
>>     -# started with ovn_attach().  That means that packets sent from
>>     one hypervisor
>>     -# to another never get dropped or delayed by ARP resolution,
>>     which makes
>>     -# testing easier.
>>     -ovn_populate_arp__() {
>>     -    for e1 in $arp_table; do
>>     -        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4
>>     -        for e2 in $arp_table; do
>>     -            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
>>     -            if test $sb1,$br1 != $sb2,$br2; then
>>     -                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac ||
>>     return 1
>>     -            fi
>>     -        done
>>     -    done
>>     -}
>>     -m4_divert_pop([PREPARE_TESTS])
>>     -
>>     -m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0],
>>     [ignore])])
>>     diff --git a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>     b/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>     deleted file mode 100644
>>     index d99d3af..0000000
>>     --- a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>     +++ /dev/null
>>     @@ -1,1660 +0,0 @@
>>     -AT_BANNER([ovn-nbctl])
>>     -
>>     -OVS_START_SHELL_HELPERS
>>     -# OVN_NBCTL_TEST_START
>>     -m4_define([OVN_NBCTL_TEST_START],
>>     -  [AT_KEYWORDS([ovn])
>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>     -   ovn_nbctl_test_start $1])
>>     -ovn_nbctl_test_start() {
>>     -   dnl Create ovn-nb database.
>>     -   AT_CHECK([ovsdb-tool create ovn-nb.db
>>     $abs_top_srcdir/ovn/ovn-nb.ovsschema])
>>     -
>>     -   dnl Start ovsdb-server.
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>     --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db],
>>     [0], [], [stderr])
>>     -   on_exit "kill `cat ovsdb-server.pid`"
>>     -   AS_CASE([$1],
>>     -     [daemon],
>>     -       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach
>>     --no-chdir --log-file -vsocket_util:off)
>>     -        on_exit "kill `cat ovn-nbctl.pid`"],
>>     -     [direct], [],
>>     -     [*], [AT_FAIL_IF(:)])
>>     -   AT_CHECK([ovn-nbctl init])
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d
>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>     -}
>>     -
>>     -# OVN_NBCTL_TEST_STOP
>>     -m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
>>     -ovn_nbctl_test_stop() {
>>     -   AT_CHECK([check_logs "$1"])
>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -}
>>     -OVS_END_SHELL_HELPERS
>>     -
>>     -# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
>>     -m4_define([OVN_NBCTL_TEST],
>>     -   [OVS_START_SHELL_HELPERS
>>     -    $1() {
>>     -      $3
>>     -    }
>>     -    OVS_END_SHELL_HELPERS
>>     -
>>     -    AT_SETUP([ovn-nbctl - $2 - direct])
>>     -    OVN_NBCTL_TEST_START direct
>>     -    $1
>>     -    OVN_NBCTL_TEST_STOP
>>     -    AT_CLEANUP
>>     -
>>     -    AT_SETUP([ovn-nbctl - $2 - daemon])
>>     -    OVN_NBCTL_TEST_START daemon
>>     -    $1
>>     -    OVN_NBCTL_TEST_STOP
>>     -    AT_CLEANUP])
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>     -<0> (ls0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>     -<0> (ls0)
>>     -<1> (ls1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-del ls0])
>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>     -<0> (ls1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl show ls0])
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>     -  [switch <0> (ls0)
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
>>     -  [ovn-nbctl: ls0: a switch with this name already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>     -  [switch <0> (ls0)
>>     -])
>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], [1], 
>> [],
>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>     together
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
>>     -  [ovn-nbctl: Multiple logical switches named 'ls0'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
>>     -  [ovn-nbctl: ls2: switch name not found
>>     -])
>>     -AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add])
>>     -AT_CHECK([ovn-nbctl ls-add])
>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port
>>     commands], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
>>     -  [ovn-nbctl: lp0: a port with this name already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>     -<0> (lp0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>     -<0> (lp0)
>>     -<1> (lp1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
>>     -  [ovn-nbctl: lp1: a port with this name already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
>>     -  [ovn-nbctl: lp1: port already exists but in switch ls0
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
>>     -  [ovn-nbctl: lp1: port already exists but has no parent
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-del lp1])
>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>     -<0> (lp0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
>>     -  [ovn-nbctl: lp2: port already exists with different parent lp3
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
>>     -  [ovn-nbctl: lp2: port already exists with different tag_request 5
>>     -])
>>     -AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
>>     -  [ovn-nbctl: lp2: port already exists but has no tag_request
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
>>     -<0> (ls0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
>>     -  [ovn-nbctl: lp1: port name not found
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 
>> unknown])
>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>     -00:11:22:33:44:55
>>     -unknown
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff
>>     00:11:22:33:44:55])
>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>     -00:11:22:33:44:55
>>     -aa:bb:cc:dd:ee:ff
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
>>     -ovn_nbctl_test_acl() {
>>     -   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop])
>>     -   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info
>>     acl-add $1 to-lport 500 udp drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
>>     -   dnl Add duplicated ACL
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1],
>>     [], [stderr])
>>     -   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>     -   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip
>>     drop])
>>     -
>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>     -from-lport   600 (udp) drop log()
>>     -from-lport   400 (tcp) drop
>>     -from-lport   200 (ip) drop
>>     -  to-lport   500 (udp) drop log(name=test,severity=info)
>>     -  to-lport   300 (tcp) drop
>>     -  to-lport   100 (ip) drop
>>     -])
>>     -
>>     -   dnl Delete in one direction.
>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>     -from-lport   600 (udp) drop log()
>>     -from-lport   400 (tcp) drop
>>     -from-lport   200 (ip) drop
>>     -])
>>     -
>>     -   dnl Delete all ACLs.
>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1])
>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>     -])
>>     -
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>     -
>>     -   dnl Delete a single flow.
>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>     -from-lport   600 (udp) drop
>>     -from-lport   200 (ip) drop
>>     -])
>>     -}
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -ovn_nbctl_test_acl ls0
>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>     -ovn_nbctl_test_acl ls1 --type=switch
>>     -AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
>>     -ovn_nbctl_test_acl pg0 --type=port-group
>>     -
>>     -dnl Test when port group doesn't exist
>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip
>>     drop], [1], [], [dnl
>>     -ovn-nbctl: pg1: port group name not found
>>     -])
>>     -
>>     -dnl Test when same name exists in logical switches and portgroups
>>     -AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [],
>>     [stderr])
>>     -AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip
>>     drop], [0], [ignore])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100
>>     burst=1000])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0
>>     rate=300 burst=3000])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301
>>     burst=30000])
>>     -
>>     -dnl Add duplicated qos
>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302
>>     burst=30002], [1], [], [stderr])
>>     -AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4
>>     dscp=11 rate=302 burst=30002])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>     -from-lport   600 (tcp) dscp=63
>>     -from-lport   500 (udp) rate=100 burst=1000
>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>     -  to-lport   300 (tcp) dscp=48
>>     -  to-lport   200 (ip) rate=101
>>     -  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
>>     -])
>>     -
>>     -dnl Delete in one direction.
>>     -AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>     -from-lport   600 (tcp) dscp=63
>>     -from-lport   500 (udp) rate=100 burst=1000
>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>     -])
>>     -
>>     -dnl Delete all qos_rules.
>>     -AT_CHECK([ovn-nbctl qos-del ls0])
>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102
>>     rate=301 dscp=19])
>>     -
>>     -dnl Delete a single flow.
>>     -AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>     -from-lport   600 (ip) rate=1000101
>>     -from-lport   200 (ip) rate=301 burst=1000102 dscp=19
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>     rate=100010111111], [1], [],
>>     -[ovn-nbctl: 100010111111: rate must be in the range 1...4294967295
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>     burst=100010111112 rate=100010], [1], [],
>>     -[ovn-nbctl: 100010111112: burst must be in the range 1...4294967295
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], [1], [],
>>     -[ovn-nbctl: -1: dscp must be in the range 0...63
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], 
>> [],
>>     -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=",
>>     and "burst="
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123],
>>     [1], [],
>>     -[ovn-nbctl: Either "rate" and/or "dscp" must be specified
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
>>     -AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
>>     -AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
>>     -AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
>>     -
>>     -dnl Add duplicate meter name
>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [],
>>     [stderr])
>>     -AT_CHECK([grep 'already exists' stderr], [0], [ignore])
>>     -
>>     -dnl Add reserved meter name
>>     -AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [],
>>     [stderr])
>>     -AT_CHECK([grep 'reserved' stderr], [0], [ignore])
>>     -
>>     -dnl Add meter with invalid rates
>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps],
>>     [1], [],
>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>     -])
>>     -
>>     -dnl Add meter with invalid rates
>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], [1], 
>> [],
>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>     -])
>>     -
>>     -dnl Add meter with invalid burst
>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps],
>>     [1], [],
>>     -[ovn-nbctl: unit must be "kbps" or "pktps"
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>     -meter1: bands:
>>     -  drop: 10 kbps
>>     -meter2: bands:
>>     -  drop: 3 kbps, 2 kb burst
>>     -meter3: bands:
>>     -  drop: 100 kbps, 200 kb burst
>>     -meter4: bands:
>>     -  drop: 10 pktps, 30 packet burst
>>     -])
>>     -
>>     -dnl Delete a single meter.
>>     -AT_CHECK([ovn-nbctl meter-del meter2])
>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>     -meter1: bands:
>>     -  drop: 10 kbps
>>     -meter3: bands:
>>     -  drop: 100 kbps, 200 kb burst
>>     -meter4: bands:
>>     -  drop: 10 pktps, 30 packet burst
>>     -])
>>     -
>>     -dnl Delete all meters.
>>     -AT_CHECK([ovn-nbctl meter-del])
>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2],
>>     [1], [],
>>     -[ovn-nbctl: snatt: type must be one of "dnat", "snat" and
>>     "dnat_and_snat".
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2],
>>     [1], [],
>>     -[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], [1], 
>> [],
>>     -[ovn-nbctl: 30.0.0: should be an IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24
>>     <http://30.0.0.2/24> 192.168.1.2], [1], [],
>>     -[ovn-nbctl: 30.0.0.2/24 <http://30.0.0.2/24>: should be an IPv4
>>     address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80
>>     <http://30.0.0.2:80> 192.168.1.2], [1], [],
>>     -[ovn-nbctl: 30.0.0.2:80 <http://30.0.0.2:80>: should be an IPv4
>>     address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a],
>>     [1], [],
>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], [1], 
>> [],
>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80
>>     <http://192.168.1.2:80>], [1], [],
>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>     IPv4 address or network.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a
>>     <http://192.168.1.2/a>], [1], [],
>>     -[ovn-nbctl: 192.168.1.2/a <http://192.168.1.2/a>: should be an
>>     IPv4 address or network.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a],
>>     [1], [],
>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], [1], 
>> [],
>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80
>>     <http://192.168.1.2:80>], [1], [],
>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>     IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24
>>     <http://192.168.1.2/24>], [1], [],
>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>     IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>     192.168.1.2/24 <http://192.168.1.2/24>], [1], [],
>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>     IPv4 address.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>     192.168.1.2 lp0], [1], [],
>>     -[ovn-nbctl: lr-nat-add with logical_port must also specify
>>     external_mac.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
>>     00:00:00:01:02:03], [1], [],
>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>     type is "dnat_and_snat".
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
>>     00:00:00:01:02:03], [1], [],
>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>     type is "dnat_and_snat".
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>     192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
>>     -[ovn-nbctl: lp0: port name not found
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>     192.168.1.2 lp0 00:00:00:01:02], [1], [],
>>     -[ovn-nbctl: invalid mac address 00:00:00:01:02.
>>     -])
>>     -
>>     -dnl Add snat and dnat
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>     <http://192.168.1.0/24>])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>     192.168.1.2])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>     192.168.1.3 lp0 00:00:00:01:02:03])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>        LOGICAL_PORT
>>     -dnat             30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>      00:00:00:01:02:03    lp0
>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>     <http://192.168.1.0/24>], [1], [],
>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>     NAT with this external_ip and logical_ip already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24
>>     <http://192.168.1.10/24>], [1], [],
>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>     NAT with this external_ip and logical_ip already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1
>>     192.168.1.0/24 <http://192.168.1.0/24>])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24
>>     <http://192.168.1.0/24>], [1], [],
>>     -[ovn-nbctl: a NAT with this type (snat) and logical_ip
>>     (192.168.1.0/24 <http://192.168.1.0/24>) already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2],
>>     [1], [],
>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>     with this external_ip and logical_ip already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1
>>     192.168.1.2])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3],
>>     [1], [],
>>     -[ovn-nbctl: a NAT with this type (dnat) and external_ip
>>     (30.0.0.1) already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>     192.168.1.2], [1], [],
>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>     with this external_ip and logical_ip already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>     30.0.0.1 192.168.1.2])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>     192.168.1.3], [1], [],
>>     -[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
>>     (30.0.0.1) already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>     30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>        LOGICAL_PORT
>>     -dnat             30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>      00:00:00:04:05:06    lp0
>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>     30.0.0.2 192.168.1.3])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>        LOGICAL_PORT
>>     -dnat             30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>     -])
>>     -
>>     -dnl Deletes the NATs
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
>>     -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and
>>     external_ip (30.0.0.3)
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
>>     -[ovn-nbctl: no matching NAT with the type (dnat) and external_ip
>>     (30.0.0.2)
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24
>>     <http://192.168.10.0/24>], [1], [],
>>     -[ovn-nbctl: no matching NAT with the type (snat) and logical_ip
>>     (192.168.10.0/24 <http://192.168.10.0/24>)
>>     -])
>>     -AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat
>>     192.168.10.0/24 <http://192.168.10.0/24>])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>        LOGICAL_PORT
>>     -dnat             30.0.0.1           192.168.1.2
>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>        LOGICAL_PORT
>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
>>     -dnl Add two LBs.
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp], [1], [],
>>     -[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP
>>     address and a port number with : as a separator).
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp], [1], [],
>>     -[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP
>>     address and a port number with : as a separator).
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80
>>     <http://30.0.0.10:80> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20 tcp], [1], [],
>>     -[ovn-nbctl: 192.168.10.20 <http://192.168.10.20>: should be an IP
>>     address and a port number with : as a separator.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>], [1], [],
>>     -[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address
>>     and a port number with : as a separator).
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>], [1], [],
>>     -[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and
>>     a port number with : as a separator).
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>     192.168.10.10,192.168.10.20:80 <http://192.168.10.20:80>], [1], [],
>>     -[ovn-nbctl: 192.168.10.20:80 <http://192.168.10.20:80>: should be
>>     an IP address.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>     192.168.10.10:a80], [1], [],
>>     -[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>     192.168.10.10:], [1], [],
>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>:: should be an
>>     IP address.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>     192.168.10.1a], [1], [],
>>     -[ovn-nbctl: 192.168.10.1a: should be an IP address.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 <http://30.0.0.10>:
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp], [1], [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], [1], 
>> [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900
>>     <http://192.168.10.10:900> tcp], [1], [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -dnl Add ips to lb
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,,])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,192.168.10.20:80
>>     <http://192.168.10.20:80>,,,,])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>
>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -])
>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -])
>>     -
>>     -dnl Update the VIP of the lb1.
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>     <http://30.0.0.10:80> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>     <http://30.0.0.10:80> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080> udp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     -])
>>     -
>>     -dnl Config lb1 with another VIP.
>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 <http://30.0.0.20:80>
>>     192.168.10.10:80 <http://192.168.10.10:80> udp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     - udp 30.0.0.20:80 <http://30.0.0.20:80> 192.168.10.10:80
>>     <http://192.168.10.10:80>
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80 <http://30.0.0.20:80>])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     -])
>>     -
>>     -dnl Add LBs whose vip is just an IP address.
>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     -<2>    lb2                 tcp/udp    30.0.0.30  192.168.10.10
>>     -<3>    lb3                 tcp/udp    30.0.0.30  192.168.10.10
>>     -])
>>     -AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
>>     -AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp])
>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>            IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>     <http://192.168.10.20:8080>
>>     -<2>    lb2                 tcp 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>>     -<3>    lb2                 tcp 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>>     -])
>>     -
>>     -dnl If there are multiple load balancers with the same name, use
>>     a UUID to update/delete.
>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> tcp], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>     <http://30.0.0.10:80> 192.168.10.10:8080
>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>     <http://192.168.10.20:8080> udp])
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:8080
>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>     <http://192.168.10.20:8080> udp])
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090
>>     <http://30.0.0.10:9090> 192.168.10.10:8080
>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>     <http://192.168.10.20:8080> udp])
>>     -AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80 <http://30.0.0.10:80>])
>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>            IPs
>>     -<0>    lb2                 tcp 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>>     -<1>    lb2                 tcp 30.0.0.10:8080
>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>     <http://192.168.10.10:80>,192.168.10.20:80 <http://192.168.10.20:80>
>>     -])
>>     -
>>     -dnl Add load balancer to logical switch.
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80> udp])
>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10
>>     192.168.10.10,192.168.10.20])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>      192.168.10.10,192.168.10.20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>      192.168.10.10,192.168.10.20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>     -
>>     -dnl Remove all load balancers from logical switch.
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>     -
>>     -dnl Add load balancer to logical router.
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>      192.168.10.10,192.168.10.20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>          IPs
>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>     <http://192.168.10.20:80>
>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>      192.168.10.10,192.168.10.20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>     -
>>     -dnl Remove all load balancers from logical router.
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>     -
>>     -dnl Remove load balancers after adding them to a logical
>>     router/switch.
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
>>     -dnl A bunch of commands that should fail
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>     -[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP
>>     address and a port number with : as a separator).
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>     -[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP
>>     address and a port number with : as a separator).
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>     -[ovn-nbctl: fd0f::20: should be an IP address and a port number
>>     with : as a separator.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff
>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>     -[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP
>>     address and a port number with : as a separator).
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>     [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
>>     -[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>     fd0f::10,[[fd0f::20]]:80], [1], [],
>>     -[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>     [[fd0f::10]]:a80], [1], [],
>>     -[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>     [[fd0f::10]]:], [1], [],
>>     -[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>     fd0f::1001a], [1], [],
>>     -[ovn-nbctl: fd0f::1001a: should be an IP address.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp],
>>     [1], [],
>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>     family is different from VIP ae0f::10.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>     family is different from VIP ae0f::10.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80
>>     <http://192.168.10.10:80>], [1], [],
>>     -[ovn-nbctl: 192.168.10.10:80 <http://192.168.10.10:80>: IP
>>     address family is different from VIP [[ae0f::10]]:80.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
>>     -[ovn-nbctl: ae0f::10: IP address family is different from VIP
>>     30.0.0.10.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>     [[ae0f::10]]:80], [1], [],
>>     -[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from
>>     VIP 30.0.0.10:80 <http://30.0.0.10:80>.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
>>     -AT_CHECK([ovn-nbctl lb-add lb0
>>     ae0f:0000:0000:0000:0000:0000:0000:0010 fd0f::20],
>>     -[1], [], [ovn-nbctl: lb0: a load balancer with this vip
>>     (ae0f::10) already exists
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>     -
>>     -dnl Add ips to lb
>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>     ,,,[[fd0f::10]]:80,,,,,])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>     ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80    [[fd0f::10]]:80
>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -])
>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>     -
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -])
>>     -
>>     -dnl Update the VIP of the lb1.
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     -])
>>     -
>>     -dnl Config lb1 with another VIP.
>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 udp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     - udp        [[ae0f::20]]:80    [[fd0f::10]]:80
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     -])
>>     -
>>     -dnl Add LBs whose vip is just an IP address.
>>     -AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     -<2>    lb2                 tcp/udp    ae0f::30  fd0f::10
>>     -<3>    lb3                 tcp/udp    ae0f::30  fd0f::10
>>     -])
>>     -AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
>>     -AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>             IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>     -<2>    lb2                 tcp [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<3>    lb2                 tcp [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -])
>>     -
>>     -dnl If there are multiple load balancers with the same name, use
>>     a UUID to update/delete.
>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080
>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090
>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>     -AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>             IPs
>>     -<0>    lb2                 tcp [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb2                 tcp [[ae0f::10]]:8080
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -])
>>     -
>>     -dnl Add load balancer to logical switch.
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>     -
>>     -dnl Remove all load balancers from logical switch.
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>     -
>>     -dnl Add load balancer to logical router.
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>     -UUID                                    LB PROTO      VIP
>>           IPs
>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>     -
>>     -dnl Remove all load balancers from logical router.
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router
>>     commands], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>     -<0> (lr0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>     -<0> (lr0)
>>     -<1> (lr1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>     -<0> (lr1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl show lr0])
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>     -  [router <0> (lr0)
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
>>     -  [ovn-nbctl: lr0: a router with this name already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>     -  [router <0> (lr0)
>>     -])
>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], [1], 
>> [],
>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>     together
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
>>     -  [ovn-nbctl: Multiple logical routers named 'lr0'.  Use a UUID.
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
>>     -  [ovn-nbctl: lr2: router name not found
>>     -])
>>     -AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-add])
>>     -AT_CHECK([ovn-nbctl lr-add])
>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port
>>     commands], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02
>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
>>     -])
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04
>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>     -
>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
>>     -router <0> (lr0)
>>     -    port lrp0
>>     -        mac: "00:00:00:01:02:03"
>>     -        networks: [["192.168.1.1/24 <http://192.168.1.1/24>"]]
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp0: a port with this name already exists
>>     -])
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>])
>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>     -<0> (lrp0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24> peer=lrp1-peer])
>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>     -<0> (lrp0)
>>     -<1> (lrp1)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp1: a port with this name already exists
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp1: port already exists but in router lr0
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:04:05:06 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp1: port already exists with mac 00:00:00:01:02:03
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>     -  [ovn-nbctl: lrp1: port already exists with mismatching peer
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24>
>>     peer=lrp1-peer], [1], [],
>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>     peer=lrp1-peer])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-del lrp1])
>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>     -<0> (lrp0)
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>     10.0.0.1/24 <http://10.0.0.1/24> peer=lrp1-peer])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>     172.16.0.1/24 <http://172.16.0.1/24> peer=lrp1-peer], [1], [],
>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24> 192.168.1.1/24
>>     <http://192.168.1.1/24> peer=lrp1-peer])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port
>>     gateway chassis], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], [],
>>     -[ovn-nbctl: lp0: port name not found
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
>>     -[ovn-nbctl: lp0: port name not found
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], [],
>>     -[ovn-nbctl: lp0: port name not found
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], [1], [],
>>     -[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
>>     -])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis1     0
>>     -])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis1    10
>>     -])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis1    20
>>     -])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis1    20
>>     -lrp0-chassis2     5
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis2     5
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>     -lrp0-chassis2    10
>>     -lrp0-chassis3     5
>>     -lrp0-chassis1     1
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port
>>     enable and disable], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
>>     -  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -
>>     -dnl Check IPv4 routes
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>     192.168.0.1])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24
>>     <http://10.0.1.0/24> 11.0.1.1 lp0])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>     <http://10.0.0.1/24> 11.0.0.2])
>>     -
>>     -dnl Add overlapping route with 10.0.0.1/24 <http://10.0.0.1/24>
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>     <http://10.0.0.111/24> 11.0.0.1], [1], [],
>>     -  [ovn-nbctl: duplicate prefix: 10.0.0.0/24 <http://10.0.0.0/24>
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1],
>>     [1], [],
>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a
>>     <http://10.0.0.111/24a> 11.0.0.1], [1], [],
>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
>>     <http://10.0.0.111/24a>
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>     <http://10.0.0.111/24> 11.0.0.1a], [1], [],
>>     -  [ovn-nbctl: bad next hop argument: 11.0.0.1a
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>     <http://10.0.0.111/24> 11.0.0.1/24 <http://11.0.0.1/24>], [1], [],
>>     -  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
>>     <http://11.0.0.1/24>
>>     -])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>     2001:0db8:0:f103::1/64], [1], [],
>>     -  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>     <http://10.0.0.111/24> 11.0.0.1])
>>     -AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24
>>     <http://9.16.1.0/24> 11.0.0.1])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv4 Routes
>>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip
>>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip 
>> lp0
>>     - 9.16.1.0/24 <http://9.16.1.0/24>                 11.0.0.1 src-ip
>>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>     <http://10.0.0.111/24> 11.0.0.1 lp1])
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv4 Routes
>>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip 
>> lp1
>>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip 
>> lp0
>>     - 9.16.1.0/24 <http://9.16.1.0/24>                 11.0.0.1 src-ip
>>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>>     -])
>>     -
>>     -dnl Delete non-existent prefix
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24
>>     <http://10.0.2.1/24>], [1], [],
>>     -  [ovn-nbctl: no matching prefix: 10.0.2.0/24 <http://10.0.2.0/24>
>>     -])
>>     -AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24
>>     <http://10.0.2.1/24>])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24
>>     <http://10.0.1.1/24>])
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24
>>     <http://9.16.1.0/24>])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv4 Routes
>>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip 
>> lp1
>>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -])
>>     -
>>     -dnl Check IPv6 routes
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>     2001:0db8:0:f101::1])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>     2001:0db8:0:f102::1 lp0])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>     2001:0db8:0:f103::1])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv6 Routes
>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv6 Routes
>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -])
>>     -
>>     -dnl Check IPv4 and IPv6 routes
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>     192.168.0.1])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24
>>     <http://10.0.1.1/24> 11.0.1.1 lp0])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>     <http://10.0.0.1/24> 11.0.0.1])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>     2001:0db8:0:f101::1])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>     2001:0db8:0:f102::1 lp0])
>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>     2001:0db8:0:f103::1])
>>     -
>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>     -IPv4 Routes
>>     - 10.0.0.0/24 <http://10.0.0.0/24>                 11.0.0.1 dst-ip
>>     - 10.0.1.0/24 <http://10.0.1.0/24>                 11.0.1.1 dst-ip 
>> lp0
>>     - 0.0.0.0/0 <http://0.0.0.0/0>              192.168.0.1 dst-ip
>>     -
>>     -IPv6 Routes
>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>     -
>>     -dnl Add policies with allow and drop actions
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>     <http://1.1.1.0/24>" drop])
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24
>>     <http://1.1.2.0/24>" allow])
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24
>>     <http://2.1.1.0/24>" allow])
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24
>>     <http://2.1.2.0/24>" drop])
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64"
>>     drop])
>>     -
>>     -dnl Add duplicated policy
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>     <http://1.1.1.0/24>" drop], [1], [],
>>     -  [ovn-nbctl: Same routing policy already existed on the logical
>>     router lr0.
>>     -])
>>     -
>>     -dnl Add duplicated policy
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24
>>     <http://1.1.1.0/24>" deny], [1], [],
>>     -  [ovn-nbctl: deny: action must be one of "allow", "drop", and
>>     "reroute"
>>     -])
>>     -
>>     -dnl Delete by priority and match string
>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24
>>     <http://1.1.1.0/24>"])
>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>     -Routing Policies
>>     -       101                              ip4.src == 2.1.1.0/24
>>     <http://2.1.1.0/24>           allow
>>     -       101                              ip4.src == 2.1.2.0/24
>>     <http://2.1.2.0/24>            drop
>>     -       101                               ip6.src == 2002::/64
>>             drop
>>     -       100                              ip4.src == 1.1.2.0/24
>>     <http://1.1.2.0/24>           allow
>>     -])
>>     -
>>     -dnl Delete all policies for given priority
>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>     -Routing Policies
>>     -       100                              ip4.src == 1.1.2.0/24
>>     <http://1.1.2.0/24>           allow
>>     -])
>>     -
>>     -dnl Add policy with reroute action
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24
>>     <http://3.1.2.0/24>" reroute 3.3.3.3])
>>     -
>>     -dnl Add policy with invalid reroute ip
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24
>>     <http://3.1.2.0/24>" reroute 3.3.3.x], [1], [],
>>     -  [ovn-nbctl: bad next hop argument: 3.3.3.x
>>     -])
>>     -
>>     -dnl Add policy with reroute action
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64"
>>     reroute 2002::5])
>>     -
>>     -dnl Add policy with invalid reroute ip
>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64"
>>     reroute 2002::x], [1], [],
>>     -  [ovn-nbctl: bad next hop argument: 2002::x
>>     -])
>>     -
>>     -])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>     -
>>     -dnl switchport type defaults to empty
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -
>>     -])
>>     -
>>     -dnl The following are the valid entries for
>>     -dnl switchport type
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -l2gateway
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -router
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -localnet
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -localport
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -vtep
>>     -])
>>     -
>>     -dnl All of these are valid southbound port types but
>>     -dnl should be rejected for northbound logical switch
>>     -dnl ports.
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
>>     -ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized.
>>     Not setting type.
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
>>     -ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not
>>     setting type.
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], [], [dnl
>>     -ovn-nbctl: Logical switch port type 'chassisredirect' is
>>     unrecognized. Not setting type.
>>     -])
>>     -
>>     -dnl switch port type should still be "vtep" since previous
>>     -dnl commands failed.
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -vtep
>>     -])
>>     -
>>     -dnl Attempt a nonsense type
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
>>     -ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not
>>     setting type.
>>     -])
>>     -
>>     -dnl Empty string should work too
>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>     -
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
>>     -AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection
>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
>>     -AT_CHECK([ovn-nbctl list connection | grep inactivity_probe],
>>     [0], [dnl
>>     -inactivity_probe    : 30000
>>     -inactivity_probe    : 30000
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
>>     -dnl Check that dry run has no permanent effect.
>>     -AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt],
>>     [0], [dnl
>>     -<0> (ls0)
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>     -])
>>     -
>>     -dnl Check that dry-run mode is not sticky.
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>     -<0> (ls0)
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
>>     -AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
>>     -
>>     -dnl Expect one line for one command.
>>     -AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
>>     -<0> (ls0)\n<1> (ls1)
>>     -])
>>     -
>>     -dnl Expect lines for two commands.
>>     -AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt],
>>     [0], [dnl
>>     -<0> (ls0)\n<1> (ls1)
>>     -<0> (ls0)\n<1> (ls1)
>>     -])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error
>>     paths], [
>>     -dnl FIXME: Duplicate options are allowed when passed with global
>>     options.
>>     -dnl        For example: ovn-nbctl --if-exists --if-exists list
>>     Logical_Switch
>>     -
>>     -dnl Duplicate option
>>     -AT_CHECK([ovn-nbctl -- --if-exists --if-exists list
>>     Logical_Switch], [1], [], [stderr])
>>     -AT_CHECK([grep 'option specified multiple times' stderr], [0],
>>     [ignore])
>>     -
>>     -dnl Missing command
>>     -AT_CHECK([ovn-nbctl], [1], [], [stderr])
>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl --], [1], [], [stderr])
>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>     -
>>     -dnl Unknown command
>>     -AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>     -
>>     -dnl Unknown option
>>     -AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], [stderr])
>>     -AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], 
>> [stderr])
>>     -AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
>>     -
>>     -dnl Missing option argument
>>     -AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
>>     -AT_CHECK([grep 'option .* requires an argument' stderr], [0],
>>     [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [],
>>     [stderr])
>>     -AT_CHECK([grep 'missing argument to .* option' stderr], [0],
>>     [ignore])
>>     -
>>     -dnl Unexpected option argument
>>     -AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1],
>>     [], [stderr])
>>     -AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .*
>>     requires an argument' stderr], [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1],
>>     [], [stderr])
>>     -AT_CHECK([grep 'option on .* does not accept an argument'
>>     stderr], [0], [ignore])
>>     -
>>     -dnl Not enough arguments
>>     -AT_CHECK([ovn-nbctl list], [1], [], [stderr])
>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>     [0], [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>     [0], [ignore])
>>     -
>>     -dnl Too many arguments
>>     -AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>     [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>     [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>     [ignore])
>>     -
>>     -AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>     [ignore])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
>>     -dnl Check that port group can be looked up by name
>>     -AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
>>     -pg0
>>     -])])
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
>>     -dnl This test addresses a specific issue seen when running
>>     ovn-nbctl in
>>     -dnl daemon mode. All we have to do is ensure that each time we
>>     list database
>>     -dnl information, there is not an extra newline at the beginning
>>     of the output.
>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>     [dnl
>>     -name                : sw1
>>     -])
>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>     [dnl
>>     -name                : sw1
>>     -])])
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
>>     -dnl This test addresses a specific issue seen when running
>>     ovn-nbctl in
>>     -dnl daemon mode. We need to ensure that table formatting options
>>     are honored
>>     -dnl when listing database information.
>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch
>>     sw1], [0], [dnl
>>     -sw1
>>     -])])
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group
>>     commands], [
>>     -AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],
>>     -[pg1
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
>>     -SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>     sw1-p1)
>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
>>     -SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>     sw1-p2)
>>     -
>>     -AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1],
>>     [0],[dnl
>>     -pg1
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>     port_group pg1], [0], [dnl
>>     -$SW1P1
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>     port_group pg1], [0], [dnl
>>     -$SW1P2
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>     -])
>>     -
>>     -AT_SETUP([ovn-nbctl - daemon retry connection])
>>     -OVN_NBCTL_TEST_START daemon
>>     -AT_CHECK([kill `cat ovsdb-server.pid`])
>>     -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>     [stderr])
>>     -AT_CHECK([ovn-nbctl show], [0], [ignore])
>>     -OVN_NBCTL_TEST_STOP /Terminated/d
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn-northd.at <http://ovn-northd.at>
>>     b/tests/ovn-northd.at <http://ovn-northd.at>
>>     deleted file mode 100644
>>     index 62e58fd..0000000
>>     --- a/tests/ovn-northd.at <http://ovn-northd.at>
>>     +++ /dev/null
>>     @@ -1,900 +0,0 @@
>>     -AT_BANNER([OVN northd])
>>     -AT_SETUP([ovn -- check   from NBDB to SBDB])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>     -
>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl --wait=sb \
>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>     -                                     chassis_name=gw1 \
>>     -                                     priority=20 -- \
>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>     -                                     chassis_name=gw2 \
>>     -                                     priority=10 -- \
>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find
>>     Gateway_Chassis name="alice_gw1"`
>>     -
>>     -# With the new ha_chassis_group table added, there should be no
>>     rows in
>>     -# gateway_chassis table in SB DB.
>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -# There should be one ha_chassis_group with the name "alice"
>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="alice"`
>>     -
>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>     -
>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>     ha_chassis_group name=alice`
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>     port_binding \
>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>     -])
>>     -
>>     -# There should be one ha_chassis_group with the name "alice"
>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="alice"`
>>     -
>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>     -
>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>     ha_chassis_group name=alice`
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>     port_binding \
>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>     -])
>>     -
>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>>     -# Trim the spaces.
>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>     -
>>     -ha_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list="$ha_ch_list $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>     -
>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>     -
>>     -# Delete chassis - gw2 in SB DB.
>>     -# ovn-northd should not recreate ha_chassis rows
>>     -# repeatedly when gw2 is deleted.
>>     -ovn-sbctl chassis-del gw2
>>     -
>>     -ha_ch_list_1=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>     -
>>     -ha_ch_list_2=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>     -
>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>     -
>>     -# Add back the gw2 chassis
>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>     -
>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>     -gw_ch=`ovn-sbctl --bare --columns gateway_chassis find 
>> port_binding \
>>     -logical_port="cr-alice"`
>>     -AT_CHECK([test "$gw_ch" = ""])
>>     -
>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>     -# Trim the spaces.
>>     -echo "ha ch in grp = $ha_ch"
>>     -
>>     -ha_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list="$ha_ch_list $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>     -
>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>     -
>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>     -ovn-nbctl --wait=sb set Logical_Router_Port alice
>>     gateway_chassis=${nb_gwc1_uuid}
>>     -
>>     -# There should be only 1 row in ha_chassis SB DB table.
>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>     -l], [0], [1
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -# There should be only 1 row in ha_chassis SB DB table.
>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>     -l], [0], [1
>>     -])
>>     -
>>     -# delete all the gateway_chassis on NBDB for alice port
>>     -
>>     -ovn-nbctl --wait=sb clear Logical_Router_Port alice gateway_chassis
>>     -
>>     -# expect that the ha_chassis doesn't exist anymore
>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>     -])
>>     -
>>     -# expect that the ha_chassis doesn't exist anymore
>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to
>>     SBDB backwards compatibility])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>     -
>>     -ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03
>>     172.16.1.1/24 <http://172.16.1.1/24> \
>>     -    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
>>     -
>>     -
>>     -# It should be converted to ha_chassis_group entries in SBDB, and
>>     -# still redirect-chassis is kept for backwards compatibility
>>     -
>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>     -l], [0], [1
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group
>>     | wc -l], [0], [1
>>     -])
>>     -
>>     -# There should be one ha_chassis_group with the name "bob_gw1"
>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="bob_gw1"`
>>     -
>>     -AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
>>     -
>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>     ha_chassis_group name=bob_gw1`
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>     port_binding \
>>     -logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb remove Logical_Router_Port bob options
>>     redirect-chassis
>>     -
>>     -# expect that the ha_chassis/ha_chassis_group doesn't exist anymore
>>     -
>>     -AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check up state of VIF LSP])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add S1
>>     -ovn-nbctl --wait=sb lsp-add S1 S1-vm1
>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
>>     -
>>     -ovn-sbctl chassis-add hv1 geneve 127.0.0.1
>>     -ovn-sbctl lsp-bind S1-vm1 hv1
>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check up state of router LSP linked to a
>>     distributed LR])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl ls-add S1
>>     -ovn-nbctl lsp-add S1 S1-R1
>>     -ovn-nbctl lsp-set-type S1-R1 router
>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check up state of router LSP linked to a gateway
>>     LR])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>     -
>>     -ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl ls-add S1
>>     -ovn-nbctl lsp-add S1 S1-R1
>>     -ovn-nbctl lsp-set-type S1-R1 router
>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>     -
>>     -ovn-sbctl lsp-bind S1-R1 gw1
>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check up state of router LSP linked to an LRP
>>     with set Gateway Chassis])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
>>     -
>>     -ovn-nbctl ls-add S1
>>     -ovn-nbctl lsp-add S1 S1-R1
>>     -ovn-nbctl lsp-set-type S1-R1 router
>>     -ovn-nbctl lsp-set-addresses S1-R1 router
>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
>>     -ovn_start
>>     -
>>     -ovn-nbctl lr-add ro
>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>>     -ovn-nbctl ls-add sw
>>     -ovn-nbctl lsp-add sw sw-ro
>>     -ovn-nbctl lsp-set-type sw-ro router
>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:send_periodic=true
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:address_mode=slaac
>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:mtu=1280
>>     -
>>     -uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding
>>     logical_port=ro-sw)
>>     -
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_send_periodic],
>>     -[0], ["true"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_address_mode],
>>     -[0], [slaac
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[0], ["600"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[0], ["200"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
>>     -[0], ["1280"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_src_eth],
>>     -[0], ["00:00:00:00:00:01"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_src_addr],
>>     -[0], ["fe80::200:ff:fe00:1"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_prefixes],
>>     -[0], ["aef0::/64"
>>     -])
>>     -
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:max_interval=300
>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:min_interval=600
>>     -
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[0], ["300"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[0], ["225"
>>     -])
>>     -
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:max_interval=300
>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:min_interval=250
>>     -
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[0], ["300"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[0], ["225"
>>     -])
>>     -
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:max_interval=0
>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:min_interval=0
>>     -
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[0], ["4"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[0], ["3"
>>     -])
>>     -
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:max_interval=3600
>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:min_interval=2400
>>     -
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[0], ["1800"
>>     -])
>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[0], ["1350"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb set Logical_Router_port ro-sw
>>     ipv6_ra_configs:send_periodic=false
>>     -
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_send_periodic],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in
>>     Port_Binding record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_max_interval],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in
>>     Port_Binding record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_min_interval],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in
>>     Port_Binding record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_mtu],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record
>>     "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_address_mode],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in
>>     Port_Binding record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_src_eth],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding
>>     record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_src_addr],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding
>>     record "${uuid}" column options
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>     options:ipv6_ra_prefixes],
>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding
>>     record "${uuid}" column options
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- test unixctl])
>>     -ovn_init_db ovn-sb; ovn-sbctl init
>>     -ovn_init_db ovn-nb; ovn-nbctl init
>>     -
>>     -# test unixctl option
>>     -mkdir "$ovs_base"/northd
>>     -as northd start_daemon ovn-northd
>>     --unixctl="$ovs_base"/northd/ovn-northd.ctl
>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -ovn-nbctl ls-add sw
>>     -ovn-nbctl --wait=sb lsp-add sw p1
>>     -# northd created with unixctl option successfully created
>>     port_binding entry
>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>     logical_port="p1" | wc -l], [0], [1
>>     -])
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
>>     -
>>     -# ovs-appctl exit with unixctl option
>>     -OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl],
>>     ["$ovs_base"/northd/ovn-northd.pid])
>>     -
>>     -# Check no port_binding entry for new port as ovn-northd is not
>>     running
>>     -ovn-nbctl lsp-add sw p2
>>     -ovn-nbctl --timeout=10 --wait=sb sync
>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>     logical_port="p2" | wc -l], [0], [0
>>     -])
>>     -
>>     -# test default unixctl path
>>     -as northd start_daemon ovn-northd
>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -ovn-nbctl --wait=sb lsp-add sw p3
>>     -# northd created with default unixctl path successfully created
>>     port_binding entry
>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>     logical_port="p3" | wc -l], [0], [1
>>     -])
>>     -
>>     -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])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to
>>     SBDB])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>     -
>>     -# ovn-northd should not create HA chassis group and HA chassis rows
>>     -# unless the HA chassis group in OVN NB DB is associated to
>>     -# a logical router port or logical port of type external.
>>     -AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group
>>     name="hagrp1" \
>>     -| wc -l], [0], [0
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>     -
>>     -# There should be no HA_Chassis rows in SB DB.
>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>     $3}' \
>>     -| grep -v '-' | wc -l ], [0], [0
>>     -])
>>     -
>>     -# Add chassis ch1.
>>     -ovn-sbctl chassis-add ch1 geneve 127.0.0.2
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc
>>     -l`])
>>     -
>>     -# There should be no HA_Chassis rows
>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>     $3}' \
>>     -| grep -v '-' | wc -l ], [0], [0
>>     -])
>>     -
>>     -# Create a logical router port and attach ha chassis group.
>>     -ovn-nbctl lr-add lr0
>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13
>>     172.168.0.100/24 <http://172.168.0.100/24>
>>     -
>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>     ha_chassis_group name=hagrp1`
>>     -ovn-nbctl set logical_router_port lr0-public
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Make sure that ovn-northd doesn't recreate the ha_chassis
>>     -# records if the chassis record is missing in SB DB.
>>     -
>>     -ha_ch_list_1=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>     -
>>     -ha_ch_list_2=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>     -
>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>     -
>>     -# 2 HA chassis should be created with 'chassis' column empty because
>>     -# we have not added hv1 and hv2 chassis to the SB DB.
>>     -AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis |
>>     awk '{print $3}' \
>>     -| grep -v '-' | wc -l`])
>>     -
>>     -# We should have 1 ha chassis with 'chassis' column set for hv1
>>     -AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | awk '{print $3}' \
>>     -| grep '-' | wc -l`])
>>     -
>>     -# Create another logical router port and associate to the same
>>     ha_chasis_group
>>     -ovn-nbctl lr-add lr1
>>     -ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14
>>     182.168.0.100/24 <http://182.168.0.100/24>
>>     -
>>     -ovn-nbctl set logical_router_port lr1-public
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -# We should still have 1 HA chassis group and 3 HA chassis in SB DB.
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Change the priority of ch1 - ha chassis in NB DB. It should get
>>     -# reflected in SB DB.
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority find \
>>     -ha_chassis | grep 100 | wc -l`])
>>     -
>>     -# Delete ch1 HA chassis in NB DB.
>>     -ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
>>     -
>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>     chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Add back the ha chassis
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
>>     -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep
>>     chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Delete lr0-public. We should still have 1 HA chassis group and
>>     -# 3 HA chassis in SB DB.
>>     -ovn-nbctl --wait=sb lrp-del lr0-public
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Delete lr1-public. There should be no HA chassis group in SB DB.
>>     -ovn-nbctl --wait=sb lrp-del lr1-public
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>     -l`])
>>     -
>>     -# Add lr0-public again
>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> set
>>     logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Create a Gateway chassis. ovn-northd should ignore this.
>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
>>     -
>>     -# There should be only 1 HA chassis group in SB DB with the
>>     -# name hagrp1.
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Now delete HA chassis group. ovn-northd should create HA
>>     chassis group
>>     -# with the Gateway chassis name
>>     -ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
>>     -ovn-nbctl ha-chassis-group-del hagrp1
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>     -find ha_chassis | wc -l`])
>>     -
>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>     -
>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>     chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Test if 'ref_chassis' column is properly set or not in
>>     -# SB DB ha_chassis_group.
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>     -
>>     -ovn-sbctl chassis-add ch2 geneve 127.0.0.3
>>     -ovn-sbctl chassis-add ch3 geneve 127.0.0.4
>>     -ovn-sbctl chassis-add comp1 geneve 127.0.0.5
>>     -ovn-sbctl chassis-add comp2 geneve 127.0.0.6
>>     -
>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
>>     <http://10.0.0.1/24>
>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>     -
>>     -ovn-sbctl lsp-bind sw0-p1 comp1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
>>     -
>>     -comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="comp1"`
>>     -comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="comp2"`
>>     -ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="comp1"`
>>     -
>>     -echo "comp1_ch_uuid = $comp1_ch_uuid"
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp1_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# unbind sw0-p1
>>     -ovn-sbctl lsp-unbind sw0-p1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "" = "$ref_ch_list"])
>>     -
>>     -# Bind sw0-p1 in comp2
>>     -ovn-sbctl lsp-bind sw0-p1 comp2
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>     -ovn-nbctl lr-add lr1
>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add sw1 sw1-lr1
>>     -ovn-nbctl lsp-set-type sw1-lr1 router
>>     -ovn-nbctl lsp-set-addresses sw1-lr1 router
>>     -ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
>>     -
>>     -# Bind sw1-p1 in comp1.
>>     -ovn-sbctl lsp-bind sw1-p1 comp1
>>     -# Wait until sw1-p1 is up
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
>>     -
>>     -# sw1-p1 is not connected to lr0. So comp1 should not be in
>>     'ref_chassis'
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Now attach sw0 to lr1
>>     -ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
>>     <http://10.0.0.10/24>
>>     -ovn-nbctl lsp-add sw0 sw0-lr1
>>     -ovn-nbctl lsp-set-type sw0-lr1 router
>>     -ovn-nbctl lsp-set-addresses sw0-lr1 router
>>     -ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
>>     -
>>     -# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is
>>     indirectly
>>     -# connected to lr0
>>     -exp_ref_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>     -do
>>     -    if test $i = $comp1_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    elif test $i = $comp2_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    fi
>>     -done
>>     -
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# Unind sw1-p1. comp2 should not be in the ref_chassis.
>>     -ovn-sbctl lsp-unbind sw1-p1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Create sw2 and attach it to lr2
>>     -ovn-nbctl ls-add sw2
>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>     -ovn-nbctl lr-add lr2
>>     -ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
>>     <http://30.0.0.1/24>
>>     -ovn-nbctl lsp-add sw2 sw2-lr2
>>     -ovn-nbctl lsp-set-type sw2-lr2 router
>>     -ovn-nbctl lsp-set-addresses sw2-lr2 router
>>     -ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
>>     -
>>     -# Bind sw2-p1 to comp1
>>     -ovn-sbctl lsp-bind sw2-p1 comp1
>>     -# Wait until sw2-p1 is up
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
>>     -
>>     -# sw2-p1 is not connected to lr0. So comp1 should not be in
>>     'ref_chassis'
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected
>>     to lr0.
>>     -ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
>>     <http://20.0.0.10/24>
>>     -ovn-nbctl lsp-add sw1 sw1-lr2
>>     -ovn-nbctl lsp-set-type sw1-lr2 router
>>     -ovn-nbctl lsp-set-addresses sw1-lr2 router
>>     -ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
>>     -
>>     -# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2)
>>     should be in
>>     -# 'ref_chassis'
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# Create sw0-p2 and bind it to comp1
>>     -ovn-nbctl lsp-add sw0 sw0-p2
>>     -ovn-sbctl lsp-bind sw0-p2 comp1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# unbind sw0-p2
>>     -ovn-sbctl lsp-unbind sw0-p2
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# Delete lr1-sw0. comp1 should be deleted from ref_chassis as
>>     there is no link
>>     -# from sw1 and sw2 to lr0.
>>     -ovn-nbctl lrp-del lr1-sw0
>>     -
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Set redirect-chassis option to lr0-public. It should be ignored.
>>     -ovn-nbctl set logical_router_port lr0-public
>>     options:redirect-chassis=ch1
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>     -
>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>     chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Delete the gateway chassis. HA chassis group should be created
>>     in SB DB
>>     -# for the redirect-chassis option.
>>     -ovn-nbctl clear logical_router_port lr0-public gateway_chassis
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group | wc -l`])
>>     -
>>     -ovn-sbctl list ha_chassis_group
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="lr0-public_ch1" | wc -l`])
>>     -
>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep chassis |
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Clear the redirect-chassis option.
>>     -ovn-nbctl clear logical_router_port lr0-public options
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>> -l`])
>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>     -
>>     -# Delete old sw0.
>>     -ovn-nbctl ls-del sw0
>>     -
>>     -# Create external logical ports and associate ha_chassis_group
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl lsp-add sw0 sw0-pext1
>>     -ovn-nbctl lsp-add sw0 sw0-pext2
>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>     -
>>     -ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 10.0.0.3"
>>     -ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 10.0.0.4"
>>     -ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
>>     -
>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>     -
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>     -
>>     -# ovn-northd should not create HA chassis group and HA chassis rows
>>     -# unless the HA chassis group in OVN NB DB is associated to
>>     -# a logical router port or logical port of type external.
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>> -l`])
>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>     -
>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find 
>> ha_chassis_group \
>>     -name=hagrp1`
>>     -
>>     -# The type of the lsp - sw0-pext1 is still not set to external.
>>     -# So ha_chassis_group should be ignored.
>>     -ovn-nbctl set logical_switch_port sw0-pext1
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>     -l`])
>>     -
>>     -# Set the type of sw0-pext1 to external
>>     -ovn-nbctl lsp-set-type sw0-pext1 external
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>     ha_chassis_group \
>>     -name=hagrp1`
>>     -
>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>     -
>>     -# Set the type of sw0-pext2 to external and associate
>>     ha_chassis_group
>>     -ovn-nbctl lsp-set-type sw0-pext2 external
>>     -ovn-nbctl set logical_switch_port sw0-pext2
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
>>     -grep -v chassis-name | wc -l`])
>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>     -
>>     -OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare
>>     --columns \
>>     -ha_chassis_group find port_binding logical_port=sw0-pext2`])
>>     -
>>     -# sw0-p1 is a normal port. So ha_chassis_group should not be set
>>     -# in port_binding.
>>     -ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
>>     -ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding \
>>     -logical_port=sw0-p1) = x], [0], [])
>>     -
>>     -# Clear ha_chassis_group for sw0-pext1
>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1
>>     ha_chassis_group
>>     -
>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding \
>>     -logical_port=sw0-pext1) = x], [0], [])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>     -
>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -# Clear ha_chassis_group for sw0-pext2
>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2
>>     ha_chassis_group
>>     -
>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding \
>>     -logical_port=sw0-pext2) = x], [0], [])
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>> -l`])
>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>     -
>>     -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])
>>     -
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn-performance.at <http://ovn-performance.at>
>>     b/tests/ovn-performance.at <http://ovn-performance.at>
>>     deleted file mode 100644
>>     index a8a15f8..0000000
>>     --- a/tests/ovn-performance.at <http://ovn-performance.at>
>>     +++ /dev/null
>>     @@ -1,424 +0,0 @@
>>     -#
>>     -# Tests targeting performance of OVN components.
>>     -#
>>     -
>>     -m4_divert_push([PREPARE_TESTS])
>>     -
>>     -# vec_cmp VALUE_VEC OP-VALUE_VEC
>>     -#
>>     -# Compares each value from VALUE_VEC to the operator-value pair
>>     from the
>>     -# OP-VALUE_VEC.
>>     -#
>>     -# VALUE_VEC must be a list of values separated by a character
>>     from $IFS.
>>     -# OP-VALUE_VEC must be a list of operator-value expressions
>>     separated by a
>>     -# character from $IFS.  Operator-value expressions cannot contain
>>     any characters
>>     -# from $IFS like spaces. '=' is treated as an equality operator
>>     ('==') for
>>     -# conciseness.
>>     -#
>>     -# Returns the result of each comparison as a list of boolean
>>     values (0 or 1)
>>     -# separated by a new-line character.
>>     -vec_cmp() {
>>     -    local a b i j
>>     -
>>     -    i=0
>>     -    for a in $1; do
>>     -        j=0
>>     -        for b in $2; do
>>     -            if test $i -eq $j; then
>>     -                # Replace assignment '=' with equality comparison
>>     '=='
>>     -                case "$b" in
>>     -                =[[0-9]]*) b="=$b" ;;
>>     -                esac
>>     -
>>     -                echo $(($a $b))
>>     -                break
>>     -            fi
>>     -            j=$((j + 1))
>>     -        done
>>     -        i=$((i + 1))
>>     -    done
>>     -}
>>     -
>>     -# vec_sub VEC_A VEC_B
>>     -#
>>     -# Subtracts two vectors:
>>     -#
>>     -#     VEC_A = [a1, a2, ...]
>>     -#     VEC_B = [b1, b2, ...]
>>     -#     OUT = [(a1 - b1), (a2 - b2), ...]
>>     -#
>>     -# VEC_A and VEC_B must be lists of values separated by a
>>     character from $IFS.
>>     -vec_sub() {
>>     -    local a b i j
>>     -
>>     -    i=0
>>     -    for a in $1; do
>>     -        j=0
>>     -        for b in $2; do
>>     -            if test $i -eq $j; then
>>     -                echo $((a - b))
>>     -                break
>>     -            fi
>>     -            j=$((j + 1))
>>     -        done
>>     -        i=$((i + 1))
>>     -    done
>>     -}
>>     -
>>     -# vec_fold VEC OP
>>     -#
>>     -# Reduces a vector to a single value by applying the binary
>>     operator OP (i.e.,
>>     -# one that requires two arguments) cumulatively to all vector
>>     elements from left
>>     -# to right:
>>     -#
>>     -#     VEC = [e1, e2, e3 ...]
>>     -#     OUT = (...((e1 OP e2) OP e3) OP ...)
>>     -#
>>     -# VEC must be a list of values separated by a character from $IFS.
>>     -vec_fold() {
>>     -    local first op prod
>>     -
>>     -    first=1
>>     -    op=$2
>>     -    for a in $1; do
>>     -        if test $first -eq 1; then
>>     -            prod=$a
>>     -            first=0
>>     -        else
>>     -            prod=$((prod $op a))
>>     -        fi
>>     -    done
>>     -    echo $prod
>>     -}
>>     -
>>     -# read_counters SANDBOXES TARGET COUNTER
>>     -#
>>     -# Prints out the coverage COUNTER for the TARGET in each of the
>>     SANDBOXES.
>>     -#
>>     -# SANDBOXES must be a list of strings separated by a character
>>     from $IFS.
>>     -read_counters() {
>>     -    local sims="$1" target="$2" counter="$3"
>>     -
>>     -    for sim in $sims; do
>>     -        as $sim ovs-appctl -t "$target" coverage/read-counter
>>     "$counter" || return 1
>>     -    done
>>     -}
>>     -
>>     -# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
>>     -#
>>     -# Runs the COMMAND and reports the COUNTER change registered
>>     during the command
>>     -# run for the given TARGET in each of the SANDBOXES.
>>     -counter_delta_() {
>>     -    local sims="$1" target="$2" counter="$3" cmd="$4"
>>     -    local before after
>>     -
>>     -    before=$(read_counters "$sims" "$target" "$counter") || return 1
>>     -    eval "$cmd" >/dev/null || return 1
>>     -    after=$(read_counters "$sims" "$target" "$counter") || return 1
>>     -
>>     -    vec_sub "$after" "$before"
>>     -}
>>     -
>>     -# counter_delta SANDBOXES TARGET COUNTER COMMAND
>>     -#
>>     -# Same as counter_delta_ but also prints the COUNTER values
>>     together with the
>>     -# COMMAND to standard error.
>>     -counter_delta() {
>>     -    local cmd="$4"
>>     -    local v
>>     -
>>     -    v=$(counter_delta_ "$@") || return 1
>>     -
>>     -    # Dump the counters and the command for troubleshooting
>>     -    echo "$v" | tr '\n' '\t' >&2
>>     -    echo "$cmd" >&2
>>     -
>>     -    echo "$v"
>>     -}
>>     -
>>     -# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
>>     -#
>>     -# Check if COUNTER change in the TARGET app in each of the
>>     SANDBOXES after
>>     -# running the COMMAND meets the conditions listed as
>>     operator-value pairs in
>>     -# CONDS.
>>     -vec_cmp_counter_delta() {
>>     -    local v
>>     -
>>     -    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
>>     -    v=$(vec_cmp "$v" "$4") || return 1
>>     -    v=$(vec_fold "$v" "&&") || return 1
>>     -
>>     -    echo "$v"
>>     -}
>>     -
>>     -# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
>>     -#
>>     -# Check if COUNTER change in the TARGET app in each of the
>>     SANDBOXES after
>>     -# running the COMMAND meets the COND condition given as a
>>     operator-value pair.
>>     -cmp_counter_delta() {
>>     -    local conds=""
>>     -
>>     -    # Use the same condition for each sandbox
>>     -    for _ in $1; do
>>     -        conds="$conds $4"
>>     -    done
>>     -
>>     -    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
>>     -}
>>     -
>>     -m4_divert_pop([PREPARE_TESTS])
>>     -
>>     -# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
>>     -#
>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>     in all of
>>     -# the SANDBOXES did not change.
>>     -m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
>>     -    rc=$?
>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>     -])
>>     -
>>     -# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER COMMAND
>>     -#
>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET in
>>     -# all of the SANDBOXES has changed.
>>     -m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
>>     -    rc=$?
>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>     -])
>>     -
>>     -# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
>>     -#
>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>     in all of the
>>     -# SANDBOXES satisfies the conditions listed in CONDS.
>>     -m4_define([CHECK_COUNTER_DELTA_COND],[
>>     -    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
>>     -    rc=$?
>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>     -])
>>     -
>>     -# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
>>     -#
>>     -# Checks if the COUNTER value has changed for any of the
>>     ovn-controller
>>     -# processes in the SANDBOXES when the COMMAND was run.
>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT],[
>>     -    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2],
>>     [$3])
>>     -])
>>     -
>>     -# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
>>     -#
>>     -# Checks if the COUNTER value has not changed for any of the
>>     ovn-controller
>>     -# processes in the SANDBOXES when the COMMAND was run.
>>     -m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
>>     -    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], [$3])
>>     -])
>>     -
>>     -# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
>>     -#
>>     -# Checks if the change of the COUNTER value, when the COMMAND was
>>     run, of the
>>     -# ovn-controller process in each of the SANDBOXES meets the
>>     conditions in
>>     -# CONDS. CONDS must be a list of operator-value pairs, for
>>     example "[>0 =0]",
>>     -# following the same order as SANDBOXES.
>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
>>     -    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3],
>>     [$4])
>>     -])
>>     -
>>     -AT_SETUP([ovn -- ovn-controller incremental processing])
>>     -# Check which operations the trigger full logical flow processing.
>>     -#
>>     -# Create and destroy logical routers, switches, ports, address
>>     sets and ACLs
>>     -# while counting calls to lflow_run() in ovn-controller.
>>     -
>>     -ovn_start
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -done
>>     -
>>     -# Add router lr1
>>     -OVN_CONTROLLER_EXPECT_HIT(
>>     -    [hv1 hv2], [lflow_run],
>>     -    [ovn-nbctl --wait=hv lr-add lr1]
>>     -)
>>     -
>>     -for i in 1 2; do
>>     -    ls=ls$i
>>     -    lsp=$ls-lr1
>>     -    lrp=lr1-$ls
>>     -
>>     -    # Add switch $ls
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv ls-add $ls]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config
>>     subnet=10.0.$i.0/24]
>>     -    )
>>     -
>>     -    # Add router port to $ls
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01
>>     10.0.$i.1/24]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-set-options $lsp router-port=$lrp]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
>>     -    )
>>     -done
>>     -
>>     -get_lsp_uuid () {
>>     -    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
>>     -}
>>     -
>>     -pg_ports=
>>     -
>>     -for i in 1 2; do
>>     -    j=$((i%2 + 1))
>>     -    as=as$i
>>     -    ls=ls$i
>>     -    lp=lp$i
>>     -    vif=vif$i
>>     -
>>     -    # Add port $lp
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lp]
>>     -    )
>>     -
>>     -    pg_ports="$pg_port `get_lsp_uuid $lp`"
>>     -
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl wait-until Logical_Switch_Port $lp
>>     dynamic_addresses!=[[]] &&
>>     -         ovn-nbctl --wait=hv sync]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl get Logical_Switch_Port $lp dynamic_addresses &&
>>     -         ovn-nbctl --wait=hv sync]
>>     -    )
>>     -
>>     -    # Add address set $as
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv create Address_Set name="$as"]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv add Address_Set "$as" addresses
>>     "10.0.$i.10"]
>>     -    )
>>     -
>>     -    # Add ACLs for port $lp
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport
>>     == \"$lp\" && ip4.src == \$$as' allow]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport
>>     == \"$lp\"' drop]
>>     -    )
>>     -
>>     -    # Bind port $lp and wait for it to come up
>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>     -        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface
>>     $vif external-ids:iface-id=$lp &&
>>     -         ovn-nbctl wait-until Logical_Switch_Port $lp 'up=true' &&
>>     -         ovn-nbctl --wait=hv sync]
>>     -    )
>>     -done
>>     -
>>     -for i in 1 2; do
>>     -    j=$((i%2 + 1))
>>     -    as=as$i
>>     -    ls=ls$i
>>     -    lp=lp$i
>>     -
>>     -    # Delete ACLs for port $lp
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport
>>     == \"$lp\" && ip4.src == \$$as']
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport
>>     == \"$lp\"']
>>     -    )
>>     -
>>     -    # Delete address set $as
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses
>>     "10.0.$i.10"]
>>     -    )
>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
>>     -    )
>>     -done
>>     -
>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -    [hv1 hv2], [lflow_run],
>>     -    [ovn-nbctl --wait=hv create Port_Group name=pg1
>>     ports=\"$pg_ports\"]
>>     -)
>>     -
>>     -# Add ACLs for port group pg1
>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -    [hv1 hv2], [lflow_run],
>>     -    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport ==
>>     @pg1 && ip4.src == $pg1_ip4' allow]
>>     -)
>>     -
>>     -for i in 1 2; do
>>     -    j=$((i%2 + 1))
>>     -    lp=lp$i
>>     -
>>     -    # Delete port $lp
>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>     -        [ovn-nbctl --wait=hv lsp-del $lp]
>>     -    )
>>     -done
>>     -
>>     -# Delete port group pg1
>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>     -    [hv1 hv2], [lflow_run],
>>     -    [ovn-nbctl --wait=hv destroy Port_Group pg1]
>>     -)
>>     -
>>     -for i in 1 2; do
>>     -    ls=ls$i
>>     -
>>     -    # Delete switch $ls
>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>     -        [hv1 hv2], [lflow_run],
>>     -        [ovn-nbctl --wait=hv ls-del $ls]
>>     -    )
>>     -done
>>     -
>>     -# Delete router lr1
>>     -OVN_CONTROLLER_EXPECT_HIT(
>>     -    [hv1 hv2], [lflow_run],
>>     -    [ovn-nbctl --wait=hv lr-del lr1]
>>     -)
>>     -
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>     b/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>     deleted file mode 100644
>>     index 650e357..0000000
>>     --- a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>     +++ /dev/null
>>     @@ -1,150 +0,0 @@
>>     -AT_BANNER([ovn-sbctl])
>>     -
>>     -# OVN_SBCTL_TEST_START
>>     -m4_define([OVN_SBCTL_TEST_START],
>>     -  [dnl Create databases (ovn-nb, ovn-sb).
>>     -   AT_KEYWORDS([ovn])
>>     -   for daemon in ovn-nb ovn-sb; do
>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>     -   done
>>     -
>>     -   dnl Start ovsdb-servers.
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>     --pidfile=ovnnb_db.pid --unixctl=$OVS_RUNDIR/ovnnb_db.ctl
>>     --log-file=ovsdb_nb.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock
>>     ovn-nb.db ], [0], [], [stderr])
>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>     --pidfile=ovnsb_db.pid --unixctl=$OVS_RUNDIR/ovnsb_db.ctl
>>     --log-file=ovsdb_sb.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock
>>     ovn-sb.db], [0], [], [stderr])
>>     -   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d
>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>     -
>>     -   dnl Start ovn-northd.
>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file
>>     --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock
>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>     -   on_exit "kill `cat ovn-northd.pid`"
>>     -   AT_CHECK([[sed < stderr '
>>     -/vlog|INFO|opened log file/d']])
>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>     -])
>>     -
>>     -# OVN_SBCTL_TEST_STOP
>>     -m4_define([OVN_SBCTL_TEST_STOP],
>>     -  [AT_CHECK([check_logs "$1"])
>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl],
>>     [$OVS_RUNDIR/ovnnb_db.pid])
>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl],
>>     [$OVS_RUNDIR/ovnsb_db.pid])])
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -AT_SETUP([ovn-sbctl - chassis commands])
>>     -OVN_SBCTL_TEST_START
>>     -ovn_init_db ovn-sb
>>     -
>>     -AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>     ip,type list encap | sort],
>>     -         [0], [dnl
>>     -1.2.3.4,geneve
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>     ip,type list encap | sort],
>>     -         [0], [dnl
>>     -1.2.3.4,geneve
>>     -1.2.3.5,geneve
>>     -1.2.3.5,stt
>>     -1.2.3.5,vxlan
>>     -])
>>     -
>>     -AT_CHECK([ovn-sbctl chassis-del ch0])
>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>     ip,type list encap | sort],
>>     -         [0], [dnl
>>     -1.2.3.5,geneve
>>     -1.2.3.5,stt
>>     -1.2.3.5,vxlan
>>     -])
>>     -
>>     -OVN_SBCTL_TEST_STOP
>>     -as ovn-sb
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -AT_CLEANUP
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -AT_SETUP([ovn-sbctl])
>>     -OVN_SBCTL_TEST_START
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add br-test])
>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>     -AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>     -
>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>     -Chassis ch0
>>     -    Encap stt
>>     -        ip: "1.2.3.5"
>>     -        options: {csum="true"}
>>     -    Port_Binding vif0
>>     -])
>>     -
>>     -# adds another 'vif1'
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>     -
>>     -AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
>>     -Chassis ch0
>>     -    Encap stt
>>     -        ip: "1.2.3.5"
>>     -        options: {csum="true"}
>>     -    Port_Binding vif
>>     -    Port_Binding vif
>>     -])
>>     -
>>     -# deletes 'vif1'
>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>     -
>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>     -Chassis ch0
>>     -    Encap stt
>>     -        ip: "1.2.3.5"
>>     -        options: {csum="true"}
>>     -    Port_Binding vif0
>>     -])
>>     -
>>     -uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':'
>>     -f2 | tr -d ' ')
>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis
>>     list Port_Binding], [0], [dnl
>>     -logical_port        : vif0
>>     -mac                 : [["f0:ab:cd:ef:01:02"]]
>>     -chassis             : ${uuid}
>>     -])
>>     -
>>     -# test the passing down of logical port type and options.
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
>>     -AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
>>     -AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0
>>     vtep_logical_switch=l0])
>>     -
>>     -AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0
>>     options!={}])
>>     -AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list
>>     Port_Binding vtep0], [0], [dnl
>>     -logical_port        : vtep0
>>     -mac                 : [[]]
>>     -type                : vtep
>>     -options             : {vtep_logical_switch=l0,
>>     vtep_physical_switch=p0}
>>     -])
>>     -
>>     -OVN_SBCTL_TEST_STOP
>>     -AT_CLEANUP
>>     -
>>     -dnl
>>     ---------------------------------------------------------------------
>>     -
>>     -AT_SETUP([ovn-sbctl - connection])
>>     -OVN_SBCTL_TEST_START
>>     -
>>     -AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection
>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
>>     -AT_CHECK([ovn-sbctl list connection | grep inactivity_probe],
>>     [0], [dnl
>>     -inactivity_probe    : 30000
>>     -inactivity_probe    : 30000
>>     -])
>>     -
>>     -OVN_SBCTL_TEST_STOP
>>     -AT_CLEANUP
>>     diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at
>>     <http://ovn.at>
>>     deleted file mode 100644
>>     index cb380d2..0000000
>>     --- a/tests/ovn.at <http://ovn.at>
>>     +++ /dev/null
>>     @@ -1,14702 +0,0 @@
>>     -# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
>>     -#
>>     -# This compares packets read from PCAP, in pcap format, to those 
>> read
>>     -# from EXPECTED, which is a text file containing packets as hex
>>     -# strings, one per line.  If PCAP contains fewer packets than
>>     -# EXPECTED, it waits up to 10 seconds for more packets to appear.
>>     -#
>>     -# The implementation is an m4 macro that is mostly implemented in
>>     -# terms of a shell function.  This reduces the size of the generated
>>     -# testsuite file since the shell function is only emitted once even
>>     -# when this macro is invoked many times.
>>     -m4_divert_text([PREPARE_TESTS],
>>     -  [ovn_check_packets__ () {
>>     -     echo
>>     -     echo "checking packets in $1 against $2:"
>>     -     rcv_pcap=$1
>>     -     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
>>     -     exp_text=$2
>>     -     exp_n=`wc -l < "$exp_text"`
>>     -     OVS_WAIT_UNTIL(
>>     -       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $rcv_pcap > $rcv_text
>>     -        rcv_n=`wc -l < "$rcv_text"`
>>     -        echo "rcv_n=$rcv_n exp_n=$exp_n"
>>     -        test $rcv_n -ge $exp_n])
>>     -     sort $exp_text > expout
>>     -   }
>>     -])
>>     -m4_define([OVN_CHECK_PACKETS],
>>     -  [ovn_check_packets__ "$1" "$2"
>>     -   AT_CHECK([sort $rcv_text], [0], [expout])])
>>     -
>>     -AT_BANNER([OVN components])
>>     -
>>     -AT_SETUP([ovn -- lexer])
>>     -dnl For lines without =>, input and expected output are identical.
>>     -dnl For lines with =>, input precedes => and expected output
>>     follows =>.
>>     -AT_DATA([test-cases.txt], [dnl
>>     -foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
>>     -"abc\u0020def" => "abc def"
>>     -" => error("Input ends inside quoted string.")dnl "
>>     -
>>     -$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
>>     -$1 => error("`$' must be followed by a valid identifier.") 1
>>     -
>>     -a/*b*/c => a c
>>     -a//b c => a
>>     -a/**/b => a b
>>     -a/*/b => a error("`/*' without matching `*/'.")
>>     -a/*/**/b => a b
>>     -a/b => a error("`/' is only valid as part of `//' or `/*'.") b
>>     -
>>     -0 1 12345 18446744073709551615
>>     -18446744073709551616 => error("Decimal constants must be less
>>     than 2**64.")
>>     -9999999999999999999999 => error("Decimal constants must be less
>>     than 2**64.")
>>     -01 => error("Decimal constants must not have leading zeros.")
>>     -
>>     -0/0
>>     -0/1
>>     -1/0 => error("Value contains unmasked 1-bits.")
>>     -1/1
>>     -128/384
>>     -1/3
>>     -1/ => error("Integer constant expected.")
>>     -
>>     -1/0x123 => error("Value and mask have incompatible formats.")
>>     -
>>     -0x1234
>>     -0x01234 => 0x1234
>>     -0x0 => 0
>>     -0x000 => 0
>>     -0xfedcba9876543210
>>     -0XFEDCBA9876543210 => 0xfedcba9876543210
>>     -0xfedcba9876543210fedcba9876543210
>>     -0x0000fedcba9876543210fedcba9876543210 =>
>>     0xfedcba9876543210fedcba9876543210
>>     -0x => error("Hex digits expected following 0x.")
>>     -0X => error("Hex digits expected following 0X.")
>>     -0x0/0x0 => 0/0
>>     -0x0/0x1 => 0/0x1
>>     -0x1/0x0 => error("Value contains unmasked 1-bits.")
>>     -0xffff/0x1ffff
>>     -0x. => error("Invalid syntax in hexadecimal constant.")
>>     -
>>     -192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
>>     -256.1.2.3 => error("Invalid numeric constant.")
>>     -192.168.0.0/16 <http://192.168.0.0/16>
>>     -192.168.0.0/255.255.0.0 <http://192.168.0.0/255.255.0.0> =>
>>     192.168.0.0/16 <http://192.168.0.0/16>
>>     -192.168.0.0/255.255.255.0 <http://192.168.0.0/255.255.255.0> =>
>>     192.168.0.0/24 <http://192.168.0.0/24>
>>     -192.168.0.0/255.255.0.255 <http://192.168.0.0/255.255.0.255>
>>     -192.168.0.0/255.0.0.0 <http://192.168.0.0/255.0.0.0> =>
>>     error("Value contains unmasked 1-bits.")
>>     -192.168.0.0/32 <http://192.168.0.0/32>
>>     -192.168.0.0/255.255.255.255 <http://192.168.0.0/255.255.255.255>
>>     => 192.168.0.0/32 <http://192.168.0.0/32>
>>     -1.2.3.4:5 <http://1.2.3.4:5> => 1.2.3.4 : 5
>>     -
>>     -::
>>     -::1
>>     -ff00::1234 => ff00::1234
>>     -2001:db8:85a3::8a2e:370:7334
>>     -2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
>>     -2001:0db8:85a3:0000:0000:8a2e:0370:7334 =>
>>     2001:db8:85a3::8a2e:370:7334
>>     -::ffff:192.0.2.128
>>     -::ffff:c000:0280 => ::ffff:192.0.2.128
>>     -::1/::1
>>     -::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
>>     -::1/128
>>     -ff00::/8
>>     -ff00::/ff00:: => ff00::/8
>>     -
>>     -01:23:45:67:ab:cd
>>     -01:23:45:67:AB:CD => 01:23:45:67:ab:cd
>>     -fe:dc:ba:98:76:54
>>     -FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
>>     -01:00:00:00:00:00/01:00:00:00:00:00
>>     -ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>     -fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>     -ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains
>>     unmasked 1-bits.")
>>     -fe:x => error("Invalid numeric constant.")
>>     -00:01:02:03:04:x => error("Invalid numeric constant.")
>>     -
>>     -# Test that operators are tokenized as expected, even without
>>     white space.
>>     -(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= >
>>     >= ! && || .. , ; = <-> -- :
>>     -& => error("`&' is only valid as part of `&&'.")
>>     -| => error("`|' is only valid as part of `||'.")
>>     -- => error("`-' is only valid as part of `--'.")
>>     -
>>     -^ => error("Invalid character `^' in input.")
>>     -])
>>     -AT_CAPTURE_FILE([input.txt])
>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>     -sed 's/.* => //' test-cases.txt > expout
>>     -AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
>>     -AT_CLEANUP
>>     -
>>     -dnl The OVN expression parser needs to know what fields overlap
>>     with one
>>     -dnl another.  This test therefore verifies that all the smaller
>>     registers
>>     -dnl are defined as terms of subfields of the larger ones.
>>     -dnl
>>     -dnl When we add or remove registers this test needs to be
>>     updated, of course.
>>     -AT_SETUP([ovn -- registers])
>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
>>     -[[reg0 = xxreg0[96..127]
>>     -reg1 = xxreg0[64..95]
>>     -reg2 = xxreg0[32..63]
>>     -reg3 = xxreg0[0..31]
>>     -reg4 = xxreg1[96..127]
>>     -reg5 = xxreg1[64..95]
>>     -reg6 = xxreg1[32..63]
>>     -reg7 = xxreg1[0..31]
>>     -reg8 = xreg4[32..63]
>>     -reg9 = xreg4[0..31]
>>     -xreg0 = xxreg0[64..127]
>>     -xreg1 = xxreg0[0..63]
>>     -xreg2 = xxreg1[64..127]
>>     -xreg3 = xxreg1[0..63]
>>     -xreg4 = OXM_OF_PKT_REG4
>>     -xxreg0 = NXM_NX_XXREG0
>>     -xxreg1 = NXM_NX_XXREG1
>>     -]])
>>     -AT_CLEANUP
>>     -
>>     -dnl Check that the OVN conntrack field definitions are correct.
>>     -AT_SETUP([ovn -- conntrack fields])
>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
>>     -[[ct.dnat = ct_state[7]
>>     -ct.est = ct_state[1]
>>     -ct.inv = ct_state[4]
>>     -ct.new = ct_state[0]
>>     -ct.rel = ct_state[2]
>>     -ct.rpl = ct_state[3]
>>     -ct.snat = ct_state[6]
>>     -ct.trk = ct_state[5]
>>     -ct_label = NXM_NX_CT_LABEL
>>     -ct_label.blocked = ct_label[0]
>>     -ct_mark = NXM_NX_CT_MARK
>>     -ct_state = NXM_NX_CT_STATE
>>     -]])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- composition])
>>     -AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- expression parser])
>>     -dnl For lines without =>, input and expected output are identical.
>>     -dnl For lines with =>, input precedes => and expected output
>>     follows =>.
>>     -AT_DATA([test-cases.txt], [[
>>     -eth.type == 0x800
>>     -eth.type==0x800 => eth.type == 0x800
>>     -eth.type[0..15] == 0x800 => eth.type == 0x800
>>     -
>>     -vlan.present
>>     -vlan.present == 1 => vlan.present
>>     -!(vlan.present == 0) => vlan.present
>>     -!(vlan.present != 1) => vlan.present
>>     -!vlan.present
>>     -vlan.present == 0 => !vlan.present
>>     -vlan.present != 1 => !vlan.present
>>     -!(vlan.present == 1) => !vlan.present
>>     -!(vlan.present != 0) => !vlan.present
>>     -
>>     -eth.dst[0]
>>     -eth.dst[0] == 1 => eth.dst[0]
>>     -eth.dst[0] != 0 => eth.dst[0]
>>     -!(eth.dst[0] == 0) => eth.dst[0]
>>     -!(eth.dst[0] != 1) => eth.dst[0]
>>     -
>>     -!eth.dst[0]
>>     -eth.dst[0] == 0 => !eth.dst[0]
>>     -eth.dst[0] != 1 => !eth.dst[0]
>>     -!(eth.dst[0] == 1) => !eth.dst[0]
>>     -!(eth.dst[0] != 0) => !eth.dst[0]
>>     -
>>     -vlan.tci[12..15] == 0x3
>>     -vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
>>     -vlan.tci[12..15] != 0x3
>>     -vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
>>     -
>>     -!vlan.pcp => vlan.pcp == 0
>>     -!(vlan.pcp) => vlan.pcp == 0
>>     -vlan.pcp == 0x4
>>     -vlan.pcp != 0x4
>>     -vlan.pcp > 0x4
>>     -vlan.pcp >= 0x4
>>     -vlan.pcp < 0x4
>>     -vlan.pcp <= 0x4
>>     -!(vlan.pcp != 0x4) => vlan.pcp == 0x4
>>     -!(vlan.pcp == 0x4) => vlan.pcp != 0x4
>>     -!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
>>     -!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
>>     -!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
>>     -!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
>>     -0x4 == vlan.pcp => vlan.pcp == 0x4
>>     -0x4 != vlan.pcp => vlan.pcp != 0x4
>>     -0x4 < vlan.pcp => vlan.pcp > 0x4
>>     -0x4 <= vlan.pcp => vlan.pcp >= 0x4
>>     -0x4 > vlan.pcp => vlan.pcp < 0x4
>>     -0x4 >= vlan.pcp => vlan.pcp <= 0x4
>>     -!(0x4 != vlan.pcp) => vlan.pcp == 0x4
>>     -!(0x4 == vlan.pcp) => vlan.pcp != 0x4
>>     -!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
>>     -!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
>>     -!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
>>     -!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
>>     -
>>     -1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>     -1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
>>     -1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>     -4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
>>     -4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
>>     -4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
>>     -4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
>>     -!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>     -!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
>>     -!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>     -!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
>>     -!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
>>     -!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
>>     -!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
>>     -
>>     -vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 ||
>>     vlan.pcp == 0x3 || vlan.pcp == 0x4
>>     -vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp ==
>>     4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 ||
>>     vlan.pcp == 0x4
>>     -
>>     -vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 &&
>>     vlan.pcp != 0x3 && vlan.pcp != 0x4
>>     -vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp ==
>>     4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 &&
>>     vlan.pcp == 0x4
>>     -
>>     -vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 ||
>>     vlan.pcp != 0x4)
>>     -vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3)
>>     && vlan.pcp == 0x4
>>     -vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>     == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3)
>>     || vlan.pcp != 0x4)
>>     -
>>     -ip4.src == {10.0.0.0/8 <http://10.0.0.0/8>, 192.168.0.0/16
>>     <http://192.168.0.0/16>, 172.16.20.0/24 <http://172.16.20.0/24>,
>>     8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 ||
>>     ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
>>     -ip6.src == ::1 => ip6.src == 0x1
>>     -
>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304
>>     -ip4.src == ::1.2.3.4/::ffff:ffff <http://1.2.3.4/::ffff:ffff> =>
>>     ip4.src == 0x1020304
>>     -ip6.src == ::1 => ip6.src == 0x1
>>     -
>>     -1
>>     -0
>>     -!1 => 0
>>     -!0 => 1
>>     -
>>     -inport == "eth0"
>>     -!(inport != "eth0") => inport == "eth0"
>>     -
>>     
>> -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>
>>     => 0
>>     -
>>     -ip4.src == "eth0" => Integer field ip4.src is not compatible with
>>     string constant.
>>     -inport == 1 => String field inport is not compatible with integer
>>     constant.
>>     -ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational
>>     operator.
>>     -
>>     -ip4.src > {1, 2, 3} => Only == and != operators may be used with
>>     value sets.
>>     -eth.type > 0x800 => Only == and != operators may be used with
>>     nominal field eth.type.
>>     -vlan.present > 0 => Only == and != operators may be used with
>>     Boolean field vlan.present.
>>     -
>>     -inport != "eth0" => Nominal field inport may only be tested for
>>     equality (taking enclosing `!' operators into account).
>>     -!(inport == "eth0") => Nominal field inport may only be tested
>>     for equality (taking enclosing `!' operators into account).
>>     -eth.type != 0x800 => Nominal field eth.type may only be tested
>>     for equality (taking enclosing `!' operators into account).
>>     -!(eth.type == 0x800) => Nominal field eth.type may only be tested
>>     for equality (taking enclosing `!' operators into account).
>>     -inport = "eth0" => Syntax error at `=' expecting relational 
>> operator.
>>     -
>>     -123 == 123 => Syntax error at `123' expecting field name.
>>     -
>>     -$name => Syntax error at `$name' expecting address set name.
>>     -@name => Syntax error at `@name' expecting port group name.
>>     -
>>     -123 == xyzzy => Syntax error at `xyzzy' expecting field name.
>>     -xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
>>     -
>>     -inport[1] == 1 => Cannot select subfield of string field inport.
>>     -
>>     -eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
>>     -eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
>>     -eth.type[18446744073709551615] == 1 => Syntax error at
>>     `18446744073709551615' expecting small integer.
>>     -
>>     -eth.type[5!] => Syntax error at `!' expecting `@:>@'.
>>     -
>>     -eth.type[5..1] => Invalid bit range 5 to 1.
>>     -
>>     -eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field
>>     eth.type.
>>     -
>>     -eth.type[10] == 1 => Cannot select subfield of nominal field
>>     eth.type.
>>     -
>>     -eth.type => Explicit `!= 0' is required for inequality test of
>>     multibit field against 0.
>>     -
>>     -!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test
>>     of multibit field against 0.
>>     -
>>     -123 => Syntax error at end of input expecting relational operator.
>>     -
>>     -123 x => Syntax error at `x' expecting relational operator.
>>     -
>>     -{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
>>     -
>>     -eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
>>     -
>>     -(1 x) => Syntax error at `x' expecting `)'.
>>     -
>>     -!0x800 != eth.type => Missing parentheses around operand of !.
>>     -
>>     -eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => &&
>>     and || must be parenthesized when used together.
>>     -
>>     -eth.dst == {} => Syntax error at `}' expecting constant.
>>     -
>>     -eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and !=
>>     operators may be used with masked constants. Consider using
>>     subfields instead (e.g. eth.src[0..15] > 0x1111 in place of
>>     eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
>>     -
>>     -ip4.src == ::1 => 128-bit constant is not compatible with 32-bit
>>     field ip4.src.
>>     -
>>     -1 == eth.type == 2 => Range expressions must have the form `x <
>>     field < y' or `x > field > y', with each `<' optionally replaced
>>     by `<=' or `>' by `>=').
>>     -
>>     -eth.dst[40] x => Syntax error at `x' expecting end of input.
>>     -
>>     -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at
>>     `$unknownset' expecting address set name.
>>     -eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at
>>     `badmac' expecting constant.
>>     -
>>     
>> -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>
>>     => Parentheses nested too deeply.
>>     -
>>     -ct_label > $set4 => Only == and != operators may be used to
>>     compare a field against an empty value set.
>>     -]])
>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>     -sed 's/.* => //' test-cases.txt > expout
>>     -AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- expression annotation])
>>     -dnl Input precedes =>, expected output follows =>.
>>     -dnl Empty lines and lines starting with # are ignored.
>>     -AT_DATA([test-cases.txt], [[
>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
>>     -ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
>>     -ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 ||
>>     eth.type == 0x86dd)
>>     -ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea)
>>     && (eth.type == 0x800 || eth.type == 0x86dd)
>>     -ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304
>>     && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
>>     -
>>     -# Nested expressions over a single symbol should be annotated
>>     with symbol's
>>     -# prerequisites only once, at the top level.
>>     -tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1
>>     || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 &&
>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>     -
>>     -ip => eth.type == 0x800 || eth.type == 0x86dd
>>     -ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>     -ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>     -ip > 0 => Only == and != operators may be used with nominal field 
>> ip.
>>     -!ip => Nominal predicate ip may only be tested positively, e.g.
>>     `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>     -ip == 0 => Nominal predicate ip may only be tested positively,
>>     e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>     -
>>     -vlan.present => vlan.tci[12]
>>     -!vlan.present => !vlan.tci[12]
>>     -
>>     -!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
>>     -vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 &&
>>     vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
>>     -!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 &&
>>     xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
>>     -
>>     -ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type ==
>>     0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
>>     -!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type
>>     != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>     0x86dd))
>>     -ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>     0x86dd)
>>     -
>>     -bad_prereq != 0 => Error parsing expression `xyzzy' encountered
>>     as prerequisite or predicate of initial expression: Syntax error
>>     at `xyzzy' expecting field name.
>>     -self_recurse != 0 => Error parsing expression `self_recurse != 0'
>>     encountered as prerequisite or predicate of initial expression:
>>     Recursive expansion of symbol `self_recurse'.
>>     -mutual_recurse_1 != 0 => Error parsing expression
>>     `mutual_recurse_2 != 0' encountered as prerequisite or predicate
>>     of initial expression: Error parsing expression `mutual_recurse_1
>>     != 0' encountered as prerequisite or predicate of initial
>>     expression: Recursive expansion of symbol `mutual_recurse_1'.
>>     -mutual_recurse_2 != 0 => Error parsing expression
>>     `mutual_recurse_1 != 0' encountered as prerequisite or predicate
>>     of initial expression: Error parsing expression `mutual_recurse_2
>>     != 0' encountered as prerequisite or predicate of initial
>>     expression: Recursive expansion of symbol `mutual_recurse_2'.
>>     -]])
>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>     -sed 's/.* => //' test-cases.txt > expout
>>     -AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], 
>> [expout])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 1-term expression conversion])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
>>     -  [Tested converting all 1-terminal expressions with 2 numeric
>>     vars (each 3 bits) in terms of operators == != < <= > >= and 2
>>     string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2-term expression conversion])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
>>     -  [Tested converting 578 expressions of 2 terminals with 2
>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>     and 2 string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 3-term expression conversion])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert
>>     --bits=2 3], [0],
>>     -  [Tested converting 67410 expressions of 3 terminals with 2
>>     numeric vars (each 2 bits) in terms of operators == != < <= > >=
>>     and 2 string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 3-term numeric expression simplification])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>     --nvars=2 --svars=0 3], [0],
>>     -  [Tested simplifying 490770 expressions of 3 terminals with 2
>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term string expression simplification])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>     --nvars=0 --svars=4 4], [0],
>>     -  [Tested simplifying 21978 expressions of 4 terminals with 4
>>     string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 3-term mixed expression simplification])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>     --nvars=1 --svars=1 3], [0],
>>     -  [Tested simplifying 127890 expressions of 3 terminals with 1
>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>     and 1 string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- simplification special cases])
>>     -simplify() {
>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>     -}
>>     -AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
>>     -])
>>     -AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
>>     -])
>>     -AT_CHECK([simplify 'tcp.dst >= 0'], [0],
>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>     -])
>>     -AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>     -])
>>     -AT_CHECK([simplify 'tcp.dst > 0'], [0],
>>     -    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] ||
>>     tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8]
>>     || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] ||
>>     tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 &&
>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>     -]])
>>     -AT_CHECK([simplify 'tcp.dst < 65535'], [0],
>>     -    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3]
>>     || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] ||
>>     !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] ||
>>     !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) &&
>>     ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>     -]])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- is_chassis_resident simplification])
>>     -simplify() {
>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>     -}
>>     -AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
>>     -])
>>     -AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
>>     -])
>>     -AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
>>     -])
>>     -AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term numeric expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=3 --svars=0 --bits=1 4], [0],
>>     -  [Tested normalizing 1874026 expressions of 4 terminals with 3
>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term string expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=0 --svars=3 --bits=1 4], [0],
>>     -  [Tested normalizing 11242 expressions of 4 terminals with 3
>>     string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term mixed expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=1 --bits=1 --svars=2 4], [0],
>>     -  [Tested normalizing 175978 expressions of 4 terminals with 1
>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=
>>     and 2 string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 5-term numeric expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
>>     -  [Tested normalizing 1317600 expressions of 5 terminals with 3
>>     numeric vars (each 1 bits) in terms of operators ==.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 5-term string expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
>>     -  [Tested normalizing 368550 expressions of 5 terminals with 3
>>     string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 5-term mixed expression normalization])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>     --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
>>     -  [Tested normalizing 216000 expressions of 5 terminals with 1
>>     numeric vars (each 1 bits) in terms of operators == and 1 string 
>> vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term numeric expressions to flows])
>>     -AT_KEYWORDS([expression])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2
>>     --svars=0 --bits=2 --relops='==' 4], [0],
>>     -  [Tested converting to flows 175978 expressions of 4 terminals
>>     with 2 numeric vars (each 2 bits) in terms of operators ==.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term string expressions to flows])
>>     -AT_KEYWORDS([expression])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0
>>     --svars=4 4], [0],
>>     -  [Tested converting to flows 21978 expressions of 4 terminals
>>     with 4 string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4-term mixed expressions to flows])
>>     -AT_KEYWORDS([expression])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1
>>     --bits=2 --svars=1 --relops='==' 4], [0],
>>     -  [Tested converting to flows 48312 expressions of 4 terminals
>>     with 1 numeric vars (each 2 bits) in terms of operators == and 1
>>     string vars.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 3-term numeric expressions to flows])
>>     -AT_KEYWORDS([expression])
>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3
>>     --svars=0 --bits=3 --relops='==' 3], [0],
>>     -  [Tested converting to flows 41328 expressions of 3 terminals
>>     with 3 numeric vars (each 3 bits) in terms of operators ==.
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- converting expressions to flows -- string fields])
>>     -AT_KEYWORDS([expression])
>>     -expr_to_flow () {
>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>     -}
>>     -AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
>>     -ip,reg14=0x5
>>     -ipv6,reg14=0x5
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
>>     -ip,reg14=0x6
>>     -ipv6,reg14=0x6
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2",
>>     "LOCAL"}'], [0],
>>     -[reg14=0x5
>>     -reg14=0x6
>>     -reg14=0xfffe
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} &&
>>     ip'], [0], [dnl
>>     -ip,reg14=0x5
>>     -ip,reg14=0x6
>>     -ipv6,reg14=0x5
>>     -ipv6,reg14=0x6
>>     -])
>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'],
>>     [0], [dnl
>>     -(no flows)
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- converting expressions to flows -- address sets])
>>     -AT_KEYWORDS([expression])
>>     -expr_to_flow () {
>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>     -}
>>     -AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2,
>>     10.0.0.3}'], [0], [dnl
>>     -ip,nw_src=10.0.0.1
>>     -ip,nw_src=10.0.0.2
>>     -ip,nw_src=10.0.0.3
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
>>     -ip,nw_src=10.0.0.1
>>     -ip,nw_src=10.0.0.2
>>     -ip,nw_src=10.0.0.3
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
>>     -ip,nw_src=1.2.3.4
>>     -ip,nw_src=10.0.0.1
>>     -ip,nw_src=10.0.0.2
>>     -ip,nw_src=10.0.0.3
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20
>>     <http://1.2.0.0/20>, 5.5.5.0/24 <http://5.5.5.0/24>, $set1}'],
>>     [0], [dnl
>>     -ip,nw_src=1.2.0.0/20 <http://1.2.0.0/20>
>>     -ip,nw_src=10.0.0.1
>>     -ip,nw_src=10.0.0.2
>>     -ip,nw_src=10.0.0.3
>>     -ip,nw_src=5.5.5.0/24 <http://5.5.5.0/24>
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
>>     -ipv6,ipv6_src=::1
>>     -ipv6,ipv6_src=::2
>>     -ipv6,ipv6_src=::3
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
>>     -ipv6,ipv6_src=::1
>>     -ipv6,ipv6_src=::2
>>     -ipv6,ipv6_src=::3
>>     -ipv6,ipv6_src=::4
>>     -])
>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01,
>>     00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
>>     -dl_src=00:00:00:00:00:01
>>     -dl_src=00:00:00:00:00:02
>>     -dl_src=00:00:00:00:00:03
>>     -])
>>     -AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
>>     -dl_src=00:00:00:00:00:01
>>     -dl_src=00:00:00:00:00:02
>>     -dl_src=00:00:00:00:00:03
>>     -])
>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3,
>>     ba:be:be:ef:de:ad, $set3}'], [0], [dnl
>>     -dl_src=00:00:00:00:00:01
>>     -dl_src=00:00:00:00:00:02
>>     -dl_src=00:00:00:00:00:03
>>     -dl_src=ba:be:be:ef:de:ad
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
>>     -(no flows)
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
>>     -ip,nw_src=1.2.3.4
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src ==
>>     {$set4}'], [0], [dnl
>>     -ip,nw_src=1.2.3.4
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
>>     -
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8 <http://1.0.0.0/8>,
>>     $set4}'], [0], [dnl
>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>     -])
>>     -AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 <http://1.0.0.0/8>
>>     && ip4.src != {$set4}'], [0], [dnl
>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- converting expressions to flows -- port groups])
>>     -AT_KEYWORDS([expression])
>>     -expr_to_flow () {
>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>     -}
>>     -AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
>>     -reg15=0x11
>>     -reg15=0x12
>>     -reg15=0x13
>>     -])
>>     -AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
>>     -(no flows)
>>     -])
>>     -AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], [dnl
>>     -reg15=0x11
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- converting expressions to flows -- conjunction])
>>     -AT_KEYWORDS([conjunction])
>>     -expr_to_flow () {
>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>     -}
>>     -
>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>     -conj_id=1,ip
>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>     -ip,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/2)
>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>     -])
>>     -
>>     -lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>     -ct_state=+est+trk,ct_label=0x1/0x1,ip
>>     -ct_state=+est+trk,ct_label=0x1/0x1,ipv6
>>     -ct_state=-est+trk,ip
>>     -ct_state=-est+trk,ipv6
>>     -])
>>     -
>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>     -ip4.dst == {20.0.0.1, 20.0.0.2}"
>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>     -conj_id=1,ip
>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>     -])
>>     -
>>     -lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
>>     -tcp.dst >= 1000 && tcp.dst <= 1010"
>>     -
>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>     -conj_id=1,tcp
>>     -tcp,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/3)
>>     -tcp,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/3)
>>     -tcp,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/3)
>>     -tcp,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/3)
>>     -tcp,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/3)
>>     -tcp,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/3)
>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
>>     -tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
>>     -tcp,tp_dst=1000: conjunction(1, 2/3)
>>     -tcp,tp_dst=1001: conjunction(1, 2/3)
>>     -tcp,tp_dst=1010: conjunction(1, 2/3)
>>     -])
>>     -
>>     -lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
>>     -((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 && \
>>     -tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
>>     -|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
>>     -
>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>     -conj_id=1,tcp
>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
>>     -tcp,nw_dst=20.0.0.4 <http://20.0.0.4>: conjunction(1, 0/4)
>>     -tcp,nw_dst=20.0.0.7 <http://20.0.0.7>: conjunction(1, 0/4)
>>     -tcp,nw_dst=20.0.0.8 <http://20.0.0.8>: conjunction(1, 0/4)
>>     -tcp,nw_src=10.0.0.4 <http://10.0.0.4>: conjunction(1, 1/4)
>>     -tcp,nw_src=10.0.0.5 <http://10.0.0.5>: conjunction(1, 1/4)
>>     -tcp,nw_src=10.0.0.6 <http://10.0.0.6>: conjunction(1, 1/4)
>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
>>     -tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
>>     -tcp,tp_dst=1000: conjunction(1, 2/4)
>>     -tcp,tp_dst=1001: conjunction(1, 2/4)
>>     -tcp,tp_dst=2000: conjunction(1, 2/4)
>>     -tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
>>     -tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
>>     -tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
>>     -tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
>>     -tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
>>     -tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
>>     -tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
>>     -tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
>>     -tcp,tp_src=1000: conjunction(1, 3/4)
>>     -tcp,tp_src=1001: conjunction(1, 3/4)
>>     -tcp,tp_src=2000: conjunction(1, 3/4)
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- action parsing])
>>     -dnl Unindented text is input (a set of OVN logical actions).
>>     -dnl Indented text is expected output.
>>     -AT_DATA([test-cases.txt],
>>     -[[# drop
>>     -drop;
>>     -    encodes as drop
>>     -drop; next;
>>     -    Syntax error at `next' expecting end of input.
>>     -next; drop;
>>     -    Syntax error at `drop' expecting action.
>>     -
>>     -# output
>>     -output;
>>     -    encodes as resubmit(,64)
>>     -
>>     -# next
>>     -next;
>>     -    encodes as resubmit(,19)
>>     -next(11);
>>     -    formats as next;
>>     -    encodes as resubmit(,19)
>>     -next(0);
>>     -    encodes as resubmit(,8)
>>     -next(23);
>>     -    encodes as resubmit(,31)
>>     -
>>     -next();
>>     -    Syntax error at `)' expecting "pipeline" or "table".
>>     -next(10;
>>     -    Syntax error at `;' expecting `)'.
>>     -next(24);
>>     -    "next" action cannot advance beyond table 23.
>>     -
>>     -next(table=11);
>>     -    formats as next;
>>     -    encodes as resubmit(,19)
>>     -next(pipeline=ingress);
>>     -    formats as next;
>>     -    encodes as resubmit(,19)
>>     -next(table=11, pipeline=ingress);
>>     -    formats as next;
>>     -    encodes as resubmit(,19)
>>     -next(pipeline=ingress, table=11);
>>     -    formats as next;
>>     -    encodes as resubmit(,19)
>>     -
>>     -next(pipeline=egress);
>>     -    "next" action cannot advance from ingress to egress pipeline
>>     (use "output" action instead)
>>     -
>>     -next(table=10);
>>     -    formats as next(10);
>>     -    encodes as resubmit(,18)
>>     -
>>     -# Loading a constant value.
>>     -tcp.dst=80;
>>     -    formats as tcp.dst = 80;
>>     -    encodes as set_field:80->tcp_dst
>>     -    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type
>>     == 0x86dd)
>>     -eth.dst[40] = 1;
>>     -    encodes as 
>> set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
>>     -vlan.pcp = 2;
>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>     -    has prereqs vlan.tci[12]
>>     -vlan.tci[13..15] = 2;
>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>     -inport = "";
>>     -    encodes as set_field:0->reg14
>>     -ip.ttl=4;
>>     -    formats as ip.ttl = 4;
>>     -    encodes as set_field:4->nw_ttl
>>     -    has prereqs eth.type == 0x800 || eth.type == 0x86dd
>>     -outport="eth0"; next; outport="LOCAL"; next;
>>     -    formats as outport = "eth0"; next; outport = "LOCAL"; next;
>>     -    encodes as
>>     
>> set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
>>     -
>>     -inport[1] = 1;
>>     -    Cannot select subfield of string field inport.
>>     -ip.proto[1] = 1;
>>     -    Cannot select subfield of nominal field ip.proto.
>>     -eth.dst[40] == 1;
>>     -    Syntax error at `==' expecting `=' or `<->'.
>>     -ip = 1;
>>     -    Predicate symbol ip used where lvalue required.
>>     -ip.proto = 6;
>>     -    Field ip.proto is not modifiable.
>>     -inport = {"a", "b"};
>>     -    Syntax error at `{' expecting constant.
>>     -inport = {};
>>     -    Syntax error at `{' expecting constant.
>>     -bad_prereq = 123;
>>     -    Error parsing expression `xyzzy' encountered as prerequisite
>>     or predicate of initial expression: Syntax error at `xyzzy'
>>     expecting field name.
>>     -self_recurse = 123;
>>     -    Error parsing expression `self_recurse != 0' encountered as
>>     prerequisite or predicate of initial expression: Error parsing
>>     expression `self_recurse != 0' encountered as prerequisite or
>>     predicate of initial expression: Recursive expansion of symbol
>>     `self_recurse'.
>>     -vlan.present = 0;
>>     -    Predicate symbol vlan.present used where lvalue required.
>>     -
>>     -# Moving one field into another.
>>     -reg0=reg1;
>>     -    formats as reg0 = reg1;
>>     -    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
>>     -vlan.pcp = reg0[0..2];
>>     -    encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
>>     -    has prereqs vlan.tci[12]
>>     -reg0[10] = vlan.pcp[1];
>>     -    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
>>     -    has prereqs vlan.tci[12]
>>     -outport = inport;
>>     -    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
>>     -
>>     -reg0[0] = vlan.present;
>>     -    Predicate symbol vlan.present used where lvalue required.
>>     -reg0 = reg1[0..10];
>>     -    Can't assign 11-bit value to 32-bit destination.
>>     -inport = reg0;
>>     -    Can't assign integer field (reg0) to string field (inport).
>>     -inport = big_string;
>>     -    String fields inport and big_string are incompatible for
>>     assignment.
>>     -ip.proto = reg0[0..7];
>>     -    Field ip.proto is not modifiable.
>>     -
>>     -# Exchanging fields.
>>     -reg0 <-> reg1;
>>     -    encodes as
>>     
>> push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127] 
>>
>>     -vlan.pcp <-> reg0[0..2];
>>     -    encodes as
>>     
>> push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15] 
>>
>>     -    has prereqs vlan.tci[12]
>>     -reg0[10] <-> vlan.pcp[1];
>>     -    encodes as
>>     
>> push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106] 
>>
>>     -    has prereqs vlan.tci[12]
>>     -outport <-> inport;
>>     -    encodes as
>>     
>> push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[] 
>>
>>     -
>>     -reg0[0] <-> vlan.present;
>>     -    Predicate symbol vlan.present used where lvalue required.
>>     -reg0 <-> reg1[0..10];
>>     -    Can't exchange 32-bit field with 11-bit field.
>>     -inport <-> reg0;
>>     -    Can't exchange string field (inport) with integer field (reg0).
>>     -inport <-> big_string;
>>     -    String fields inport and big_string are incompatible for
>>     exchange.
>>     -ip.proto <-> reg0[0..7];
>>     -    Field ip.proto is not modifiable.
>>     -reg0[0..7] <-> ip.proto;
>>     -    Field ip.proto is not modifiable.
>>     -
>>     -# TTL decrement.
>>     -ip.ttl--;
>>     -    encodes as dec_ttl
>>     -    has prereqs ip
>>     -ip.ttl
>>     -    Syntax error at end of input expecting `--'.
>>     -
>>     -# load balancing.
>>     -ct_lb;
>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>     -    has prereqs ip
>>     -ct_lb();
>>     -    formats as ct_lb;
>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>     -    has prereqs ip
>>     -ct_lb(192.168.1.2:80 <http://192.168.1.2:80>, 192.168.1.3:80
>>     <http://192.168.1.3:80>);
>>     -    encodes as group:1
>>     -    has prereqs ip
>>     -ct_lb(192.168.1.2, 192.168.1.3, );
>>     -    formats as ct_lb(192.168.1.2, 192.168.1.3);
>>     -    encodes as group:2
>>     -    has prereqs ip
>>     -ct_lb(fd0f::2, fd0f::3, );
>>     -    formats as ct_lb(fd0f::2, fd0f::3);
>>     -    encodes as group:3
>>     -    has prereqs ip
>>     -
>>     -ct_lb(192.168.1.2:);
>>     -    Syntax error at `)' expecting port number.
>>     -ct_lb(192.168.1.2:123456 <http://192.168.1.2:123456>);
>>     -    Syntax error at `123456' expecting port number.
>>     -ct_lb(foo);
>>     -    Syntax error at `foo' expecting IP address.
>>     -ct_lb([192.168.1.2]);
>>     -    Syntax error at `192.168.1.2' expecting IPv6 address.
>>     -
>>     -# ct_next
>>     -ct_next;
>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
>>     -    has prereqs ip
>>     -
>>     -# ct_commit
>>     -ct_commit;
>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>     -    has prereqs ip
>>     -ct_commit();
>>     -    formats as ct_commit;
>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>     -    has prereqs ip
>>     -ct_commit(ct_mark=1);
>>     -    formats as ct_commit(ct_mark=0x1);
>>     -    encodes as
>>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
>>     -    has prereqs ip
>>     -ct_commit(ct_mark=1/1);
>>     -    formats as ct_commit(ct_mark=0x1/0x1);
>>     -    encodes as
>>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
>>     -    has prereqs ip
>>     -ct_commit(ct_label=1);
>>     -    formats as ct_commit(ct_label=0x1);
>>     -    encodes as
>>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
>>     -    has prereqs ip
>>     -ct_commit(ct_label=1/1);
>>     -    formats as ct_commit(ct_label=0x1/0x1);
>>     -    encodes as
>>     ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
>>     -    has prereqs ip
>>     -ct_commit(ct_mark=1, ct_label=2);
>>     -    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
>>     -    encodes as
>>     
>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label)) 
>>
>>     -    has prereqs ip
>>     -
>>     -ct_commit(ct_label=0x01020304050607080910111213141516);
>>     -    formats as 
>> ct_commit(ct_label=0x1020304050607080910111213141516);
>>     -    encodes as
>>     
>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label)) 
>>
>>     -    has prereqs ip
>>     -ct_commit(ct_label=0x181716151413121110090807060504030201);
>>     -    formats as
>>     ct_commit(ct_label=0x16151413121110090807060504030201);
>>     -    encodes as
>>     
>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label)) 
>>
>>     -    has prereqs ip
>>     
>> -ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000); 
>>
>>     -    encodes as
>>     
>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label)) 
>>
>>     -    has prereqs ip
>>     -ct_commit(ct_label=18446744073709551615);
>>     -    formats as ct_commit(ct_label=0xffffffffffffffff);
>>     -    encodes as
>>     
>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label)) 
>>
>>     -    has prereqs ip
>>     -ct_commit(ct_label=18446744073709551616);
>>     -    Decimal constants must be less than 2**64.
>>     -
>>     -# ct_dnat
>>     -ct_dnat;
>>     -    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
>>     -    has prereqs ip
>>     -ct_dnat(192.168.1.2);
>>     -    encodes as
>>     ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
>>     -    has prereqs ip
>>     -
>>     -ct_dnat(192.168.1.2, 192.168.1.3);
>>     -    Syntax error at `,' expecting `)'.
>>     -ct_dnat(foo);
>>     -    Syntax error at `foo' expecting IPv4 address.
>>     -ct_dnat(foo, bar);
>>     -    Syntax error at `foo' expecting IPv4 address.
>>     -ct_dnat();
>>     -    Syntax error at `)' expecting IPv4 address.
>>     -
>>     -# ct_snat
>>     -ct_snat;
>>     -    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
>>     -    has prereqs ip
>>     -ct_snat(192.168.1.2);
>>     -    encodes as
>>     ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
>>     -    has prereqs ip
>>     -
>>     -ct_snat(192.168.1.2, 192.168.1.3);
>>     -    Syntax error at `,' expecting `)'.
>>     -ct_snat(foo);
>>     -    Syntax error at `foo' expecting IPv4 address.
>>     -ct_snat(foo, bar);
>>     -    Syntax error at `foo' expecting IPv4 address.
>>     -ct_snat();
>>     -    Syntax error at `)' expecting IPv4 address.
>>     -
>>     -# ct_clear
>>     -ct_clear;
>>     -    encodes as ct_clear
>>     -
>>     -# clone
>>     -clone { ip4.dst = 255.255.255.255; output; }; next;
>>     -    encodes as
>>     clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
>>     -    has prereqs eth.type == 0x800
>>     -
>>     -# arp
>>     -arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip4
>>     -arp { };
>>     -    formats as arp { drop; };
>>     -    encodes as controller(userdata=00.00.00.00.00.00.00.00)
>>     -    has prereqs ip4
>>     -
>>     -# get_arp
>>     -get_arp(outport, ip4.dst);
>>     -    encodes as
>>     
>> push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[] 
>>
>>     -    has prereqs eth.type == 0x800
>>     -get_arp(inport, reg0);
>>     -    encodes as
>>     
>> push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] 
>>
>>     -
>>     -get_arp;
>>     -    Syntax error at `;' expecting `('.
>>     -get_arp();
>>     -    Syntax error at `)' expecting field name.
>>     -get_arp(inport);
>>     -    Syntax error at `)' expecting `,'.
>>     -get_arp(inport ip4.dst);
>>     -    Syntax error at `ip4.dst' expecting `,'.
>>     -get_arp(inport, ip4.dst;
>>     -    Syntax error at `;' expecting `)'.
>>     -get_arp(inport, eth.dst);
>>     -    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is
>>     required.
>>     -get_arp(inport, outport);
>>     -    Cannot use string field outport where numeric field is required.
>>     -get_arp(reg0, ip4.dst);
>>     -    Cannot use numeric field reg0 where string field is required.
>>     -
>>     -# put_arp
>>     -put_arp(inport, arp.spa, arp.sha);
>>     -    encodes as
>>     
>> push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[] 
>>
>>     -    has prereqs eth.type == 0x806 && eth.type == 0x806
>>     -
>>     -# put_dhcp_opts
>>     -reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) 
>>
>>     -reg2[5] =
>>     
>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org 
>>
>>     
>> <http://ovn.org>",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot"); 
>>
>>     -    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router
>>     = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name =
>>     "ovn.org <http://ovn.org>", wpad = "https://example.org",
>>     bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix =
>>     "/tftpboot");
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause) 
>>
>>     -reg0[15] =
>>     
>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1 
>>
>>     
>> <http://30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1>},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5}); 
>>
>>     -    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4,
>>     router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400,
>>     ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8,
>>     7.7.7.7}, classless_static_route = {30.0.0.0/24
>>     <http://30.0.0.0/24>, 10.0.0.4, 40.0.0.0/16 <http://40.0.0.0/16>,
>>     10.0.0.6, 0.0.0.0/0 <http://0.0.0.0/0>, 10.0.0.1}, ethernet_encap
>>     = 1, router_discovery = 0, tftp_server_address = {10.0.0.4,
>>     10.0.0.5});
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause) 
>>
>>     -
>>     -reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>     -    Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
>>     -reg1[0] = put_dhcp_opts();
>>     -    put_dhcp_opts requires offerip to be specified.
>>     -reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
>>     -    Syntax error at `x' expecting DHCPv4 option name.
>>     -reg1[0] = put_dhcp_opts(router = 10.0.0.1);
>>     -    put_dhcp_opts requires offerip to be specified.
>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
>>     -    Syntax error at `"hi"'.
>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
>>     -    Syntax error at `xyzzy' expecting DHCPv4 option name.
>>     -reg1[0] = put_dhcp_opts(offerip="xyzzy");
>>     -    DHCPv4 option offerip requires numeric value.
>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>>     -    DHCPv4 option domain_name requires string value.
>>     -
>>     -# nd_ns
>>     -nd_ns { nd.target = xxreg0; output; };
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>
>>     -    has prereqs ip6
>>     -
>>     -nd_ns { };
>>     -    formats as nd_ns { drop; };
>>     -    encodes as controller(userdata=00.00.00.09.00.00.00.00)
>>     -    has prereqs ip6
>>     -
>>     -# nd_na
>>     -nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc;
>>     outport = inport; inport = ""; /* Allow sending out inport. */
>>     output; };
>>     -    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>     12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>
>>     -    has prereqs nd_ns
>>     -# nd_na_router
>>     -nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>     12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending
>>     out inport. */ output; };
>>     -    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll
>>     = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>
>>     -    has prereqs nd_ns
>>     -
>>     -# get_nd
>>     -get_nd(outport, ip6.dst);
>>     -    encodes as
>>     
>> push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[] 
>>
>>     -    has prereqs eth.type == 0x86dd
>>     -get_nd(inport, xxreg0);
>>     -    encodes as
>>     
>> push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[] 
>>
>>     -get_nd;
>>     -    Syntax error at `;' expecting `('.
>>     -get_nd();
>>     -    Syntax error at `)' expecting field name.
>>     -get_nd(inport);
>>     -    Syntax error at `)' expecting `,'.
>>     -get_nd(inport ip6.dst);
>>     -    Syntax error at `ip6.dst' expecting `,'.
>>     -get_nd(inport, ip6.dst;
>>     -    Syntax error at `;' expecting `)'.
>>     -get_nd(inport, eth.dst);
>>     -    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is
>>     required.
>>     -get_nd(inport, outport);
>>     -    Cannot use string field outport where numeric field is required.
>>     -get_nd(xxreg0, ip6.dst);
>>     -    Cannot use numeric field xxreg0 where string field is required.
>>     -
>>     -# put_nd
>>     -put_nd(inport, nd.target, nd.sll);
>>     -    encodes as
>>     
>> push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[] 
>>
>>     -    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) &&
>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>     eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd &&
>>     ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>     ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>     icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a &&
>>     (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 &&
>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>     eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 ||
>>     eth.type == 0x86dd)
>>     -
>>     -# put_dhcpv6_opts
>>     -reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
>>     00:00:00:00:10:02);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause) 
>>
>>     -reg1[0] = put_dhcpv6_opts();
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>
>>     -reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
>>     -    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1,
>>     ae70::2});
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>
>>     -reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc,
>>     dns_server={ae70::1,ae89::2});
>>     -    formats as reg1[0] = put_dhcpv6_opts(server_id =
>>     12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>
>>     -reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org
>>     <http://ovn.org>");
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause) 
>>
>>     -reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
>>     -    Syntax error at `x' expecting DHCPv6 option name.
>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
>>     -    Syntax error at `"hi"'.
>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
>>     -    Syntax error at `xyzzy' expecting DHCPv6 option name.
>>     -reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
>>     -    DHCPv6 option ia_addr requires numeric value.
>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
>>     -    DHCPv6 option domain_search requires string value.
>>     -
>>     -# set_queue
>>     -set_queue(0);
>>     -    encodes as set_queue:0
>>     -set_queue(61440);
>>     -    encodes as set_queue:61440
>>     -set_queue(65535);
>>     -    Queue ID 65535 for set_queue is not in valid range 0 to 61440.
>>     -
>>     -# dns_lookup
>>     -reg1[0] = dns_lookup();
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>
>>     -    has prereqs udp
>>     -reg1[0] = dns_lookup("foo");
>>     -    dns_lookup doesn't take any parameters
>>     -
>>     -# set_meter
>>     -set_meter(0);
>>     -    Rate 0 for set_meter is not in valid.
>>     -set_meter(1);
>>     -    encodes as meter:1
>>     -set_meter(100, 1000);
>>     -    encodes as meter:2
>>     -set_meter(100, 1000, );
>>     -    Syntax error at `,' expecting `)'.
>>     -set_meter(4294967295, 4294967295);
>>     -    encodes as meter:3
>>     -
>>     -# log
>>     -log(verdict=allow, severity=warning);
>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
>>     -log(name="test1", verdict=drop, severity=info);
>>     -    encodes as
>>     controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
>>     -log(verdict=drop, severity=info, meter="meter1");
>>     -    encodes as
>>     controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
>>     -log(name="test1", verdict=drop, severity=info, meter="meter1");
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4) 
>>
>>     -log(verdict=drop);
>>     -    formats as log(verdict=drop, severity=info);
>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
>>     -log(verdict=bad_verdict, severity=info);
>>     -    Syntax error at `bad_verdict' unknown verdict.
>>     -log(verdict=drop, severity=bad_severity);
>>     -    Syntax error at `bad_severity' unknown severity.
>>     -log(severity=notice);
>>     -    Syntax error at `;' expecting verdict.
>>     -
>>     -# put_nd_ra_opts
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>     = aef0::/64, slla = ae:01:02:03:04:05);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause) 
>>
>>     -    has prereqs ip6
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla =
>>     ae:01:02:03:04:10, mtu = 1450);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause) 
>>
>>     -    has prereqs ip6
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>     ae:01:02:03:04:06, prefix = aef0::/64);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause) 
>>
>>     -    has prereqs ip6
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>     = aef0::/64);
>>     -    slla option not present
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>     ae:01:02:03:04:10);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>
>>     -    has prereqs ip6
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>     ae:01:02:03:04:10);
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>
>>     -    has prereqs ip6
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla =
>>     ae:01:02:03:04:10);
>>     -    prefix option needs to be set when address mode is
>>     slaac/dhcpv6_stateless.
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>     ae:01:02:03:04:10);
>>     -    prefix option needs to be set when address mode is
>>     slaac/dhcpv6_stateless.
>>     -reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix =
>>     aef0::/64, slla = ae:01:02:03:04:10);
>>     -    Syntax error at `dhcpv6_stateless' expecting constant.
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>     = aef0::, slla = ae:01:02:03:04:10);
>>     -    Invalid value for "prefix" option
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla =
>>     ae:01:02:03:04:10);
>>     -    Invalid value for "addr_mode" option
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla
>>     = ae:01:02:03:04:10);
>>     -    IPv6 ND RA option mtu requires numeric value.
>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4,
>>     slla = ae:01:02:03:04:10);
>>     -    Invalid value for "mtu" option
>>     -
>>     -# icmp4
>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip4
>>     -
>>     -icmp4 { };
>>     -    formats as icmp4 { drop; };
>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>     -    has prereqs ip4
>>     -
>>     -# icmp4 with icmp4.frag_mtu
>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>     output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip4
>>     -
>>     -# icmp4_error
>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip4
>>     -
>>     -icmp4_error { };
>>     -    formats as icmp4_error { drop; };
>>     -    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
>>     -    has prereqs ip4
>>     -
>>     -# icmp4_error with icmp4.frag_mtu
>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>     output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip4
>>     -
>>     -icmp4.frag_mtu = 1500;
>>     -    encodes as
>>     controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
>>     -
>>     -# icmp6
>>     -icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs ip6
>>     -
>>     -icmp6 { };
>>     -    formats as icmp6 { drop; };
>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>     -    has prereqs ip6
>>     -
>>     -# tcp_reset
>>     -tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>
>>     -    has prereqs tcp
>>     -
>>     -tcp_reset { };
>>     -    formats as tcp_reset { drop; };
>>     -    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
>>     -    has prereqs tcp
>>     -
>>     -# trigger_event
>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer =
>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>     -    encodes as
>>     
>> controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63) 
>>
>>     -
>>     -# Testing invalid vip results in extra error messages from
>>     socket-util.c
>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>     <http://10.0.0.1:80>", protocol = "sctp", load_balancer =
>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>     -    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer = "bacon");
>>     -    Load balancer 'bacon' is not a UUID
>>     -
>>     -# IGMP
>>     -igmp;
>>     -    encodes as controller(userdata=00.00.00.10.00.00.00.00)
>>     -
>>     -# Contradictionary prerequisites (allowed but not useful):
>>     -ip4.src = ip6.src[0..31];
>>     -    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>     -ip4.src <-> ip6.src[0..31];
>>     -    encodes as
>>     
>> push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[] 
>>
>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>     -
>>     -# check_pkt_larger
>>     -reg0[0] = check_pkt_larger(1500);
>>     -    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
>>     -
>>     -reg0 = check_pkt_larger(1500);
>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>     required.
>>     -
>>     -reg0 = check_pkt_larger(foo);
>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>     required.
>>     -
>>     -reg0[0] = check_pkt_larger(foo);
>>     -    Syntax error at `foo' expecting `;'.
>>     -
>>     -# Miscellaneous negative tests.
>>     -;
>>     -    Syntax error at `;'.
>>     -xyzzy;
>>     -    Syntax error at `xyzzy' expecting action.
>>     -next; 123;
>>     -    Syntax error at `123'.
>>     -next; xyzzy;
>>     -    Syntax error at `xyzzy' expecting action.
>>     -next
>>     -    Syntax error at end of input expecting `;'.
>>     -]])
>>     -sed '/^[[      ]]/d' test-cases.txt > input.txt
>>     -cp test-cases.txt expout
>>     -AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], 
>> [expout])
>>     -AT_CLEANUP
>>     -
>>     -AT_BANNER([OVN end-to-end tests])
>>     -
>>     -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
>>     -AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
>>     -AT_KEYWORDS([ovnarp])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Create hypervisors hv[123].
>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>     -# Add all of the vifs to a single logical switch lsw0.
>>     -# Turn on port security on all the vifs except vif[123]1.
>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2 3; do
>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>     vif$i$j external-ids:iface-id=lp$i$j
>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>     -        if test $j = 1; then
>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>     -        else
>>     -            if test $j = 3; then
>>     -                ip_addrs="192.168.0.$i$j
>>     fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
>>     -            else
>>     -                ip_addrs="192.168.0.$i$j"
>>     -            fi
>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>     "f0:00:00:00:00:$i$j $ip_addrs"
>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>     f0:00:00:00:00:$i$j
>>     -        fi
>>     -    done
>>     -done
>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>     inport == "lp11"' drop
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>     outport == "lp33"' drop
>>     -ovn-nbctl create Address_Set name=set1
>>     
>> addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\" 
>>
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>     eth.src == $set1 && outport == "lp33"' drop
>>     -
>>     -get_lsp_uuid () {
>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>     -}
>>     -
>>     -ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid
>>     lp22`,`get_lsp_uuid lp33`
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 &&
>>     outport == @pg1' drop
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Make sure there is no attempt to adding duplicated flows by
>>     ovn-controller
>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv${1%?}
>>     -}
>>     -
>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>     for vif11.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>     -    local
>>     
>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -    hv=`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>     -
>>     -    if test X$reply_ha = X; then
>>     -        # Expect to receive the broadcast ARP on the other
>>     logical switch ports
>>     -        # if no reply is expected.
>>     -        local i j
>>     -        for i in 1 2 3; do
>>     -            for j in 1 2 3; do
>>     -                if test $i$j != $inport; then
>>     -                    echo $request >> $i$j.expected
>>     -                fi
>>     -            done
>>     -        done
>>     -    else
>>     -        # Expect to receive the reply, if any.
>>     -        local
>>     
>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>>     -        echo $reply >> $inport.expected
>>     -    fi
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast packets are delivered to exactly one logical switch 
>> port
>>     -#    (except that packets destined to their input ports are 
>> dropped).
>>     -#
>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>     ports
>>     -#    except the input port.
>>     -#
>>     -# 3. When port security is turned on, the switch drops packets
>>     from the wrong
>>     -#    MAC address.
>>     -#
>>     -# 4. The switch drops all packets with a VLAN tag.
>>     -#
>>     -# 5. The switch drops all packets with a multicast source
>>     address.  (This only
>>     -#    affects behavior when port security is turned off, since
>>     otherwise port
>>     -#    security would drop the packet anyway.)
>>     -#
>>     -# 6. The switch delivers packets with an unknown destination to
>>     logical
>>     -#    switch ports with "unknown" among their MAC addresses (and port
>>     -#    security disabled).
>>     -#
>>     -# 7. The switch drops unicast packets that violate an ACL.
>>     -#
>>     -# 8. The switch drops multicast and broadcast packets that
>>     violate an ACL.
>>     -#
>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>     except for
>>     -#    requests from a port for the port's own IP.
>>     -#
>>     -# 10. No response to ARP requests for unknown IPs.
>>     -
>>     -for is in 1 2 3; do
>>     -    for js in 1 2 3; do
>>     -        s=$is$js
>>     -        bcast=
>>     -        unknown=
>>     -        bacl2=
>>     -        bacl3=
>>     -        for id in 1 2 3; do
>>     -            for jd in 1 2 3; do
>>     -                d=$id$jd
>>     -
>>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>     $unicast     #1
>>     -
>>     -                if test $d != $s && test $js = 1; then
>>     -                    impersonate=$d
>>     -                else
>>     -                    impersonate=
>>     -                fi
>>     -                test_packet $s f000000000$d f00000000055 55$d
>>     $impersonate #3
>>     -
>>     -                if test $d != $s && test $s != 11; then acl2=$d;
>>     else acl2=; fi
>>     -                if test $d != $s && test $d != 33; then acl3=$d;
>>     else acl3=; fi
>>     -                if test $d = $s || (test $js = 1 && test $d =
>>     33); then
>>     -                    # Source of 11, 21, or 31 and dest of 33
>>     should be dropped
>>     -                    # due to the 4th ACL that uses 
>> address_set(set1).
>>     -                    acl4=
>>     -                else
>>     -                    acl4=$d
>>     -                fi
>>     -                if test $d = $s || test $d = 22 || test $d = 33; 
>> then
>>     -                    # dest of 22 and 33 should be dropped
>>     -                    # due to the 5th ACL that uses port_group(pg1).
>>     -                    acl5=
>>     -                else
>>     -                    acl5=$d
>>     -                fi
>>     -                test_packet $s f000000000$d f000000000$s 1234
>>         #7, acl1
>>     -                test_packet $s f000000000$d f000000000$s 1235
>>     $acl2  #7, acl2
>>     -                test_packet $s f000000000$d f000000000$s 1236
>>     $acl3  #7, acl3
>>     -                test_packet $s f000000000$d f000000000$s 1237
>>     $acl4  #7, acl4
>>     -                test_packet $s f000000000$d f000000000$s 1238
>>     $acl5  #7, acl5
>>     -
>>     -                test_packet $s f000000000$d f00000000055
>>     810000091234      #4
>>     -                test_packet $s f000000000$d 0100000000$s $s$d
>>               #5
>>     -
>>     -                if test $d != $s && test $jd = 1; then
>>     -                    unknown="$unknown $d"
>>     -                fi
>>     -                bcast="$bcast $unicast"
>>     -                bacl2="$bacl2 $acl2"
>>     -                bacl3="$bacl3 $acl3"
>>     -
>>     -                sip=`ip_to_hex 192 168 0 $is$js`
>>     -                tip=`ip_to_hex 192 168 0 $id$jd`
>>     -                tip_unknown=`ip_to_hex 11 11 11 11`
>>     -                if test $d != $s; then
>>     -                    reply_ha=f000000000$d
>>     -                else
>>     -                    reply_ha=
>>     -                fi
>>     -                test_arp $s f000000000$s $sip $tip $reply_ha
>>              #9
>>     -                test_arp $s f000000000$s $sip $tip_unknown
>>              #10
>>     -
>>     -                if test $jd = 3; then
>>     -                    # lsp[123]3 has an additional ip
>>     192.169.0.[123]3.
>>     -                    tip=`ip_to_hex 192 169 0 $id$jd`
>>     -                    test_arp $s f000000000$s $sip $tip $reply_ha
>>              #9
>>     -                fi
>>     -            done
>>     -        done
>>     -
>>     -        # Broadcast and multicast.
>>     -        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast
>>              #2
>>     -        test_packet $s 010000000000 f000000000$s ${s}ff $bcast
>>              #2
>>     -        if test $js = 1; then
>>     -            bcast_impersonate=$bcast
>>     -        else
>>     -            bcast_impersonate=
>>     -        fi
>>     -        test_packet $s 010000000000 f00000000044 44ff
>>     $bcast_impersonate   #3
>>     -
>>     -        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown
>>              #6
>>     -
>>     -        test_packet $s ffffffffffff f000000000$s 1234
>>     #8, acl1
>>     -        test_packet $s ffffffffffff f000000000$s 1235 $bacl2
>>        #8, acl2
>>     -        test_packet $s ffffffffffff f000000000$s 1236 $bacl3
>>        #8, acl3
>>     -        test_packet $s 010000000000 f000000000$s 1234
>>     #8, acl1
>>     -        test_packet $s 010000000000 f000000000$s 1235 $bacl2
>>        #8, acl2
>>     -        test_packet $s 010000000000 f000000000$s 1236 $bacl3
>>        #8, acl3
>>     -    done
>>     -done
>>     -
>>     -# set address for lp13 with invalid characters.
>>     -# lp13 should be configured with only 192.168.0.13.
>>     -ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13
>>     invalid 192.169.0.13"
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -sip=`ip_to_hex 192 168 0 11`
>>     -tip=`ip_to_hex 192 168 0 13`
>>     -test_arp 11 f00000000011  $sip $tip f00000000013
>>     -
>>     -tip=`ip_to_hex 192 169 0 13`
>>     -#arp request for 192.169.0.13 should be flooded
>>     -test_arp 11 f00000000011  $sip $tip
>>     -
>>     -# dump information and flows with counters
>>     -ovn-sbctl dump-flows -- list multicast_group
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv3 dump ------"
>>     -as hv3 ovs-vsctl show
>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# 2 hypervisors, one logical switch, 2 logical ports per hypervisor
>>     -# logical ports bound to chassis encap-ip.
>>     -AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
>>     -AT_KEYWORDS([ovnarp])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Create hypervisors hv[12].
>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2; do
>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>     vif$i$j external-ids:iface-id=lp$i$j
>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>     -        ip_addrs="192.168.0.$i$j"
>>     -        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
>>     $ip_addrs"
>>     -        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j
>>     f0:00:00:00:00:$i$j
>>     -    done
>>     -done
>>     -
>>     -get_lsp_uuid () {
>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>     -}
>>     -
>>     -# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just
>>     do it
>>     -# explictly
>>     -
>>     -# For Chassis hv1
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp11], [0], [dnl
>>     -encap               : [[]]
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp12], [0], [dnl
>>     -encap               : [[]]
>>     -])
>>     -
>>     -# For Chassis hv2
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp21], [0], [dnl
>>     -encap               : [[]]
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp22], [0], [dnl
>>     -encap               : [[]]
>>     -])
>>     -
>>     -# Bind the ports to the encap-ip
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        as hv$i
>>     -        ovs-vsctl set Interface vif$i$j
>>     external-ids:encap-ip=192.168.0.$i
>>     -    done
>>     -done
>>     -
>>     -sleep 1
>>     -
>>     -# dump port bindings; since we have vxlan and geneve tunnels, we
>>     expect the
>>     -# ports to be bound to geneve tunnels.
>>     -
>>     -# For Chassis 1
>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>     encap chassis_name=hv1 type=geneve ip=192.168.0.1`
>>     -
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp11], [0], [dnl
>>     -encap               : ${encap_rec}
>>     -])
>>     -
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp12], [0], [dnl
>>     -encap               : ${encap_rec}
>>     -])
>>     -
>>     -# For Chassis 2
>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>     encap chassis_name=hv2 type=geneve ip=192.168.0.2`
>>     -
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp21], [0], [dnl
>>     -encap               : ${encap_rec}
>>     -])
>>     -
>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>     lp22], [0], [dnl
>>     -encap               : ${encap_rec}
>>     -])
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Make sure there is no attempt to adding duplicated flows by
>>     ovn-controller
>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv${1%?}
>>     -}
>>     -
>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>     for vif11.
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast packets are delivered to exactly one logical switch 
>> port
>>     -#    (except that packets destined to their input ports are 
>> dropped).
>>     -
>>     -for is in 1 2; do
>>     -    for js in 1 2; do
>>     -        s=$is$js
>>     -        bcast=
>>     -        unknown=
>>     -        bacl2=
>>     -        bacl3=
>>     -        for id in 1 2 3; do
>>     -            for jd in 1 2 3; do
>>     -                d=$id$jd
>>     -
>>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>     $unicast     #1
>>     -            done
>>     -        done
>>     -
>>     -    done
>>     -done
>>     -
>>     -# dump information and flows with counters
>>     -ovn-sbctl dump-flows -- list multicast_group
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv3 dump ------"
>>     -as hv3 ovs-vsctl show
>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Create a logical switch and some logical ports.
>>     -# Turn on port security on all lports except ls1.
>>     -# Make ls1 a destination for unknown MACs.
>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>     -ovn-nbctl ls-add lsw0
>>     -ovn-sbctl chassis-add hv0 geneve 127.0.0.1
>>     -for i in 1 2 3; do
>>     -    ovn-nbctl lsp-add lsw0 lp$i
>>     -done
>>     -ovn-nbctl --wait=sb sync
>>     -for i in 1 2 3; do
>>     -    ovn-sbctl lsp-bind lp$i hv0
>>     -    if test $i = 1; then
>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>     192.168.0.$i" unknown
>>     -    else
>>     -        if test $i = 3; then
>>     -           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64
>>     192.169.0.$i"
>>     -        else
>>     -           ip_addrs="192.168.0.$i"
>>     -        fi
>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>     $ip_addrs"
>>     -        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
>>     -    fi
>>     -done
>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>     inport == "lp1"' drop
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>     outport == "lp3"' drop
>>     -ovn-nbctl create Address_Set name=set1
>>     addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>     eth.src == $set1 && outport == "lp3"' drop
>>     -
>>     -ovn-nbctl --wait=sb sync
>>     -on_exit 'kill `cat ovn-trace.pid`'
>>     -ovn-trace --detach --pidfile --no-chdir
>>     -
>>     -# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>     for vif11.
>>     -test_packet() {
>>     -    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
>>     -    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst &&
>>     eth.src==$eth_src"
>>     -    while :; do
>>     -        case $1 in # (
>>     -            -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; # (
>>     -            -eth) uflow="$uflow && eth.type == 0x$2"; shift;
>>     shift ;; # (
>>     -            *) break ;;
>>     -        esac
>>     -    done
>>     -    for outport; do
>>     -        echo "output(\"lp$outport\");"
>>     -    done > expout
>>     -
>>     -    AT_CAPTURE_FILE([trace])
>>     -    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" |
>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>     -}
>>     -
>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>     -
>>     -    local request="inport == \"lp$inport\"
>>     -                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src == 
>> $sha
>>     -                   && arp.op == 1 && arp.sha == $sha && arp.spa
>>     == $spa
>>     -                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa ==
>>     $tpa"
>>     -
>>     -    if test -z "$reply_ha"; then
>>     -        reply=
>>     -        local i
>>     -        for i in 1 2 3; do
>>     -            if test $i != $inport; then
>>     -                reply="${reply}output(\"lp$i\");
>>     -"
>>     -            fi
>>     -        done
>>     -    else
>>     -        reply="\
>>     -eth.dst = $sha;
>>     -eth.src = $reply_ha;
>>     -arp.op = 2;
>>     -arp.tha = $sha;
>>     -arp.sha = $reply_ha;
>>     -arp.tpa = $spa;
>>     -arp.spa = $tpa;
>>     -output(\"lp$inport\");
>>     -"
>>     -    fi
>>     -
>>     -    AT_CAPTURE_FILE([trace])
>>     -    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0
>>     "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
>>     -}
>>     -
>>     -# Send packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast packets are delivered to exactly one logical switch 
>> port
>>     -#    (except that packets destined to their input ports are 
>> dropped).
>>     -#
>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>     ports
>>     -#    except the input port.
>>     -#
>>     -# 3. When port security is turned on, the switch drops packets
>>     from the wrong
>>     -#    MAC address.
>>     -#
>>     -# 4. The switch drops all packets with a VLAN tag.
>>     -#
>>     -# 5. The switch drops all packets with a multicast source
>>     address.  (This only
>>     -#    affects behavior when port security is turned off, since
>>     otherwise port
>>     -#    security would drop the packet anyway.)
>>     -#
>>     -# 6. The switch delivers packets with an unknown destination to
>>     logical
>>     -#    switch ports with "unknown" among their MAC addresses (and port
>>     -#    security disabled).
>>     -#
>>     -# 7. The switch drops unicast packets that violate an ACL.
>>     -#
>>     -# 8. The switch drops multicast and broadcast packets that
>>     violate an ACL.
>>     -#
>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>     except for
>>     -#    requests from a port for the port's own IP.
>>     -#
>>     -# 10. No response to ARP requests for unknown IPs.
>>     -
>>     -for s in 1 2 3; do
>>     -    bcast=
>>     -    unknown=
>>     -    bacl2=
>>     -    bacl3=
>>     -    for d in 1 2 3; do
>>     -        echo
>>     -        echo "lp$s -> lp$d"
>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s
>>     $unicast      #1
>>     -
>>     -        if test $d != $s && test $s = 1; then
>>     -            impersonate=$d
>>     -        else
>>     -            impersonate=
>>     -        fi
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>     $impersonate   #3
>>     -
>>     -        if test $d != $s && test $s != 1; then acl2=$d; else
>>     acl2=; fi
>>     -        if test $d != $s && test $d != 3; then acl3=$d; else
>>     acl3=; fi
>>     -        if test $d = $s || ( (test $s = 1 || test $s = 2) && test
>>     $d = 3); then
>>     -            # Source of 1 or 2 and dest of 3 should be dropped
>>     -            # due to the 4th ACL that uses address_set(set1).
>>     -            acl4=
>>     -        else
>>     -            acl4=$d
>>     -        fi
>>     -
>>     -        #7, acl1 to acl4:
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>     1234
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>     1235 $acl2
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>     1236 $acl3
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>     1237 $acl4
>>     -
>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>     -vlan          #4
>>     -        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s
>>              #5
>>     -
>>     -        if test $d != $s && test $d = 1; then
>>     -            unknown="$unknown $d"
>>     -        fi
>>     -        bcast="$bcast $unicast"
>>     -        bacl2="$bacl2 $acl2"
>>     -        bacl3="$bacl3 $acl3"
>>     -
>>     -        sip=192.168.0.$s
>>     -        tip=192.168.0.$d
>>     -        tip_unknown=11.11.11.11
>>     -        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else
>>     reply_ha=; fi
>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>              #9
>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown
>>            #10
>>     -
>>     -        if test $d = 3; then
>>     -            # lp3 has an additional ip 192.169.0.[123]3.
>>     -            tip=192.169.0.$d
>>     -            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>              #9
>>     -        fi
>>     -    done
>>     -
>>     -    # Broadcast and multicast.
>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast
>>              #2
>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast
>>              #2
>>     -    if test $s = 1; then
>>     -       bcast_impersonate=$bcast
>>     -    else
>>     -       bcast_impersonate=
>>     -    fi
>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44
>>     $bcast_impersonate  #3
>>     -
>>     -    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown
>>              #6
>>     -
>>     -    #8, acl1 to acl3:
>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235
>>     $bacl2
>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236
>>     $bacl3
>>     -
>>     -    #8, acl1 to acl3:
>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235
>>     $bacl2
>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236
>>     $bacl3
>>     -done
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# 2 hypervisors, 4 logical ports per HV
>>     -# 2 locally attached networks (one flat, one vlan tagged over
>>     same device)
>>     -# 2 ports per HV on each network
>>     -AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# In this test cases we create 3 switches, all connected to same
>>     -# physical network (through br-phys on each HV). Each switch has
>>     -# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>     -# lp23 means VIF 3 on hv2.
>>     -#
>>     -# Each switch's VLAN tag and their logical switch ports are:
>>     -#   - ls1:
>>     -#       - untagged
>>     -#       - ports: lp11, lp12, lp21, lp22
>>     -#
>>     -#   - ls2:
>>     -#       - tagged with VLAN 101
>>     -#       - ports: lp13, lp14, lp23, lp24
>>     -#   - ls3:
>>     -#       - untagged
>>     -#       - ports: lp15, lp25
>>     -#
>>     -# Note: a localnet port is created for each switch to connect to
>>     -# physical network.
>>     -
>>     -for i in 1 2 3; do
>>     -    ls_name=ls$i
>>     -    ovn-nbctl ls-add $ls_name
>>     -    ln_port_name=ln$i
>>     -    if test $i -eq 2; then
>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>     -    else
>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name
>>     -    fi
>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>     -done
>>     -
>>     -# lsp_to_ls LSP
>>     -#
>>     -# Prints the name of the logical switch that contains LSP.
>>     -lsp_to_ls () {
>>     -    case $1 in dnl (
>>     -        lp?[[12]]) echo ls1 ;; dnl (
>>     -        lp?[[34]]) echo ls2 ;; dnl (
>>     -        lp?5) echo ls3 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2 3 4 5; do
>>     -        ovs-vsctl add-port br-int vif$i$j -- \
>>     -            set Interface vif$i$j external-ids:iface-id=lp$i$j \
>>     - options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>     - options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>     -                                  ofport-request=$i$j
>>     -
>>     -        lsp_name=lp$i$j
>>     -        ls_name=$(lsp_to_ls $lsp_name)
>>     -
>>     -        ovn-nbctl lsp-add $ls_name $lsp_name
>>     -        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
>>     -        ovn-nbctl lsp-set-port-security $lsp_name 
>> f0:00:00:00:00:$i$j
>>     -
>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` =
>>     xup])
>>     -    done
>>     -done
>>     -ovn-nbctl --wait=sb sync
>>     -ovn-sbctl dump-flows
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -# XXX This is now the 3rd copy of these functions in this file ...
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv${1%?}
>>     -}
>>     -#
>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is
>>     specified as
>>     -# logical switch port numbers, e.g. 11 for vif11.
>>     -#
>>     -# EOUT is the end-to-end output port, that is, where the packet
>>     will end up
>>     -# after possibly bouncing through one or more localnet ports.
>>     LOUT is the
>>     -# logical output port, which might be a localnet port, as seen by
>>     ovn-trace
>>     -# (which doesn't know what localnet ports are connected to and
>>     therefore can't
>>     -# figure out the end-to-end answer).
>>     -for i in 1 2; do
>>     -    for j in 1 2 3 4 5; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
>>     -    echo "$@"
>>     -
>>     -    # First try tracing the packet.
>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>     eth.src==$src && eth.type==0x$eth"
>>     -    if test $lout != drop; then
>>     -        echo "output(\"$lout\");"
>>     -    fi > expout
>>     -    AT_CAPTURE_FILE([trace])
>>     -    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" |
>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>     -
>>     -    # Then actually send a packet, for an end-to-end test.
>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>     -    hv=`vif_to_hv $inport`
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    if test $eout != drop; then
>>     -        echo $packet >> ${eout#lp}.expected
>>     -    fi
>>     -}
>>     -
>>     -# lp11 and lp21 are on the same network (phys, untagged)
>>     -# and on different hypervisors
>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>     -
>>     -# lp11 and lp12 are on the same network (phys, untagged)
>>     -# and on the same hypervisor
>>     -test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
>>     -test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
>>     -
>>     -# lp13 and lp23 are on the same network (phys, VLAN 101)
>>     -# and on different hypervisors
>>     -test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
>>     -test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
>>     -
>>     -# lp13 and lp14 are on the same network (phys, VLAN 101)
>>     -# and on the same hypervisor
>>     -test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
>>     -test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
>>     -
>>     -# lp11 and lp15 are on the same network (phys, untagged),
>>     -# same hypervisor, and on different switches
>>     -test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
>>     -test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
>>     -
>>     -# lp11 and lp25 are on the same network (phys, untagged),
>>     -# different hypervisors, and on different switches
>>     -test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
>>     -test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
>>     -
>>     -# Ports that should not be able to communicate
>>     -test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
>>     -test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
>>     -test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
>>     -test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
>>     -test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
>>     -test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
>>     -test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
>>     -test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
>>     -
>>     -# Dump a bunch of info helpful for debugging if there's a failure.
>>     -
>>     -echo "------ OVN dump ------"
>>     -ovn-nbctl show
>>     -ovn-sbctl show
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2; do
>>     -    for j in 1 2 3 4 5; do
>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
>>     -AT_KEYWORDS([vtep])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Configure the Northbound database
>>     -ovn-nbctl ls-add lsw0
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp-vtep
>>     -ovn-nbctl lsp-set-type lp-vtep vtep
>>     -ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep
>>     vtep-logical-switch=lsw0
>>     -ovn-nbctl lsp-set-addresses lp-vtep unknown
>>     -
>>     -# lpr, lr and lrp1 are used for the ARP request handling test only.
>>     -ovn-nbctl lsp-add lsw0 lpr
>>     -ovn-nbctl lr-add lr
>>     -ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl set Logical_Switch_Port lpr type=router \
>>     -                             options:router-port=lrp1 \
>>     -    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
>>     -
>>     -
>>     -net_add n1               # Network to connect hv1, hv2, and vtep
>>     -net_add n2               # Network to connect vtep and hv3
>>     -
>>     -# Create hypervisor hv1 connected to n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>     -
>>     -# Create hypervisor hv2 connected to n1
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>     -
>>     -
>>     -# Start the vtep emulator with a leg in both networks
>>     -sim_add vtep
>>     -as vtep
>>     -
>>     -ovsdb-tool create "$ovs_base"/vtep/vtep.db
>>     "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
>>     -ovs-appctl -t ovsdb-server ovsdb-server/add-db
>>     "$ovs_base"/vtep/vtep.db
>>     -
>>     -ovs-vsctl add-br br-phys
>>     -net_attach n1 br-phys
>>     -
>>     -mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
>>     -arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
>>     -ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24
>>     <http://192.168.0.3/24> >/dev/null || return 1
>>     -ovs-appctl ovs/route/add 192.168.0.3/24 <http://192.168.0.3/24>
>>     br-phys >/dev/null || return 1
>>     -
>>     -ovs-vsctl add-br br-vtep
>>     -net_attach n2 br-vtep
>>     -
>>     -vtep-ctl add-ps br-vtep
>>     -vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
>>     -vtep-ctl add-ls lsw0
>>     -
>>     -start_daemon ovs-vtep br-vtep
>>     -start_daemon ovn-controller-vtep
>>     --vtep-db=unix:"$ovs_base"/vtep/db.sock
>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -
>>     -OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
>>     -
>>     -OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode
>>     lsw0 |
>>     -               grep -- source`"])
>>     -# It takes more time for the update to be processed by ovs-vtep.
>>     -sleep 1
>>     -
>>     -# Add hv3 on the other side of the vtep
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -net_attach n2 br-phys
>>     -
>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>     ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 1
>>     for vif1.
>>     -for i in 1 2 3; do
>>     -    : > $i.expected
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>     -    hv=hv$inport
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# Send packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast packets are delivered to exactly one logical switch 
>> port
>>     -#    (except that packets destined to their input ports are 
>> dropped).
>>     -#
>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>     ports
>>     -#    except the input port.
>>     -#
>>     -# 3. The switch delivers packets with an unknown destination to
>>     logical
>>     -#    switch ports with "unknown" among their MAC addresses (and port
>>     -#    security disabled).
>>     -for s in 1 2 3; do
>>     -    bcast=
>>     -    unknown=
>>     -    for d in 1 2 3; do
>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>     $unicast       #1
>>     -
>>     -        # The vtep (vif3) is the only one configured for "unknown"
>>     -        if test $d != $s && test $d = 3; then
>>     -            unknown="$unknown $d"
>>     -        fi
>>     -        bcast="$bcast $unicast"
>>     -    done
>>     -
>>     -    # Broadcast and multicast.
>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>            #2
>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>            #2
>>     -
>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>            #3
>>     -done
>>     -
>>     -# ARP request should not be responded to by logical switch router
>>     -# type arp responder on HV1 and HV2 and should reach directly to
>>     -# vif1 and vif2
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -sha=f00000000003
>>     -spa=`ip_to_hex 192 168 1 2`
>>     -tpa=`ip_to_hex 192 168 1 1`
>>     
>> -request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -as hv3 ovs-appctl netdev-dummy/receive vif3 $request
>>     -echo $request >> 1.expected
>>     -echo $request >> 2.expected
>>     -
>>     -# dump information with counters
>>     -echo "------ OVN dump ------"
>>     -ovn-nbctl show
>>     -ovn-sbctl show
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv3 dump ------"
>>     -as hv3 ovs-vsctl show
>>     -# note: hv3 has no logical port bind, thus it should not have br-int
>>     -AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
>>     -[ovs-ofctl: br-int is not a bridge or a socket
>>     -])
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>     -done
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1],[hv2],[vtep])
>>     -OVN_CLEANUP_VSWITCH([hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# Similar test to "hardware GW"
>>     -AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Configure the Northbound database
>>     -ovn-nbctl ls-add lsw0
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp-gw
>>     -ovn-nbctl lsp-set-type lp-gw l2gateway
>>     -ovn-nbctl lsp-set-options lp-gw network_name=physnet1
>>     l2gateway-chassis=hv_gw
>>     -ovn-nbctl lsp-set-addresses lp-gw unknown
>>     -
>>     -net_add n1               # Network to connect hv1, hv2, and gw
>>     -net_add n2               # Network to connect gw and hv3
>>     -
>>     -# Create hypervisor hv1 connected to n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>     -
>>     -# Create hypervisor hv2 connected to n1
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>     -
>>     -# Create hypervisor hv_gw connected to n1 and n2
>>     -# connect br-phys bridge to n1; connect hv-gw bridge to n2
>>     -sim_add hv_gw
>>     -as hv_gw
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl add-br br-phys2
>>     -net_attach n2 br-phys2
>>     -ovs-vsctl set open .
>>     external_ids:ovn-bridge-mappings="physnet1:br-phys2"
>>     -
>>     -# Add hv3 on the other side of the GW
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -net_attach n2 br-phys
>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>     ofport-request=1
>>     -
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
>>     -for i in 1 2 3; do
>>     -    : > $i.expected
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>     -    hv=hv$inport
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# Send packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast packets are delivered to exactly one lport (except
>>     that packets
>>     -#    destined to their input ports are dropped).
>>     -#
>>     -# 2. Broadcast and multicast are delivered to all lports except
>>     the input port.
>>     -#
>>     -# 3. The lswitch delivers packets with an unknown destination to
>>     lports with
>>     -#    "unknown" among their MAC addresses (and port security
>>     disabled).
>>     -for s in 1 2 3 ; do
>>     -    bcast=
>>     -    unknown=
>>     -    for d in 1 2 3 ; do
>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>     $unicast       #1
>>     -
>>     -        # The vtep (vif3) is the only one configured for "unknown"
>>     -        if test $d != $s && test $d = 3; then
>>     -            unknown="$unknown $d"
>>     -        fi
>>     -        bcast="$bcast $unicast"
>>     -    done
>>     -
>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>            #2
>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>            #3
>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>            #4
>>     -done
>>     -
>>     -echo "------ ovn-nbctl show ------"
>>     -ovn-nbctl show
>>     -echo "------ ovn-sbctl show ------"
>>     -ovn-sbctl show
>>     -
>>     -echo "------ hv1 ------"
>>     -as hv1 ovs-vsctl show
>>     -echo "------ hv1 br-int ------"
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -echo "------ hv1 br-phys ------"
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>     -
>>     -echo "------ hv2 ------"
>>     -as hv2 ovs-vsctl show
>>     -echo "------ hv2 br-int ------"
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -echo "------ hv2 br-phys ------"
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>     -
>>     -echo "------ hv_gw ------"
>>     -as hv_gw ovs-vsctl show
>>     -echo "------ hv_gw br-phys ------"
>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>     -echo "------ hv_gw br-phys2 ------"
>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
>>     -
>>     -echo "------ hv3 ------"
>>     -as hv3 ovs-vsctl show
>>     -echo "------ hv3 br-phys ------"
>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>     -done
>>     -AT_CLEANUP
>>     -
>>     -# 3 hypervisors, 3 logical switches with 3 logical ports each, 1
>>     logical router
>>     -AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -#
>>     -# Three logical switches ls1, ls2, ls3.
>>     -# One logical router lr0 connected to ls[123],
>>     -# with nine subnets, three per logical switch:
>>     -#
>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>> <http://192.168.11.0/24>
>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>> <http://192.168.12.0/24>
>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>> <http://192.168.13.0/24>
>>     -#    ...
>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>> <http://192.168.33.0/24>
>>     -#
>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>     first two
>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>     -for i in 1 2 3; do
>>     -    ovn-nbctl ls-add ls$i
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            # Add "unknown" to MAC addresses for lp?11, so
>>     packets for
>>     -            # MAC-IP bindings discovered via ARP later have
>>     somewhere to go.
>>     -            if test $j$k = 11; then unknown=unknown; else
>>     unknown=; fi
>>     -
>>     -            ovn-nbctl \
>>     -                -- lsp-add ls$i lp$i$j$k \
>>     -                -- lsp-set-addresses lp$i$j$k \
>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>     192.168.$i$j.254/24
>>     -        ovn-nbctl \
>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>     type=router \
>>     -                             options:router-port=lrp$i$j \
>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl set Logical_Switch_Port lrp33-attachment \
>>     -    addresses='"00:00:00:00:ff:33 192.168.33.254"'
>>     -
>>     -# Physical network:
>>     -#
>>     -# Three hypervisors hv[123].
>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>     lp?13 on hv3.
>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>     on hv3.
>>     -# lp?3[123] all on hv3.
>>     -
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    case $1 in dnl (
>>     -        ?11) echo 1 ;; dnl (
>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>     -    esac
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its
>>     logical router
>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>     -vif_to_lrp() {
>>     -    echo ${1%?}
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its logical
>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>     -vif_to_ls() {
>>     -    echo ${1%??}
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -done
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            hv=`vif_to_hv $i$j$k`
>>     -                as hv$hv ovs-vsctl \
>>     -                -- add-port br-int vif$i$j$k \
>>     -                -- set Interface vif$i$j$k \
>>     -                    external-ids:iface-id=lp$i$j$k \
>>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>     -                    ofport-request=$i$j$k
>>     -        done
>>     -    done
>>     -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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>     for vif123.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            : > $i$j$k.expected
>>     -        done
>>     -    done
>>     -done
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    in_ls=`vif_to_ls $inport`
>>     -    in_lrp=`vif_to_lrp $inport`
>>     -    for outport; do
>>     -        out_ls=`vif_to_ls $outport`
>>     -        if test $in_ls = $out_ls; then
>>     -            # Ports on the same logical switch receive exactly
>>     the same packet.
>>     -            echo $packet
>>     -        else
>>     -            # Routing decrements TTL and updates source and dest MAC
>>     -            # (and checksum).
>>     -            out_lrp=`vif_to_lrp $outport`
>>     -            echo
>>     
>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>
>>     -        fi >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>     -    local
>>     
>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>     -    as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
>>     -
>>     -    # Expect to receive the broadcast ARP on the other logical
>>     switch ports if
>>     -    # IP address is not configured to the switch patch port.
>>     -    local i=`vif_to_ls $inport`
>>     -    local j k
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            # 192.168.33.254 is configured to the switch patch
>>     port for lrp33,
>>     -            # so no ARP flooding expected for it.
>>     -            if test $i$j$k != $inport && test $tpa != `ip_to_hex
>>     192 168 33 254`; then
>>     -                echo $request >> $i$j$k.expected
>>     -            fi
>>     -        done
>>     -    done
>>     -
>>     -    # Expect to receive the reply, if any.
>>     -    if test X$reply_ha != X; then
>>     -        lrp=`vif_to_lrp $inport`
>>     -        local
>>     
>> reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>
>>     -        echo $reply >> $inport.expected
>>     -    fi
>>     -}
>>     -
>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>     -as hv1 ovn-sbctl list port_binding
>>     -as hv1 ovn-sbctl list datapath_binding
>>     -as hv1 ovn-sbctl dump-flows
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Send IP packets between all pairs of source and destination ports:
>>     -#
>>     -# 1. Unicast IP packets are delivered to exactly one logical
>>     switch port
>>     -#    (except that packets destined to their input ports are 
>> dropped).
>>     -#
>>     -# 2. Broadcast IP packets are delivered to all logical switch ports
>>     -#    except the input port.
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -for is in 1 2 3; do
>>     -  for js in 1 2 3; do
>>     -    for ks in 1 2 3; do
>>     -      bcast=
>>     -      s=$is$js$ks
>>     -      smac=f00000000$s
>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>     -      for id in 1 2 3; do
>>     -          for jd in 1 2 3; do
>>     -              for kd in 1 2 3; do
>>     -                d=$id$jd$kd
>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>     -                if test $is = $id; then dmac=f00000000$d; else
>>     dmac=00000000ff$is$js; fi
>>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>>     -
>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>     -
>>     -                if test $id = $is && test $d != $s; then
>>     bcast="$bcast $d"; fi
>>     -              done
>>     -          done
>>     -        done
>>     -      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
>>     -      done
>>     -  done
>>     -done
>>     -
>>     -: > mac_bindings.expected
>>     -
>>     -# 3. Send an IP packet from every logical port to every other 
>> subnet,
>>     -#    to an IP address that does not have a static IP-MAC binding.
>>     -#    This should generate a broadcast ARP request for the 
>> destination
>>     -#    IP address in the destination subnet.
>>     -#    Moreover generate an ARP reply for each of the IP addresses
>>     ARPed
>>     -for is in 1 2 3; do
>>     -  for js in 1 2 3; do
>>     -    for ks in 1 2 3; do
>>     -      s=$is$js$ks
>>     -      smac=f00000000$s
>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>     -      for id in 1 2 3; do
>>     -        for jd in 1 2 3; do
>>     -          if test $is$js = $id$jd; then
>>     -            continue
>>     -          fi
>>     -
>>     -          # Send the packet.
>>     -          dmac=00000000ff$is$js
>>     -          # Calculate a 4th octet for the destination that is
>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
>>     -          # that have static MAC bindings, and fits in the range
>>     -          # 0-255.
>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>     -          test_ip $s $smac $dmac $sip $dip
>>     -
>>     -          # Every LP on the destination subnet's lswitch should
>>     -          # receive the ARP request.
>>     -          lrmac=00000000ff$id$jd
>>     -          lrip=`ip_to_hex 192 168 $id$jd 254`
>>     -
>>     
>> arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip} 
>>
>>     -          for jd2 in 1 2 3; do
>>     -            for kd in 1 2 3; do
>>     -              echo $arp >> $id$jd2$kd.expected
>>     -            done
>>     -          done
>>     -
>>     -          hmac=8000000000$o4
>>     -          rmac=00000000ff$id$jd
>>     -          echo
>>     
>> ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000
>>     >> ${id}11.expected
>>     -
>>     -          host_mac=8000000000$o4
>>     -          lrmac=00000000ff$id$jd
>>     -
>>     -
>>     
>> arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip} 
>>
>>     -
>>     -          hv=hv`vif_to_hv ${id}${jd}1`
>>     -          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1
>>     $arp_reply
>>     -
>>     -          host_ip_pretty=192.168.$id$jd.$o4
>>     -          host_mac_pretty=80:00:00:00:00:$o4
>>     -          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >>
>>     mac_bindings.expected
>>     -        done
>>     -      done
>>     -    done
>>     -  done
>>     -done
>>     -
>>     -# Test router replies to ARP requests from all source ports:
>>     -#
>>     -# 4. Router replies to query for its MAC address from port's own
>>     IP address.
>>     -#
>>     -# 5. Router replies to query for its MAC address from any random
>>     IP address
>>     -#    in its subnet.
>>     -#
>>     -# 6. No reply to query for IP address other than router IP.
>>     -#
>>     -# 7. No reply to query from another subnet.
>>     -for i in 1 2 3; do
>>     -  for j in 1 2 3; do
>>     -    for k in 1 2 3; do
>>     -      smac=f00000000$i$j$k               # Source MAC
>>     -      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
>>     -      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
>>     -      rmac=00000000ff$i$j                # Router MAC
>>     -      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in subnet
>>     -      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in
>>     subnet
>>     -
>>     -      test_arp $i$j$k $smac $sip        $rip        $rmac     #4
>>     -      test_arp $i$j$k $smac $otherip    $rip        $rmac     #5
>>     -      test_arp $i$j$k $smac $sip        $otherip    #6
>>     -
>>     -      # When rip is 192.168.33.254, ARP request from externalip
>>     won't be
>>     -      # filtered, because 192.168.33.254 is configured to switch
>>     peer port
>>     -      # for lrp33.
>>     -      lrp33_rsp=
>>     -      if test $i = 3 && test $j = 3; then
>>     -        lrp33_rsp=$rmac
>>     -      fi
>>     -      test_arp $i$j$k $smac $externalip $rip $lrp33_rsp #7
>>     -
>>     -      # MAC binding should be learned from ARP request.
>>     -      host_mac_pretty=f0:00:00:00:0$i:$j$k
>>     -
>>     -      host_ip_pretty=192.168.$i$j.$k
>>     -      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>     mac_bindings.expected
>>     -
>>     -      # mac_binding is learned and overwritten so only the last
>>     one remains.
>>     -      if test $k = 3; then
>>     -          # lrp33 will not learn from ARP request, because
>>     192.168.33.254 is
>>     -          # configured to switch peer port for lrp33.
>>     -          if test $i != 3 || test $j != 3; then
>>     -              host_ip_pretty=192.168.$i$j.55
>>     -              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>     mac_bindings.expected
>>     -          fi
>>     -      fi
>>     -
>>     -    done
>>     -  done
>>     -done
>>     -
>>     -
>>     -# Allow some time for packet forwarding.
>>     -# XXX This can be improved.
>>     -sleep 1
>>     -
>>     -# 8. Send an IP packet from every logical port to every other
>>     subnet.  These
>>     -#    are the same packets already sent as #3, but now the
>>     destinations' IP-MAC
>>     -#    bindings have been discovered via ARP, so instead of
>>     provoking an ARP
>>     -#    request, these packets now get routed to their destinations
>>     (which don't
>>     -#    have static MAC bindings, so they go to the port we've
>>     designated as
>>     -#    accepting "unknown" MACs.)
>>     -for is in 1 2 3; do
>>     -  for js in 1 2 3; do
>>     -    for ks in 1 2 3; do
>>     -      s=$is$js$ks
>>     -      smac=f00000000$s
>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>     -      for id in 1 2 3; do
>>     -        for jd in 1 2 3; do
>>     -          if test $is$js = $id$jd; then
>>     -            continue
>>     -          fi
>>     -
>>     -          # Send the packet.
>>     -          dmac=00000000ff$is$js
>>     -          # Calculate a 4th octet for the destination that is
>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
>>     -          # that have static MAC bindings, and fits in the range
>>     -          # 0-255.
>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>     -          test_ip $s $smac $dmac $sip $dip
>>     -
>>     -          # Expect the packet egress.
>>     -          host_mac=8000000000$o4
>>     -          outport=${id}11
>>     -          out_lrp=$id$jd
>>     -          echo
>>     
>> ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 
>>
>>     >> $outport.expected
>>     -        done
>>     -      done
>>     -    done
>>     -  done
>>     -done
>>     -
>>     -ovn-sbctl -f csv -d bare --no-heading \
>>     -    -- --columns=logical_port,ip,mac list mac_binding > mac_bindings
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>     -                              [$i$j$k.expected])
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -# Check the MAC bindings against those expected.
>>     -AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort <
>>     mac_bindings.expected`
>>     -])
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IP relocation using GARP request])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -#
>>     -# Two logical switches ls1, ls2.
>>     -# One logical router lr0 connected to ls[12],
>>     -# with 2 subnets, 1 per logical switch:
>>     -#
>>     -#    lrp1 on ls1 for subnet 192.168.1.1/24 <http://192.168.1.1/24>
>>     -#    lrp2 on ls2 for subnet 192.168.2.1/24 <http://192.168.2.1/24>
>>     -#
>>     -# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
>>     -# VIFs' fixed IP addresses are 192.168.[12].1[12].
>>     -#
>>     -# There is a secondary IP 192.168.1.100 that is unknown in NB and
>>     learned
>>     -# through ARP only, and it can move between lp11 and lp12.
>>     -#
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2 ; do
>>     -    ovn-nbctl ls-add ls$i
>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
>>     -    ovn-nbctl \
>>     -        -- lsp-add ls$i lrp$i-attachment \
>>     -        -- set Logical_Switch_Port lrp$i-attachment type=router \
>>     -                         options:router-port=lrp$i \
>>     -                         addresses=router
>>     -    for j in 1 2; do
>>     -        ovn-nbctl \
>>     -            -- lsp-add ls$i lp$i$j \
>>     -            -- lsp-set-addresses lp$i$j \
>>     -               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
>>     -    done
>>     -done
>>     -
>>     -# Physical network:
>>     -# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located, e.g. "vif_to_hv 12" yields 2.
>>     -vif_to_hv() {
>>     -    echo ${1#?}
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its
>>     logical router
>>     -# port, e.g. "vif_to_lrp 12" yields 1.
>>     -vif_to_lrp() {
>>     -    echo ${1%?}
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its logical
>>     -# switch, e.g. "vif_to_ls 12" yields 1.
>>     -vif_to_ls() {
>>     -    echo ${1%?}
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -done
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        hv=`vif_to_hv $i$j`
>>     -            as hv$hv ovs-vsctl \
>>     -                -- add-port br-int vif$i$j \
>>     -                -- set Interface vif$i$j \
>>     -                    external-ids:iface-id=lp$i$j \
>>     -                    options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
>>     -                    options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
>>     -                    ofport-request=$i$j
>>     -    done
>>     -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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 12
>>     for vif12.
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    in_ls=`vif_to_ls $inport`
>>     -    in_lrp=`vif_to_lrp $inport`
>>     -    for outport; do
>>     -        out_ls=`vif_to_ls $outport`
>>     -        if test $in_ls = $out_ls; then
>>     -            # Ports on the same logical switch receive exactly
>>     the same packet.
>>     -            echo $packet
>>     -        else
>>     -            # Routing decrements TTL and updates source and dest MAC
>>     -            # (and checksum).
>>     -            out_lrp=`vif_to_lrp $outport`
>>     -            echo
>>     
>> f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>
>>     -        fi >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>     -    local
>>     
>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>     -
>>     -    # Expect to receive the broadcast ARP on the other logical
>>     switch ports if
>>     -    # IP address is not configured to the switch patch port.
>>     -    local i=`vif_to_ls $inport`
>>     -    local j
>>     -    for j in 1 2; do
>>     -        if test $i$j != $inport; then
>>     -            echo $request >> $i$j$k.expected
>>     -        fi
>>     -    done
>>     -
>>     -    # Expect to receive the reply, if any.
>>     -    if test X$reply_ha != X; then
>>     -        lrp=`vif_to_lrp $inport`
>>     -        local
>>     
>> reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>
>>     -        echo $reply >> $inport.expected
>>     -    fi
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# lp11 send GARP request to announce ownership of 192.168.1.100.
>>     -
>>     -sha=f00000000011
>>     -spa=`ip_to_hex 192 168 1 100`
>>     -tpa=$spa
>>     -test_arp 11 $sha $spa $tpa
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>     ip="192.168.1.100" | wc -l` -gt 0])
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>     to lp11.
>>     -
>>     -smac=f00000000021
>>     -dmac=00000000ff02
>>     -sip=`ip_to_hex 192 168 2 11`
>>     -dip=`ip_to_hex 192 168 1 100`
>>     -test_ip 21 $smac $dmac $sip $dip 11
>>     -
>>     -# lp12 send GARP request to announce ownership of 192.168.1.100.
>>     -
>>     -sha=f00000000012
>>     -test_arp 12 $sha $spa $tpa
>>     -OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" |
>>     grep f0:00:00:00:00:12])
>>     -ovn-nbctl --wait=hv sync
>>     -# give to the hv the time to send queued ip packets
>>     -sleep 1
>>     -
>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>     to lp12.
>>     -
>>     -test_ip 21 $smac $dmac $sip $dip 12
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2; do
>>     -    for j in 1 2; do
>>     -        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
>>     -                          [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
>>     -AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Create hypervisors hv[123].
>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>     -# Add all of the vifs to a single logical switch lsw0.
>>     -# Turn off port security on vifs vif[123]1
>>     -# Turn on l2 port security on vifs vif[123]2
>>     -# Turn of l2 and l3 port security on vifs vif[123]3
>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2 3; do
>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>     vif$i$j external-ids:iface-id=lp$i$j
>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>     -        if test $j = 1; then
>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>     -        elif test $j = 2; then
>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j"
>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>     f0:00:00:00:00:$i$j
>>     -        else
>>     -            extra_addr="f0:00:00:00:0$i:$i$j
>>     fe80::ea2a:eaff:fe28:$i$j"
>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>     -        fi
>>     -    done
>>     -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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv${1%?}
>>     -}
>>     -
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -
>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -#
>>     -# This shell function causes an ip packet to be received on INPORT.
>>     -# The packet's content has Ethernet destination DST and source SRC
>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>     digits).
>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>     should
>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>     switch
>>     -# port numbers, e.g. 11 for vif11.
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 reply_ha=$7
>>     -    local
>>     
>> request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -    hv=`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
>>     -    if test $drop != 1; then
>>     -        if test X$reply_ha = X; then
>>     -            # Expect to receive the broadcast ARP on the other
>>     logical switch ports
>>     -            # if no reply is expected.
>>     -            local i j
>>     -            for i in 1 2 3; do
>>     -                for j in 1 2 3; do
>>     -                    if test $i$j != $inport; then
>>     -                        echo $request >> $i$j.expected
>>     -                    fi
>>     -                done
>>     -            done
>>     -        else
>>     -            # Expect to receive the reply, if any.
>>     -            local
>>     
>> reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>>     -            echo $reply >> $inport.expected
>>     -        fi
>>     -    fi
>>     -}
>>     -
>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -# This function is similar to test_ip() except that it sends
>>     -# ipv6 packet
>>     -test_ipv6() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE
>>     OUTPORT...
>>     -# This function is similar to test_ipv6() except it specifies the
>>     ICMPv6 type
>>     -# of the test packet
>>     -test_icmpv6() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     icmp_type=$6
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000 
>>
>>     -    shift; shift; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# no port security
>>     -sip=`ip_to_hex 192 168 0 12`
>>     -tip=`ip_to_hex 192 168 0 13`
>>     -# the arp packet should be allowed even if lp[123]1 is
>>     -# not configured with mac f00000000023 and ip 192.168.0.12
>>     -for i in 1 2 3; do
>>     -    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 
>> f00000000013
>>     -    for j in 1 2 3; do
>>     -        if test $i != $j; then
>>     -            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip
>>     $tip ${j}1
>>     -        fi
>>     -    done
>>     -done
>>     -
>>     -# l2 port security
>>     -sip=`ip_to_hex 192 168 0 12`
>>     -tip=`ip_to_hex 192 168 0 13`
>>     -
>>     -# arp packet should be allowed since lp22 is configured with
>>     -# mac f00000000022
>>     -test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
>>     -
>>     -# arp packet should not be allowed since lp32 is not configured with
>>     -# mac f00000000021
>>     -test_arp 32 f00000000021 f00000000021 $sip $tip 1
>>     -
>>     -# arp packet with sha set to f00000000021 should not be allowed
>>     -# for lp12
>>     -test_arp 12 f00000000012 f00000000021 $sip $tip 1
>>     -
>>     -# ip packets should be allowed and received since lp[123]2 do not
>>     -# have l3 port security
>>     -sip=`ip_to_hex 192 168 0 55`
>>     -tip=`ip_to_hex 192 168 0 66`
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        if test $i != $j; then
>>     -            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip
>>     $tip ${j}2
>>     -        fi
>>     -    done
>>     -done
>>     -
>>     -# ipv6 packets should be received by lp[123]2
>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>     -sip=fe800000000000000000000000000000
>>     -tip=ff020000000000000000000000000000
>>     -
>>     -for i in 1 2 3; do
>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip ${i}2
>>     -done
>>     -
>>     -
>>     -# l2 and l3 port security
>>     -sip=`ip_to_hex 192 168 0 13`
>>     -tip=`ip_to_hex 192 168 0 22`
>>     -# arp packet should be allowed since lp13 is configured with
>>     -# f00000000013 and 192.168.0.13
>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>     -
>>     -# the arp packet should be dropped because lp23 is not configured
>>     -# with mac f00000000022
>>     -sip=`ip_to_hex 192 168 0 13`
>>     -tip=`ip_to_hex 192 168 0 22`
>>     -test_arp 23 f00000000022 f00000000022 $sip $tip 1
>>     -
>>     -# the arp packet should be dropped because lp33 is not configured
>>     -# with ip 192.168.0.55
>>     -spa=`ip_to_hex 192 168 0 55`
>>     -tpa=`ip_to_hex 192 168 0 22`
>>     -test_arp 33 f00000000031 f00000000031 $spa $tpa 1
>>     -
>>     -# ip packets should not be received by lp[123]3 since
>>     -# l3 port security is enabled
>>     -sip=`ip_to_hex 192 168 0 55`
>>     -tip=`ip_to_hex 192 168 0 66`
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
>>     -    done
>>     -done
>>     -
>>     -# ipv6 packets should be dropped for lp[123]3 since
>>     -# it is configured with only ipv4 address
>>     -sip=fe800000000000000000000000000000
>>     -tip=ff020000000000000000000000000000
>>     -
>>     -for i in 1 2 3; do
>>     -    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
>>     -done
>>     -
>>     -# ipv6 packets should not be received by lp[123]3 with mac
>>     f000000000$[123]3
>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>     -for i in 1 2 3; do
>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
>>     -done
>>     -
>>     -# lp13 has extra port security with mac f0000000113 and ipv6 addr
>>     -# fe80::ea2a:eaff:fe28:0012
>>     -
>>     -# ipv4 packet should be dropped for lp13 with mac f0000000113
>>     -sip=`ip_to_hex 192 168 0 13`
>>     -tip=`ip_to_hex 192 168 0 23`
>>     -test_ip 13 f00000000113 f00000000023 $sip $tip
>>     -
>>     -# ipv6 packet should be received by lp[123]3 with mac
>>     f00000000${i}${i}3
>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
>>     -# lp11 can send ipv6 traffic as there is no port security
>>     -sip=ee800000000000000000000000000000
>>     -for i in 1 2 3; do
>>     -    tip=fe80000000000000ea2aeafffe2800${i}3
>>     -    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
>>     -done
>>     -
>>     -
>>     -# ipv6 packet should not be received by lp33 with mac f0000000333
>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
>>     -# configured with fe80::ea2a:eaff:fe28:0033
>>     -# lp11 can send ipv6 traffic as there is no port security
>>     -
>>     -sip=ee800000000000000000000000000000
>>     -tip=fe80000000000000ea2aeafffe280023
>>     -test_ipv6 11 f00000000011 f00000000333 $sip $tip
>>     -
>>     -# ipv6 packet should be allowed for lp[123]3 with mac
>>     f0000000${i}${i}3
>>     -# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
>>     -# and should be dropped for any other ip6.src
>>     -# lp21 can receive ipv6 traffic as there is no port security
>>     -
>>     -tip=ee800000000000000000000000000000
>>     -for i in 1 2 3; do
>>     -    sip=fe80000000000000ea2aeafffe2800${i}3
>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
>>     -
>>     -    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
>>     -    sip=00000000000000000000000000000000
>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>     ff020000000000000000000000160000 83 21
>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>     ff020000000000000000000000160000 8f 21
>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>     ff0200000000000000ea2aeafffe2800 87 21
>>     -    # Traffic to non-multicast traffic should be dropped
>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
>>     -    # Traffic of other ICMPv6 types should be dropped
>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>     ff020000000000000000000000160000 80
>>     -
>>     -    # should be dropped
>>     -    sip=ae80000000000000ea2aeafffe2800aa
>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
>>     -done
>>     -
>>     -# configure lsp13 to send and received IPv4 packets with an
>>     address range
>>     -ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13
>>     192.168.0.13 20.0.0.4/24 <http://20.0.0.4/24> 10.0.0.0/24
>>     <http://10.0.0.0/24>"
>>     -
>>     -sleep 2
>>     -
>>     -sip=`ip_to_hex 10 0 0 13`
>>     -tip=`ip_to_hex 192 168 0 22`
>>     -# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>     -
>>     -sip=`ip_to_hex 10 0 0 14`
>>     -tip=`ip_to_hex 192 168 0 23`
>>     -# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
>>     -# with dst ip 192.168.0.23 should be allowed
>>     -test_ip 13 f00000000013 f00000000023 $sip $tip 23
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 10 0 0 15`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 10.0.0.15 should be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 20 0 0 4`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 20.0.0.4 should be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 20 0 0 5`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 20.0.0.5 should not be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 20 0 0 255`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 20.0.0.255 should be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 192 168 0 255`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 192.168.0.255 should not be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>     -
>>     -sip=`ip_to_hex 192 168 0 33`
>>     -tip=`ip_to_hex 224 0 0 4`
>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
>>     -# with dst ip 224.0.0.4  should be received by lsp13
>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>     -
>>     -#dump information including flow counters
>>     -ovn-nbctl show
>>     -ovn-sbctl dump-flows -- list multicast_group
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -echo "------ hv3 dump ------"
>>     -as hv3 ovs-vsctl show
>>     -as hv3 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>     -# network. R1 has a switchs ls1 (191.168.1.0/24
>>     <http://191.168.1.0/24>) connected to it.
>>     -# R2 has ls2 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>     -
>>     -ls1_lp1_mac="f0:00:00:01:02:03"
>>     -rp_ls1_mac="00:00:00:01:02:03"
>>     -rp_ls2_mac="00:00:00:01:02:04"
>>     -ls2_lp1_mac="f0:00:00:01:02:04"
>>     -
>>     -ls1_lp1_ip="192.168.1.2"
>>     -ls2_lp1_ip="172.16.1.2"
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lr-add R2
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -
>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>     type=router \
>>     -  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
>>     -
>>     -# Connect ls2 to R2
>>     -ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>     type=router \
>>     -  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
>>     -
>>     -# Connect R1 to R2
>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>     <http://20.0.0.1/24> peer=R2_R1
>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>     <http://20.0.0.2/24> peer=R1_R2
>>     -
>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.2
>>     -ovn-nbctl lr-route-add R2 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.1
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
>>     -
>>     -# Create logical port ls2-lp1 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Packet to send.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>     eth.dst==$rp_ls1_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>     ip4.dst==$ls2_lp1_ip &&
>>     -        udp && udp.src==53 && udp.dst==4369"
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -
>>     -# Packet to Expect
>>     -# The TTL should be decremented by 2.
>>     -packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
>>     -        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip &&
>>     ip4.dst==$ls2_lp1_ip &&
>>     -        udp && udp.src==53 && udp.dst==4369"
>>     -echo $packet | ovstest test-ovn expr-to-packets > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [1
>>     -])
>>     -
>>     -# Disable the ls2-lp1 port.
>>     -ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
>>     -
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [0
>>     -])
>>     -
>>     -# Generate the packet destined for ls2-lp1 and it should not be
>>     delivered.
>>     -# Packet to send.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>     eth.dst==$rp_ls1_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>     ip4.dst==$ls2_lp1_ip &&
>>     -        udp && udp.src==53 && udp.dst==4369"
>>     -
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -# The 2nd packet sent shound not be received.
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -
>>     -AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
>>     -AT_KEYWORDS([router-admin-state])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR - R1 has switch ls1 with two subnets attached to it
>>     (191.168.1.0/24 <http://191.168.1.0/24>
>>     -# and 172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24> 172.16.1.1/24
>>     -ovn-nbctl <http://172.16.1.1/24-ovn-nbctl> lsp-add ls1 rp-ls1 --
>>     set Logical_Switch_Port rp-ls1 type=router \
>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     -          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03
>>     192.168.1.2"
>>     -
>>     -# Create logical port ls1-lp2 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>     -          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 
>> 172.16.1.2"
>>     -
>>     -# Create one hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>     -    set interface vif2 external-ids:iface-id=ls1-lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Send ip packets between the two ports.
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Packet to send.
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>     -
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -
>>     -#Disable router R1
>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>     -
>>     -# Packet to Expect
>>     -expect_src_mac="000000010203"
>>     -expect_dst_mac="f00000010204"
>>     -echo
>>     
>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -
>>     -AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
>>     -AT_KEYWORDS([router-admin-state])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>     <http://191.168.1.0/24>) connected to it,
>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>     type=router \
>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>     -
>>     -# Connect ls2 to R1
>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>     type=router \
>>     -          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port ls2-lp1 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Create one hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Send ip packets between the two ports.
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Packet to send.
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>     -
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -#Disable router R1
>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Allow some time for the disabling of logical router R1 to
>>     propagate.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>     -
>>     -# Packet to Expect
>>     -expect_src_mac="000000010204"
>>     -expect_dst_mac="f00000010204"
>>     -echo
>>     
>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static 
>> routes])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>     -# network. R1 has switchess foo (192.168.1.0/24
>>     <http://192.168.1.0/24>)
>>     -# connected to it.
>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and bob
>>     (172.16.2.0/24 <http://172.16.2.0/24>) connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lr-add R2
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add bob
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -          type=router options:router-port=alice
>>     addresses=\"00:00:00:01:02:04\"
>>     -
>>     -# Connect bob to R2
>>     -ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
>>     <http://172.16.2.1/24>
>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob
>>     type=router \
>>     -          options:router-port=bob addresses=\"00:00:00:01:02:05\"
>>     -
>>     -# Connect R1 to R2
>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>     <http://20.0.0.1/24> peer=R2_R1
>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>     <http://20.0.0.2/24> peer=R1_R2
>>     -
>>     -#install static routes
>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -ovn-nbctl lr-route-add R2 172.16.2.0/24 <http://172.16.2.0/24>
>>     20.0.0.2 R1_R2
>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>     20.0.0.1
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Create logical port bob1 in bob
>>     -ovn-nbctl lsp-add bob bob1 \
>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -# Send ip packets between foo1 and bob1
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump ----------"
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -
>>     -# Packet to Expect at bob1
>>     -src_mac="000000010205"
>>     -dst_mac="f00000010205"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>     -echo
>>     
>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Packet to Expect at alice1
>>     -src_mac="000000010204"
>>     -dst_mac="f00000010204"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     -echo
>>     
>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send gratuitous arp on localnet])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0
>>     -
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>     snoopvif options:tx_pcap=hv/snoopvif-tx.pcap
>>     options:rxq_pcap=hv/snoopvif-rx.pcap])
>>     -
>>     -# Create a vif.
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>     "f0:00:00:00:00:01 192.168.1.2"])
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>     "f0:00:00:00:00:01"])
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>>     -
>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>     localvif1 external_ids:iface-id=localvif1])
>>     -
>>     -# Wait for packet to be received.
>>     -echo
>>     
>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>
>>     > expected
>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>     -
>>     -# Check GARP packet when restart openflow connection.
>>     -as hv
>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>     -
>>     -OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect"
>>     hv/ovn-controller.log])
>>     -
>>     -as hv
>>     -start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>     -vofproto_dpif -vunixctl
>>     -
>>     -# Wait for packet to be received.
>>     -echo
>>     
>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>
>>     > expected
>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>     -
>>     -# Delete the localnet ports.
>>     -AT_CHECK([ovs-vsctl del-port localvif1])
>>     -AT_CHECK([ovn-nbctl lsp-del ln_port])
>>     -
>>     -OVN_CLEANUP([hv])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>     LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>     -# connected to it. R2 has alice (172.16.1.0/24
>>     <http://172.16.1.0/24>) and R3 has bob (10.32.1.0/24
>>     <http://10.32.1.0/24>)
>>     -# connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lr-add R2
>>     -ovn-nbctl lr-add R3
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add bob
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect bob to R3
>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
>>     <http://10.32.1.1/24>
>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>     -    type=router options:router-port=bob
>>     addresses=\"00:00:03:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Connect R3 to join
>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>     <http://20.0.0.3/24>
>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>>     -    type=router options:router-port=R3_join
>>     addresses='"00:00:04:01:02:05"'
>>     -
>>     -#install static routes
>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -ovn-nbctl lr-route-add R1 10.32.1.0/24 <http://10.32.1.0/24> 
>> 20.0.0.3
>>     -
>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>     20.0.0.1
>>     -ovn-nbctl lr-route-add R2 10.32.1.0/24 <http://10.32.1.0/24> 
>> 20.0.0.3
>>     -
>>     -ovn-nbctl lr-route-add R3 192.168.1.0/24 <http://192.168.1.0/24>
>>     20.0.0.1
>>     -ovn-nbctl lr-route-add R3 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Create logical port bob1 in bob
>>     -ovn-nbctl lsp-add bob bob1 \
>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>     -
>>     -# Send ip packets between foo1 and bob1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -echo "----------------------------"
>>     -
>>     -# Packet to Expect at bob1
>>     -src_mac="000003010203"
>>     -dst_mac="f00000010205"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>     -echo
>>     
>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Packet to Expect at alice1
>>     -src_mac="000002010203"
>>     -dst_mac="f00000010204"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     -echo
>>     
>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>     10.0.0.6 20.0.0.4"
>>     -
>>     -ovn-nbctl ls-add ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03
>>     30.0.0.6 40.0.0.4"
>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>>     -
>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>     <http://10.0.0.0/24> \
>>     -options="\"server_id\"=\"10.0.0.1\"
>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>     -
>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
>>     -
>>     -d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24
>>     <http://30.0.0.0/24> \
>>     -options="\"server_id\"=\"30.0.0.1\"
>>     \"server_mac\"=\"ff:10:00:00:00:02\" \
>>     -\"lease_time\"=\"3600\"")"
>>     -
>>     -ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>     -    ofport-request=3
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>     -    ofport-request=4
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -sleep 2
>>     -
>>     -as hv1 ovs-vsctl show
>>     -
>>     -# This shell function sends a DHCP request packet
>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
>>     -test_dhcp() {
>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5
>>     request_ip=$6 use_ip=$7
>>     -    shift; shift; shift; shift; shift; shift; shift;
>>     -    if test $use_ip != 0; then
>>     -        src_ip=$1
>>     -        dst_ip=$2
>>     -        shift; shift;
>>     -    else
>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>     -    fi
>>     -    if test $request_ip != 0; then
>>     -        ip_len=0120
>>     -        udp_len=010b
>>     -    else
>>     -        ip_len=011a
>>     -        udp_len=0106
>>     -    fi
>>     -    local
>>     
>> request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip} 
>>
>>     -    # udp header and dhcp header
>>     -    request=${request}00440043${udp_len}0000
>>     -
>>     
>> request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac} 
>>
>>     -    # client hardware padding
>>     -    request=${request}00000000000000000000
>>     -    # server hostname
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # boot file name
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # dhcp magic cookie
>>     -    request=${request}63825363
>>     -    # dhcp message type
>>     -    request=${request}3501${dhcp_type}
>>     -    # dhcp unknown option
>>     -    request=${request}d70701020304050607
>>     -    # dhcp pad option
>>     -    request=${request}00
>>     -    if test $request_ip != 0; then
>>     -        # dhcp requested ip
>>     -        request=${request}3204${request_ip}
>>     -    fi
>>     -    # dhcp end option
>>     -    request=${request}ff
>>     -
>>     -    for port in $inport "$@"; do
>>     -        : >> $port.expected
>>     -    done
>>     -    if test $offer_ip != 0; then
>>     -        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3
>>     expected_dhcp_opts=$4
>>     -        # total IP length will be the IP length of the request 
>> packet
>>     -        # (which is 272 in our case) + 8 (padding bytes) +
>>     (expected_dhcp_opts / 2)
>>     -        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>     -        udp_len=`expr $ip_len - 20`
>>     -        ip_len=$(printf "%x" $ip_len)
>>     -        udp_len=$(printf "%x" $udp_len)
>>     -        # $ip_len var will be in 3 digits i.e 134. So adding a
>>     '0' before $ip_len
>>     -        local
>>     
>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>
>>     -        # udp header and dhcp header.
>>     -        # $udp_len var will be in 3 digits. So adding a '0'
>>     before $udp_len
>>     -
>>     
>> reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
>>     -        # your ip address; 0 for NAK
>>     -        if test $dhcp_reply_type = 06; then
>>     -            reply=${reply}00000000
>>     -        else
>>     -            reply=${reply}${offer_ip}
>>     -        fi
>>     -        # next server ip address, relay agent ip address, client
>>     mac address
>>     -        reply=${reply}0000000000000000${src_mac}
>>     -        # client hardware padding
>>     -        reply=${reply}00000000000000000000
>>     -        # server hostname
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -        # boot file name
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -        # dhcp magic cookie
>>     -        reply=${reply}63825363
>>     -
>>     
>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>
>>     -        echo $reply >> $inport.expected
>>     -    else
>>     -        for outport; do
>>     -            echo $request >> $outport.expected
>>     -        done
>>     -    fi
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Send DHCPDISCOVER.
>>     -offer_ip=`ip_to_hex 10 0 0 4`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -request_ip=0
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0
>>     ff1000000001 $server_ip 02 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 1.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap > 1.packets
>>     -cat 1.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 1.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>     -
>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>     to receive
>>     -# the DHCP request packet. So reset the pcap files so that its
>>     easier to test.
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the
>>     offered IP
>>     -# address in the Requested IP Address option.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -request_ip=$offer_ip
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>     ff1000000001 $server_ip 05 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a
>>     mismatched IP in
>>     -# the Requested IP Address option, expect a DHCPNAK.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -request_ip=`ip_to_hex 10 0 0 7`
>>     -expected_dhcp_opts=""
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>     ff1000000001 $server_ip 06 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 3.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by
>>     ovn-controller
>>     -# but should be resumed without the reply.
>>     -# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet
>>     twice,
>>     -# one from ovn-controller and the other from "ovs-ofctl resume."
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -offer_ip=0
>>     -request_ip=0
>>     -test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
>>     -
>>     -# NXT_RESUMEs should be 4.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# vif1-tx.pcap should have received the DHCPv4 (invalid) request
>>     packet
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4
>>     options defined.
>>     -# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet
>>     once.
>>     -
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
>>     -
>>     -# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not
>>     defined for
>>     -# this lport.
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
>>     -
>>     -# NXT_RESUMEs should be 4.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
>>     -#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
>>     -
>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>     set to 10.0.0.6
>>     -# and ip4.dst set to 10.0.0.1.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=$offer_ip
>>     -request_ip=0
>>     -src_ip=$offer_ip
>>     -dst_ip=$server_ip
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 5.
>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>     set to 10.0.0.6
>>     -# and ip4.dst set to 255.255.255.255.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=$offer_ip
>>     -request_ip=0
>>     -src_ip=$offer_ip
>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 6.
>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with a
>>     mismatched IP in the
>>     -# ciaddr, expect a DHCPNAK.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=`ip_to_hex 10 0 0 7`
>>     -request_ip=0
>>     -src_ip=$offer_ip
>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>     -expected_dhcp_opts=""
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 7.
>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state without a
>>     specifyied ciaddr,
>>     -# expect a DHCPNAK.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -request_ip=0
>>     -src_ip=$offer_ip
>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>     -expected_dhcp_opts=""
>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 8.
>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set
>>     to 10.0.0.4.
>>     -# The packet should not be received by ovn-controller.
>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 4`
>>     -test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
>>     -
>>     -# NXT_RESUMEs should be 8.
>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# vif1-tx.pcap should have received the DHCPv4 request packet
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>     10.0.0.4 ae70::4"
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp3 \
>>     --- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>>     -
>>     -d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>     -
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
>>     -
>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>     -options="\"dhcpv6_stateless\"=\"true\"
>>     \"server_id\"=\"00:00:00:10:00:01\"")"
>>     -
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
>>     -
>>     -ovn-nbctl ls-add ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 be70::3"
>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 be70::4"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>     -    ofport-request=3
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>     -    ofport-request=4
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif5 -- \
>>     -    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
>>     -    options:tx_pcap=hv1/vif5-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif5-rx.pcap \
>>     -    ofport-request=5
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -sleep 2
>>     -
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -# This shell function sends a DHCPv6 request packet
>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>     OUTPORT...
>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>     DHCPv6
>>     -# packet should be received twice (one from ovn-controller and
>>     the other
>>     -# from the "ovs-ofctl monitor br-int resume"
>>     -test_dhcpv6() {
>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>     -    if test $msg_code != 0b; then
>>     -        req_len=2a
>>     -    else
>>     -        req_len=1a
>>     -    fi
>>     -    local
>>     request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
>>     -    # dst ip ff02::1:2
>>     -    request=${request}ff020000000000000000000000010002
>>     -    # udp header and dhcpv6 header
>>     - request=${request}0222022300${req_len}ffff${msg_code}010203
>>     -    # Client identifier
>>     -    request=${request}0001000a00030001${src_mac}
>>     -    # Add IA-NA (Identity Association for Non Temporary Address)
>>     if msg_code
>>     -    # is not 11 (information request packet)
>>     -    if test $msg_code != 0b; then
>>     -        request=${request}0003000c0102030400000e1000001518
>>     -    fi
>>     -    shift; shift; shift; shift; shift;
>>     -    if test $offer_ip != 0; then
>>     -        local server_mac=000000100001
>>     -        local server_lla=fe80000000000000020000fffe100001
>>     -        local reply_code=07
>>     -        if test $msg_code = 01; then
>>     -            reply_code=02
>>     -        fi
>>     -        local msg_len=54
>>     -        if test $offer_ip = 1; then
>>     -            msg_len=28
>>     -        fi
>>     -        local
>>     
>> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla} 
>>
>>     -        # udp header and dhcpv6 header
>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>     -        # Client identifier
>>     -        reply=${reply}0001000a00030001${src_mac}
>>     -        # IA-NA
>>     -        if test $offer_ip != 1; then
>>     -
>>     
>> reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff 
>>
>>     -        fi
>>     -        # Server identifier
>>     -        reply=${reply}0002000a00030001${server_mac}
>>     -        echo $reply | trim_zeros >> $inport.expected
>>     -    else
>>     -        for outport; do
>>     -            echo $request | trim_zeros >> $outport.expected
>>     -        done
>>     -    fi
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -src_mac=f00000000001
>>     -src_lla=fe80000000000000f20000fffe000001
>>     -offer_ip=ae700000000000000000000000000004
>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>     -
>>     -# NXT_RESUMEs should be 1.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>     -# cat 1.expected | trim_zeros > expout
>>     -cat 1.expected | cut -c -120 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
>>     -# Skipping the UDP checksum
>>     -cat 1.expected | cut -c 125- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
>>     -
>>     -rm  1.expected
>>     -
>>     -# Send invalid packet on ls1-lp2. ovn-controller should resume
>>     the packet
>>     -# without any modifications and the packet should be received by
>>     ls1-lp1.
>>     -# ls1-lp1 will receive the packet twice, one from the
>>     ovn-controller after the
>>     -# resume and the other from ovs-ofctl monitor resume.
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -
>>     -src_mac=f00000000002
>>     -src_lla=fe80000000000000f20000fffe000002
>>     -offer_ip=ae700000000000000000000000000005
>>     -# Set invalid msg_type
>>     -
>>     -test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
>>     -
>>     -# NXT_RESUMEs should be 2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# vif2-tx.pcap should not have received the DHCPv6 reply packet
>>     -rm 2.packets
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap | trim_zeros > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [])
>>     -
>>     -# vif1-tx.pcap should have received the DHCPv6 (invalid) request
>>     packet
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>     -cat 1.expected > expout
>>     -AT_CHECK([cat 1.packets], [0], [expout])
>>     -
>>     -# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on
>>     this port.
>>     -# There should be no DHCPv6 reply from ovn-controller and the
>>     request packet
>>     -# should be received by ls2-lp2.
>>     -
>>     -src_mac=f00000000003
>>     -src_lla=fe80000000000000f20000fffe000003
>>     -test_dhcpv6 3 $src_mac $src_lla 01 0 4
>>     -
>>     -# NXT_RESUMEs should be 2 only.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# vif3-tx.pcap should not have received the DHCPv6 reply packet
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif3-tx.pcap | trim_zeros > 3.packets
>>     -AT_CHECK([cat 3.packets], [0], [])
>>     -
>>     -# vif4-tx.pcap should have received the DHCPv6 request packet
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif4-tx.pcap | trim_zeros > 4.packets
>>     -cat 4.expected > expout
>>     -AT_CHECK([cat 4.packets], [0], [expout])
>>     -
>>     -# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless
>>     mode for this port.
>>     -# The DHCPv6 reply shouldn't contain offer_ip.
>>     -src_mac=f00000000022
>>     -src_lla=fe80000000000000f20000fffe000022
>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>     -test_dhcpv6 5 $src_mac $src_lla 01 1 5
>>     -
>>     -# NXT_RESUMEs should be 3.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif5-tx.pcap | trim_zeros > 5.packets
>>     -# Skipping the UDP checksum
>>     -cat 5.expected | cut -c 1-120,125- > expout
>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>     -
>>     -# Send DHCPv6 information request (code 11) on ls1-lp3. The
>>     DHCPv6 reply
>>     -# shouldn't contain offer_ip
>>     -src_mac=f00000000022
>>     -src_lla=fe80000000000000f20000fffe000022
>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>     -rm -f 5.expected
>>     -test_dhcpv6 5 $src_mac $src_lla 0b 1 5
>>     -
>>     -# NXT_RESUMEs should be 4.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif5-tx.pcap |
>>     -trim_zeros > 5.packets
>>     -# Skipping the UDP checksum
>>     -cat 5.expected | cut -c 1-120,125- > expout
>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>     -# connected to it. R2 has alice (172.16.1.0/24
>>     <http://172.16.1.0/24>) connected to it.
>>     -# R2 is a gateway router.
>>     -
>>     -
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -
>>     -#install static routes
>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>     -ip_prefix=172.16.1.0/24 <http://172.16.1.0/24> nexthop=20.0.0.2
>>     -- add Logical_Router \
>>     -R1 static_routes @lrt
>>     -
>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>     -- add Logical_Router \
>>     -R2 static_routes @lrt
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 2
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -ovn-sbctl list chassis
>>     -ovn-sbctl list encap
>>     -echo "---------------------"
>>     -
>>     -# Packet to Expect at alice1
>>     -src_mac="000002010203"
>>     -dst_mac="f00000010204"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>     -
>>     -echo "------ hv1 dump after packet 1 ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump after packet 1 ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -echo "----------------------------"
>>     -
>>     -echo $expected > expected
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Delete the router and re-create it. Things should work as before.
>>     -ovn-nbctl  lr-del R2
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -
>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>     -- add Logical_Router \
>>     -R2 static_routes @lrt
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -sleep 1
>>     -
>>     -# Send the packet again.
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -echo "------ hv1 dump after packet 2 ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump after packet 2 ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -echo "----------------------------"
>>     -
>>     -echo $expected >> expected
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
>>     -AT_KEYWORDS([router-icmp-reply])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>     <http://191.168.1.0/24>) connected to it,
>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>     -    type=router options:router-port=ls1
>>     addresses=\"00:00:00:01:02:f1\"
>>     -
>>     -# Connect ls2 to R1
>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>     -    type=router options:router-port=ls2
>>     addresses=\"00:00:00:01:02:f2\"
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port ls2-lp1 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Create one hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -for i in 1 2; do
>>     -    : > vif$i.expected
>>     -done
>>     -# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>     IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ICMPv4
>>     -# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
>>     -# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and EXP_ICMP_CHKSUM 
>> are
>>     -# provided, then it should be the ip and icmp checksums of the 
>> packet
>>     -# responded; otherwise, no reply is expected.
>>     -# In the absence of an ip checksum calculation helpers, this relies
>>     -# on the caller to provide the checksums for the ip and icmp 
>> headers.
>>     -# XXX This should be more systematic.
>>     -#
>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>     -# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
>>     -# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
>>     -test_ipv4_icmp_request() {
>>     -    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5
>>     ip_chksum=$6 icmp_chksum=$7
>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>     -    shift; shift; shift; shift; shift; shift; shift
>>     -    shift; shift
>>     -
>>     -    # Use ttl to exercise section 4.2.2.9 of RFC1812
>>     -    local ip_ttl=01
>>     -    local icmp_id=5fbf
>>     -    local icmp_seq=0001
>>     -    local icmp_data=$(seq 1 56 | xargs printf "%02x")
>>     -    local icmp_type_code_request=0800
>>     -    local
>>     
>> icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload} 
>>
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    if test X$exp_icmp_chksum != X; then
>>     -        # Expect to receive the reply, if any. In same port where
>>     packet was sent.
>>     -        # Note: src and dst fields are expected to be reversed.
>>     -        local icmp_type_code_response=0000
>>     -        local reply_icmp_ttl=fe
>>     -        local
>>     
>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>
>>     -        local
>>     
>> reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>
>>     -        echo $reply >> vif$inport.expected
>>     -    fi
>>     -}
>>     -
>>     -# Send ping packet to router's ip addresses, from each of the 2
>>     logical ports.
>>     -rtr_l1_ip=$(ip_to_hex 192 168 1 1)
>>     -rtr_l2_ip=$(ip_to_hex 172 16 1 1)
>>     -l1_ip=$(ip_to_hex 192 168 1 2)
>>     -l2_ip=$(ip_to_hex 172 16 1 2)
>>     -
>>     -# Ping router ip address that is on same subnet as the logical port
>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>     -
>>     -# Ping router ip address that is on the other side of the logical
>>     ports
>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>     -
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list logical_flow
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for inport in 1 2; do
>>     -    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap],
>>     [vif$inport.expected])
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS,
>>     1 LR])
>>     -AT_KEYWORDS([policy-based-routing])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>     <http://191.168.1.0/24>) connected to it,
>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -ovn-nbctl ls-add ls3
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>     -    type=router options:router-port=ls1
>>     addresses=\"00:00:00:01:02:f1\"
>>     -
>>     -# Connect ls2 to R1
>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>     -    type=router options:router-port=ls2
>>     addresses=\"00:00:00:01:02:f2\"
>>     -
>>     -# Connect ls3 to R1
>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
>>     <http://20.20.1.1/24>
>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>     -    type=router options:router-port=ls3
>>     addresses=\"00:00:00:01:02:f3\"
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port ls2-lp1 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Create logical port ls3-lp1 in ls3
>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
>>     -
>>     -# Create one hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add pbr-hv
>>     -as pbr-hv
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ls1_ro_mac=00:00:00:01:02:f1
>>     -ls1_ro_ip=192.168.1.1
>>     -
>>     -ls2_ro_mac=00:00:00:01:02:f2
>>     -ls2_ro_ip=172.16.1.1
>>     -
>>     -ls3_ro_mac=00:00:00:01:02:f3
>>     -
>>     -ls1_p1_mac=00:00:00:01:02:03
>>     -ls1_p1_ip=192.168.1.2
>>     -
>>     -ls2_p1_mac=00:00:00:01:02:04
>>     -ls2_p1_ip=172.16.1.2
>>     -
>>     -ls3_p1_mac=00:00:00:01:02:05
>>     -
>>     -# Create a drop policy
>>     -ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24
>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>     <http://172.16.1.0/24>" drop
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>     "192.168.1.0" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>     ip4.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Check if packet hit the drop policy
>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24> actions=drop" | \
>>     -    grep "priority=10" | \
>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Expected to drop the packet.
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>     -rcvd_packet=`cat vif2.packets`
>>     -AT_FAIL_IF([rcvd_packet = ""])
>>     -
>>     -# Override drop policy with allow
>>     -ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24
>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>     <http://172.16.1.0/24>" allow
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>     "192.168.1.0" | wc -l], [0], [dnl
>>     -2
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>     ip4.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Check if packet hit the allow policy
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>     -    grep "192.168.1.0" | \
>>     -    grep "priority=20" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>     ip4.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>     -
>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>     -
>>     -# Override allow policy with reroute
>>     -ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24
>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>     <http://172.16.1.0/24>" reroute 20.20.1.2
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>     -    grep "192.168.1.0" | \
>>     -    grep "priority=30" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>     ip4.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -echo "southbound flows"
>>     -
>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>     -echo "ovs flows"
>>     -ovs-ofctl dump-flows br-int
>>     -# Check if packet hit the allow policy
>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24>" | \
>>     -    grep "priority=30" | \
>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -echo "packet hit reroute policy"
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>     ip4.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>     -
>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>     -
>>     -OVN_CLEANUP([pbr-hv])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1
>>     lport/LS, 1 LR])
>>     -AT_KEYWORDS([policy-based-routing])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>     <http://191.168.1.0/24>) connected to it,
>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -ovn-nbctl ls-add ls3
>>     -
>>     -# Connect ls1 to R1
>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>     -    type=router options:router-port=ls1
>>     addresses=\"00:00:00:01:02:f1\"
>>     -
>>     -# Connect ls2 to R1
>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>     -    type=router options:router-port=ls2
>>     addresses=\"00:00:00:01:02:f2\"
>>     -
>>     -# Connect ls3 to R1
>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>     -    type=router options:router-port=ls3
>>     addresses=\"00:00:00:01:02:f3\"
>>     -
>>     -# Create logical port ls1-lp1 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
>>     -
>>     -# Create logical port ls2-lp1 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
>>     -
>>     -# Create logical port ls3-lp1 in ls3
>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
>>     -
>>     -# Create one hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add pbr-hv
>>     -as pbr-hv
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ls1_ro_mac=00:00:00:01:02:f1
>>     -ls1_ro_ip=2001::1
>>     -
>>     -ls2_ro_mac=00:00:00:01:02:f2
>>     -ls2_ro_ip=2002::1
>>     -
>>     -ls3_ro_mac=00:00:00:01:02:f3
>>     -
>>     -ls1_p1_mac=00:00:00:01:02:03
>>     -ls1_p1_ip=2001::2
>>     -
>>     -ls2_p1_mac=00:00:00:01:02:04
>>     -ls2_p1_ip=2002::2
>>     -
>>     -ls3_p1_mac=00:00:00:01:02:05
>>     -
>>     -# Create a drop policy
>>     -ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 &&
>>     ip6.dst==2002::/64" drop
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>     | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>     ip6.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Check if packet hit the drop policy
>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
>>     -    grep "priority=10" | \
>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Expected to drop the packet.
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>     -rcvd_packet=`cat vif2.packets`
>>     -AT_FAIL_IF([rcvd_packet = ""])
>>     -
>>     -# Override drop policy with allow
>>     -ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 &&
>>     ip6.dst==2002::/64" allow
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>     | wc -l], [0], [dnl
>>     -2
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>     ip6.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Check if packet hit the allow policy
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>     -    grep "2001" | \
>>     -    grep "priority=20" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>     ip6.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>     -
>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>     -
>>     -# Override allow policy with reroute
>>     -ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 &&
>>     ip6.dst==2002::/64" reroute 2003::2
>>     -
>>     -# Check logical flow
>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>     -    grep "2001" | \
>>     -    grep "priority=30" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -# Send packet.
>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>     eth.dst==$ls1_ro_mac &&
>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>     ip6.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -echo "southbound flows"
>>     -
>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>     -echo "ovs flows"
>>     -ovs-ofctl dump-flows br-int
>>     -# Check if packet hit the allow policy
>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
>>     -    grep "priority=30" | \
>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>     -1
>>     -])
>>     -echo "packet hit reroute policy"
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>     ip6.dst==$ls2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>     -
>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>     -
>>     -OVN_CLEANUP([pbr-hv])
>>     -AT_CLEANUP
>>     -
>>     -# 1 hypervisor, 1 port
>>     -# make sure that the port state is properly set to up and back down
>>     -# when created and deleted.
>>     -AT_SETUP([ovn -- port state up and down])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl lsp-add ls1 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1 ovs-vsctl add-br br-phys
>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>     -
>>     -as hv1 ovs-vsctl del-port br-int vif1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# 1 hypervisor, 1 port
>>     -# make sure that the OF rules created to support a datapath are
>>     added/cleared
>>     -# when logical switch is created and removed.
>>     -AT_SETUP([ovn -- datapath rules added/removed])
>>     -AT_KEYWORDS([cleanup])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1 ovs-vsctl add-br br-phys
>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -# This shell function checks if OF rules in br-int have clauses
>>     -# related to OVN datapaths. The caller determines if it should find
>>     -# a match in the output, or not.
>>     -#
>>     -# EXPECT_DATAPATH param determines whether flows that refer to
>>     -#                 datapath to should be present or not. 0 means
>>     -#                 they should not be.
>>     -# STAGE_INFO param is a simple string to help identify the stage
>>     -#            in the test when this function was invoked.
>>     -test_datapath_in_of_rules() {
>>     -    local expect_datapath=$1 stage_info=$2
>>     -    echo "------ ovn-nbctl show ${stage_info} ------"
>>     -    ovn-nbctl show
>>     -    echo "------ ovn-sbctl show ${stage_info} ------"
>>     -    ovn-sbctl show
>>     -    echo "------ OF rules ${stage_info} ------"
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
>>     -    # if there is a datapath mentioned in the output, check for the
>>     -    # magic keyword that represents one, based on the exit status of
>>     -    # a quiet grep
>>     -    if test $expect_datapath != 0; then
>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [0], 
>> [ignore-nolog])
>>     -    else
>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [1], 
>> [ignore-nolog])
>>     -    fi
>>     -}
>>     -
>>     -test_datapath_in_of_rules 0 "before ls+port create"
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl lsp-add ls1 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>     -
>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>     -
>>     -test_datapath_in_of_rules 1 "after port is bound"
>>     -
>>     -as hv1 ovs-vsctl del-port br-int vif1
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>     -
>>     -ovn-nbctl lsp-set-addresses lp1
>>     -ovn-nbctl lsp-del lp1
>>     -ovn-nbctl ls-del ls1
>>     -
>>     -# wait for earlier changes to take effect
>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>     -
>>     -# ensure OF rules are no longer present. There used to be a bug 
>> here.
>>     -test_datapath_in_of_rules 0 "after lport+ls removal"
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- nd_na ])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -#TODO: since patch port for IPv6 logical router port is not ready
>>     not,
>>     -#  so we are not going to test vifs on different lswitches cases. 
>> Try
>>     -#  to update for that once relevant stuff implemented.
>>     -
>>     -# In this test cases we create 1 lswitch, it has 2 VIF ports 
>> attached
>>     -# with. NS packet we test, from one VIF for another VIF, will be
>>     replied
>>     -# by local ovn-controller, but not by target VIF.
>>     -
>>     -# Create hypervisors and logical switch lsw0.
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>     -ovn-nbctl lsp-add lsw0 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3
>>     fd81:ce49:a948:0:f816:3eff:fe94:598"
>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98
>>     192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
>>     -
>>     -# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>     external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap
>>     options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
>>     -ovn-nbctl lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
>>     fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae
>>     192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>     -
>>     -# Add ACL rule for ICMPv6 on lsw0
>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>     icmp6'  allow-related
>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>     icmp6'  allow-related
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv1${1%?}
>>     -}
>>     -for i in 1 2; do
>>     -    : > $i.expected
>>     -done
>>     -
>>     -# Complete Neighbor Solicitation packet and Neighbor
>>     Advertisement packet
>>     -# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
>>     -# vif2 will not receive NS packet, since ovn-controller will
>>     reply for it.
>>     
>> -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598 
>>
>>     
>> -na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae 
>>
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
>>     -echo $na_packet >> 1.expected
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -
>>     -for i in 1 2; do
>>     -    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- address sets modification/removal smoke test])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
>>     -ovn-nbctl set Address_Set $row name=set1
>>     addresses=\"1.1.1.1,1.1.1.2\"
>>     -ovn-nbctl destroy Address_Set $row
>>     -
>>     -sleep 1
>>     -
>>     -# A bug previously existed in the address set support code
>>     -# that caused ovn-controller to crash after an address set
>>     -# was updated and then removed.  This test case ensures
>>     -# that ovn-controller is at least still running after
>>     -# creating, updating, and deleting an address set.
>>     -AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ipam])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Add a port to a switch that does not have a subnet set, then
>>     set the
>>     -# subnet which should result in an address being allocated for
>>     the port.
>>     -ovn-nbctl --wait=hv set NB_Global .
>>     options:mac_prefix="0a:00:00:00:00:00"
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>     subnet=192.168.1.0/24
>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>     get Logical-Switch-Port p0 dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>     -])
>>     -
>>     -# Add 9 more ports to sw0, addresses should all be unique.
>>     -for n in `seq 1 9`; do
>>     -    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses
>>     "p$n" dynamic
>>     -done
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p1
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:04 192.168.1.3"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p2
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:05 192.168.1.4"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p3
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:06 192.168.1.5"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p4
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:07 192.168.1.6"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p5
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:08 192.168.1.7"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p6
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:09 192.168.1.8"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p7
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:0a 192.168.1.9"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p8
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:0b 192.168.1.10"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p9
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:0c 192.168.1.11"
>>     -])
>>     -
>>     -# Trying similar tests with a second switch. MAC addresses should
>>     be unique
>>     -# across both switches but IP's only need to be unique within the
>>     same switch.
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
>>     -ovn-nbctl --wait=sb add Logical-Switch sw1 other_config
>>     subnet=192.168.1.0/24
>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>     get Logical-Switch-Port p10 dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:0d 192.168.1.2"
>>     -])
>>     -
>>     -for n in `seq 11 19`; do
>>     -    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses
>>     "p$n" dynamic
>>     -done
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p11
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:0e 192.168.1.3"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p12
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:0f 192.168.1.4"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p13
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:10 192.168.1.5"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p14
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:11 192.168.1.6"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p15
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:12 192.168.1.7"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p16
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:13 192.168.1.8"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p17
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:14 192.168.1.9"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p18
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:15 192.168.1.10"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p19
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:16 192.168.1.11"
>>     -])
>>     -
>>     -# Change a port's address to test for multiple ip's for a single
>>     address entry
>>     -# and addresses set by the user.
>>     -ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2
>>     192.168.1.12 192.168.1.14"
>>     -ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p20
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:18 192.168.1.13"
>>     -])
>>     -
>>     -# Test for logical router port address management.
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
>>     -network="192.168.1.1/24 <http://192.168.1.1/24>"
>>     mac=\"0a:00:00:a8:01:19\" \
>>     --- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
>>     --- set Logical_Switch_Port rp-sw0 type=router 
>> options:router-port=sw0
>>     -ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p21
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:1a 192.168.1.15"
>>     -])
>>     -
>>     -# Test for address reuse after logical port is deleted.
>>     -ovn-nbctl lsp-del p0
>>     -ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p23
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:03 192.168.1.2"
>>     -])
>>     -
>>     -# Test for multiple addresses to one logical port.
>>     -ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
>>     -"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
>>     -ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p26
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:17 192.168.1.16"
>>     -])
>>     -
>>     -# Test for exhausting subnet address space.
>>     -ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config
>>     subnet=172.16.1.0/30
>>     -ovn-nbctl <http://172.16.1.0/30-ovn-nbctl> --wait=sb lsp-add sw2
>>     p27 -- lsp-set-addresses p27 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p27
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:10:01:03 172.16.1.2"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p28
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:00:00:01"
>>     -])
>>     -
>>     -# Test that address management does not add duplicate MAC for
>>     lsp/lrp peers.
>>     -ovn-nbctl create Logical_Router name=R2
>>     -ovn-nbctl ls-add sw3
>>     -ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
>>     -"0a:00:00:a8:01:18"
>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
>>     -network="192.168.2.1/24 <http://192.168.2.1/24>"
>>     mac=\"0a:00:00:a8:01:18\" \
>>     --- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
>>     --- set Logical_Switch_Port rp-sw3 type=router 
>> options:router-port=sw3
>>     -ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 dynamic
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p30
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:1d 192.168.1.17"
>>     -])
>>     -
>>     -# Test static MAC address with dynamically allocated IP
>>     -ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
>>     -"fe:dc:ba:98:76:54 dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>     dynamic_addresses], [0],
>>     -     ["fe:dc:ba:98:76:54 192.168.1.18"
>>     -])
>>     -
>>     -# Update the static MAC address with dynamically allocated IP and
>>     check
>>     -# if the MAC address is updated in
>>     'Logical_Switch_Port.dynamic_adddresses'
>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 
>> dynamic"
>>     -
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>     dynamic_addresses], [0],
>>     -     ["fe:dc:ba:98:76:55 192.168.1.18"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:1e 192.168.1.18"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 
>> dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>     dynamic_addresses], [0],
>>     -     ["fe:dc:ba:98:76:56 192.168.1.18"
>>     -])
>>     -
>>     -
>>     -# Test the exclude_ips from the IPAM list
>>     -ovn-nbctl --wait=sb set logical_switch sw0 \
>>     -other_config:exclude_ips="192.168.1.19 192.168.1.21
>>     192.168.1.23..192.168.1.50"
>>     -
>>     -ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
>>     -"dynamic"
>>     -# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p32
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:1e 192.168.1.20"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
>>     -"dynamic"
>>     -# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p33
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:1f 192.168.1.22"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
>>     -"dynamic"
>>     -# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is
>>     excluded.
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p34
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:34 192.168.1.51"
>>     -])
>>     -
>>     -# Now clear the exclude_ips list. 192.168.1.19 should be assigned.
>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>     other_config:exclude_ips="invalid"
>>     -ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
>>     -"dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p35
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:20 192.168.1.19"
>>     -])
>>     -
>>     -# Set invalid data in exclude_ips list. It should be ignored.
>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>     other_config:exclude_ips="182.168.1.30"
>>     -ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
>>     -"dynamic"
>>     -# 192.168.1.21 should be assigned as that's the next free one.
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:21 192.168.1.21"
>>     -])
>>     -
>>     -# Clear the dynamic addresses assignment request.
>>     -ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>     dynamic_addresses], [0],
>>     -         [[[]]
>>     -])
>>     -
>>     -# Set IPv6 prefix
>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>     other_config:ipv6_prefix="aef0::"
>>     -ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
>>     -"dynamic"
>>     -
>>     -# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6
>>     should be
>>     -# - aef0::800:ff:fe00:26 (EUI64)
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p37
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb ls-add sw4
>>     -ovn-nbctl --wait=sb set Logical-switch sw4
>>     other_config:ipv6_prefix="bef0::" \
>>     --- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
>>     <http://192.168.2.0/30>
>>     -ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
>>     -"dynamic"
>>     -
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p38
>>     dynamic_addresses], [0],
>>     -     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
>>     -"f0:00:00:00:10:12 dynamic"
>>     -
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p39
>>     dynamic_addresses], [0],
>>     -     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
>>     -])
>>     -
>>     -# Test the case where IPv4 addresses are exhausted and IPv6
>>     prefix is set
>>     -# p40 should not have an IPv4 address since the pool is exhausted
>>     -ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
>>     -"dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p40
>>     dynamic_addresses], [0],
>>     -         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
>>     -])
>>     -
>>     -# Test dynamic changes on switch ports.
>>     -#
>>     -ovn-nbctl --wait=sb ls-add sw5
>>     -ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
>>     -"dynamic"
>>     -# p41 will start with nothing
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         [[[]]
>>     -])
>>     -
>>     -# Set a subnet. Now p41 should have an ipv4 address, too
>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>     subnet=192.168.1.0/24
>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>     -         ["0a:00:00:a8:01:22 192.168.1.2"
>>     -])
>>     -
>>     -# Clear the other_config. The IPv4 address should be gone
>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         [[[]]
>>     -])
>>     -
>>     -# Set an IPv6 prefix. Now p41 should have an IPv6 address.
>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>     other_config:ipv6_prefix="aef0::"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
>>     -])
>>     -
>>     -# Change the MAC address to a static one. The IPv6 address should
>>     update.
>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b 
>> dynamic"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
>>     -])
>>     -
>>     -# Change the IPv6 prefix. The IPv6 address should update.
>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>     other_config:ipv6_prefix="bef0::"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
>>     -])
>>     -
>>     -# Clear the other_config. The IPv6 address should be gone
>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         [[[]]
>>     -])
>>     -
>>     -# Set the subnet again. Now p41 should get the IPv4 address again.
>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>     subnet=192.168.1.0/24
>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>     -         ["f0:00:00:00:10:2b 192.168.1.2"
>>     -])
>>     -
>>     -# Add an excluded IP address that conflicts with p41. p41 should
>>     update.
>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
>>     -exclude_ips="192.168.1.2"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         ["f0:00:00:00:10:2b 192.168.1.3"
>>     -])
>>     -
>>     -# Add static ip address
>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
>>     -ovn-nbctl list Logical-Switch-Port p41
>>     -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
>>     -"dynamic 192.168.1.101"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>     dynamic_addresses], [0],
>>     -         ["0a:00:00:a8:01:65 192.168.1.100"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p42
>>     dynamic_addresses], [0],
>>     -         ["0a:00:00:a8:01:66 192.168.1.101"
>>     -])
>>     -
>>     -# define a mac address prefix
>>     -ovn-nbctl ls-add sw6
>>     -ovn-nbctl --wait=hv set NB_Global .
>>     options:mac_prefix="00:11:22:33:44:55"
>>     -ovn-nbctl --wait=sb set Logical-Switch sw6
>>     other_config:subnet=192.168.100.0/24
>>     -for <http://192.168.100.0/24-for> n in $(seq 1 3); do
>>     -    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses
>>     "p5$n" dynamic
>>     -done
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p51
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:a8:64:03 192.168.100.2"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p52
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:a8:64:04 192.168.100.3"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p53
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:a8:64:05 192.168.100.4"
>>     -])
>>     -
>>     -# verify configuration order does not break IPAM/MACAM
>>     -ovn-nbctl ls-add sw7
>>     -for n in $(seq 1 3); do
>>     -    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses
>>     "p7$n" dynamic
>>     -done
>>     -ovn-nbctl --wait=sb set Logical-Switch sw7
>>     other_config:ipv6_prefix="bef0::"
>>     -p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 dynamic_addresses)
>>     -p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 dynamic_addresses)
>>     -p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 dynamic_addresses)
>>     -AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
>>     -AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
>>     -AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
>>     -
>>     -# request to assign mac only
>>     -#
>>     -ovn-nbctl ls-add sw8
>>     -ovn-nbctl --wait=sb set Logical-Switch sw8 
>> other_config:mac_only=true
>>     -for n in $(seq 1 3); do
>>     -    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses
>>     "p8$n" dynamic
>>     -done
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p81
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:00:00:06"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p82
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:00:00:07"
>>     -])
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p83
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:00:00:08"
>>     -])
>>     -
>>     -# clear mac_prefix and check it is allocated in a random manner
>>     -ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
>>     -ovn-nbctl ls-add sw9
>>     -ovn-nbctl --wait=sb set Logical-Switch sw9 
>> other_config:mac_only=true
>>     -ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 dynamic
>>     -
>>     -mac_prefix=$(ovn-nbctl --wait=sb get NB_Global .
>>     options:mac_prefix | tr -d \")
>>     -port_addr=$(ovn-nbctl get Logical-Switch-Port p91
>>     dynamic_addresses | tr -d \")
>>     -AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
>>     -
>>     -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
>>     -ovn-nbctl ls-add sw10
>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>     other_config:ipv6_prefix="ae01::"
>>     -ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101
>>     "dynamic ae01::1"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p101
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:00:00:0a ae01::1"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>     other_config:subnet=192.168.110.0/24
>>     -ovn-nbctl <http://192.168.110.0/24-ovn-nbctl> --wait=sb lsp-add
>>     sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 ae01::2"
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p102
>>     dynamic_addresses], [0],
>>     -    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
>>     -])
>>     -
>>     -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 northd-backup
>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ipam connectivity])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -# Test for a ping using dynamically allocated addresses.
>>     -ovn-nbctl --wait=hv set NB_Global .
>>     options:mac_prefix="0a:00:00:00:00:00"
>>     -ovn-nbctl ls-add foo -- add Logical_Switch foo other_config
>>     subnet=192.168.1.0/24
>>     -ovn-nbctl <http://192.168.1.0/24-ovn-nbctl> ls-add alice -- add
>>     Logical_Switch alice other_config subnet=192.168.2.0/24
>>     <http://192.168.2.0/24>
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -          options:router-port=foo \
>>     -          -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect alice to R1
>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice type=router \
>>     -          options:router-port=alice addresses=\"00:00:00:01:02:04\"
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl --wait=sb lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "dynamic"
>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>     foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl --wait=sb lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "dynamic"
>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>     alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
>>     -
>>     -# Create logical port foo2 in foo
>>     -ovn-nbctl --wait=sb lsp-add foo foo2 \
>>     --- lsp-set-addresses foo2 "dynamic"
>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>     foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
>>     -
>>     -# Create a hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=foo2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>     -    set interface hv1-vif3 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>     -    ofport-request=3
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and foo2
>>     -src_mac="0a0000a80103"
>>     -dst_mac="0a0000a80104"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="0a0000a80103"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Packet to Expect at foo2
>>     -src_mac="0a0000a80103"
>>     -dst_mac="0a0000a80104"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > received1.packets
>>     -echo $expected > expout
>>     -AT_CHECK([cat received1.packets], [0], [expout])
>>     -
>>     -# Packet to Expect at alice1
>>     -src_mac="000000010204"
>>     -dst_mac="0a0000a80203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif3-tx.pcap > received2.packets
>>     -echo $expected > expout
>>     -AT_CHECK([cat received2.packets], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ovs-vswitchd restart])
>>     -AT_KEYWORDS([vswitchd])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -OVN_POPULATE_ARP
>>     -sleep 2
>>     -
>>     -as hv1 ovs-vsctl show
>>     -
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
>>     -
>>     -echo "Total flows before vswitchd restart = " $total_flows
>>     -
>>     -# Code taken from ovs-save utility
>>     -save_flows () {
>>     -    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
>>     -    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
>>     -            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
>>     -    echo "EOF" >> restore_flows.sh
>>     -}
>>     -
>>     -restart_vswitchd () {
>>     -    restore_flows=$1
>>     -
>>     -    if test $restore_flows = true; then
>>     -        save_flows
>>     -    fi
>>     -
>>     -    as hv1
>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>     -
>>     -    if test $restore_flows = true; then
>>     -        as hv1
>>     -        ovs-vsctl --no-wait set open_vswitch .
>>     other_config:flow-restore-wait="true"
>>     -    fi
>>     -
>>     -    as hv1
>>     -    start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>     -vofproto_dpif -vunixctl
>>     -    ovs-ofctl dump-flows br-int
>>     -
>>     -    if test $restore_flows = true; then
>>     -        sh ./restore_flows.sh
>>     -        echo "Flows after restore"
>>     -        as hv1
>>     -        ovs-ofctl dump-flows br-int
>>     -        ovs-vsctl --no-wait --if-exists remove open_vswitch .
>>     other_config \
>>     -            flow-restore-wait="true"
>>     -    fi
>>     -}
>>     -
>>     -# Save the flows, restart vswitchd and restore the flows
>>     -restart_vswitchd true
>>     -OVS_WAIT_UNTIL([
>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>     | wc -l`
>>     -    echo "Total flows after vswitchd restart = "
>>     $total_flows_after_restart
>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>     -])
>>     -
>>     -# Restart vswitchd without restoring
>>     -restart_vswitchd false
>>     -OVS_WAIT_UNTIL([
>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>     | wc -l`
>>     -    echo "Total flows after vswitchd restart = "
>>     $total_flows_after_restart
>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>     -])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send arp for nexthop])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Topology: Two LSs - ls1 and ls2 are connected via router r0
>>     -
>>     -# Create logical switches
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -
>>     -# Create  router
>>     -ovn-nbctl create Logical_Router name=lr0
>>     -
>>     -# Add router ls1p1 port to gateway router
>>     -ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
>>     -ovn-nbctl <http://192.168.0.1/24-ovn-nbctl> lsp-add ls1 ls1lp1 --
>>     set Logical_Switch_Port ls1lp1  \
>>     -    type=router options:router-port=lrp-ls1lp1 \
>>     -    addresses='"f0:00:00:00:00:01 192.168.0.1"'
>>     -
>>     -# Add router ls2p2 port to gateway router
>>     -ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
>>     -ovn-nbctl <http://192.168.1.1/24-ovn-nbctl> lsp-add ls2 ls2lp1 --
>>     set Logical_Switch_Port ls2lp1 \
>>     -    type=router options:router-port=lrp-ls2lp1 \
>>     -    addresses='"f0:00:00:00:00:02 192.168.1.1"'
>>     -
>>     -# Set default gateway (nexthop) to 192.168.1.254
>>     -ovn-nbctl lr-route-add lr0 "0.0.0.0/0 <http://0.0.0.0/0>"
>>     192.168.1.254 lrp-ls2lp1
>>     -
>>     -# Create logical port ls1lp2 in ls1
>>     -ovn-nbctl lsp-add ls1 ls1lp2 \
>>     --- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
>>     -
>>     -# Create logical port ls2lp2 in ls2
>>     -ovn-nbctl lsp-add ls2 ls2lp2 \
>>     --- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
>>     -    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
>>     -    options:tx_pcap=hv1/ls1lp2-tx.pcap \
>>     -    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
>>     -    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
>>     -    options:tx_pcap=hv1/ls2lp2-tx.pcap \
>>     -    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -ovn-sbctl list chassis
>>     -ovn-sbctl list encap
>>     -echo "---------------------"
>>     -
>>     -echo "------Flows dump-----"
>>     -as hv1
>>     -ovs-ofctl dump-flows
>>     -echo "---------------------"
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -src_mac="f00000000003"
>>     -dst_mac="f00000000001"
>>     -src_ip=`ip_to_hex 192 168 0 2`
>>     -dst_ip=`ip_to_hex 8 8 8 8`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -# Send IP packet destined to 8.8.8.8 from lsp1lp2
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
>>     -
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -# ARP packet should be received with Target IP Address set to
>>     192.168.1.254 and
>>     -# not 8.8.8.8
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ls2lp2-tx.pcap | trim_zeros > packets
>>     
>> -expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe" 
>>
>>     -echo $expected > expout
>>     -AT_CHECK([cat packets], [0], [expout])
>>     -cat packets
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -# Create logical switch
>>     -ovn-nbctl ls-add ls0
>>     -# Create gateway router
>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>     -# Add router port to gateway router
>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>     <http://192.168.0.1/24>
>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>     -    type=router options:router-port=lrp0
>>     addresses='"f0:00:00:00:00:01"'
>>     -# Add nat-address option
>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="f0:00:00:00:00:01 192.168.0.2"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0
>>     -
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>>     -
>>     -# Wait until the patch ports are created in hv1 to connect br-int
>>     to br-eth0
>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>     -
>>     -# Wait for packet to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>
>>     -echo $expected > expout
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>
>>     -echo $expected >> expout
>>     -AT_CHECK([sort packets], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in
>>     localnet])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -# Create logical switch
>>     -ovn-nbctl ls-add ls0
>>     -# Create gateway router
>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>     -# Add router port to gateway router
>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>     <http://192.168.0.1/24>
>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>     -    type=router options:router-port=lrp0
>>     addresses='"f0:00:00:00:00:01"'
>>     -# Add nat-address option
>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="router"
>>     -# Add NAT rules
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>     <http://10.0.0.0/24>])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
>>     -# Add load balancers
>>     -AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80
>>     <http://192.168.0.3:80> 10.0.0.2:80
>>     <http://10.0.0.2:80>,10.0.0.3:80 <http://10.0.0.3:80>])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>     -AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080
>>     <http://192.168.0.3:8080> 10.0.0.2:8080
>>     <http://10.0.0.2:8080>,10.0.0.3:8080 <http://10.0.0.3:8080>])
>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl \
>>     -    -- add-br br-phys \
>>     -    -- add-br br-eth0
>>     -
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>>     -
>>     -# Wait until the patch ports are created to connect br-int to 
>> br-eth0
>>     -OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>     -
>>     -ovn-sbctl list port_binding lrp0-rp
>>     -echo "*****"
>>     -ovn-nbctl list logical_switch_port lrp0-rp
>>     -ovn-nbctl list logical_router_port lrp0
>>     -ovn-nbctl show
>>     -# Wait for packet to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>
>>     -echo $expected > expout
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>
>>     -echo $expected >> expout
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003" 
>>
>>     -echo $expected >> expout
>>     -AT_CHECK([sort packets], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- delete mac bindings])
>>     -ovn_start
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl -- add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -# Create logical switch ls0
>>     -ovn-nbctl ls-add ls0
>>     -# Create ports lp0, lp1 in ls0
>>     -ovn-nbctl lsp-add ls0 lp0
>>     -ovn-nbctl lsp-add ls0 lp1
>>     -ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
>>     -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
>>     -dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" |
>>     cut -f2 -d " "`
>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>     logical_port=lp0 mac="mac1"
>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>     logical_port=lp1 mac="mac2"
>>     -ovn-sbctl find MAC_Binding
>>     -# Delete port lp0 and check that its MAC_Binding is deleted.
>>     -ovn-nbctl lsp-del lp0
>>     -ovn-sbctl find MAC_Binding
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0
>>     | wc -l` = 0])
>>     -# Delete logical switch ls0 and check that its MAC_Binding is
>>     deleted.
>>     -ovn-nbctl ls-del ls0
>>     -ovn-sbctl find MAC_Binding
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- conntrack zone allocation])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# 2 logical switches "foo" (192.168.1.0/24
>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>     <http://172.16.1.0/24>)
>>     -# connected to a router R1.
>>     -# foo has foo1 to act as a client.
>>     -# bar has bar1, bar2, bar3 to act as servers.
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -for i in foo1 bar1 bar2 bar3; do
>>     -    ovs-vsctl -- add-port br-int $i -- \
>>     -        set interface $i external-ids:iface-id=$i \
>>     -        options:tx_pcap=hv1/$i-tx.pcap \
>>     -        options:rxq_pcap=hv1/$i-rx.pcap
>>     -done
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port bar1, bar2 and bar3 in bar
>>     -for i in `seq 1 3`; do
>>     -    ip=`expr $i + 1`
>>     -    ovn-nbctl lsp-add bar bar$i \
>>     -    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
>>     -done
>>     -
>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep
>>     REG13 | wc -l` -eq 4])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- tag allocation])
>>     -ovn_start
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>     -
>>     -dnl When a tag is provided, no allocation is done
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>     -])
>>     -dnl The same 'tag' gets created in southbound database.
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c0"], [0], [3
>>     -])
>>     -
>>     -dnl Allocate tags and see it getting created in both NB and SB
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c1"], [0], [1
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c2"], [0], [2
>>     -])
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c3"], [0], [4
>>     -])
>>     -
>>     -dnl A different parent.
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c4"], [0], [1
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c5"], [0], [2
>>     -])
>>     -
>>     -dnl Delete a logical port and create a new one.
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c6"], [0], [1
>>     -])
>>     -
>>     -dnl Restart northd to see that the same allocation remains.
>>     -as northd
>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>     -start_daemon ovn-northd \
>>     -    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>     -    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>     -
>>     -dnl Create a switch to make sure that ovn-northd has run through
>>     the main loop.
>>     -AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>     -])
>>     -
>>     -dnl Create a switch port with a tag that has already been allocated.
>>     -dnl It should go through fine with a duplicate tag.
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
>>     -])
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="c7"], [0], [2
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>     -])
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add ls2])
>>     -dnl When there is no parent_name provided (for say, 'localnet'),
>>     'tag_request'
>>     -dnl gets copied to 'tag'
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
>>     -])
>>     -dnl The same 'tag' gets created in southbound database.
>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>     port_binding \
>>     -logical_port="local0"], [0], [25
>>     -])
>>     -dnl If 'tag_request' is 0 for localnet, nothing gets written to 
>> 'tag'
>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1])
>>     -dnl change the tag_request.
>>     -AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1
>>     tag_request=50])
>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on
>>     localnet])
>>     -ovn_start
>>     -ovn-nbctl ls-add lsw0
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -    ovs-vsctl add-br br-eth0
>>     -    AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>     -done
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>>     -
>>     -
>>     -# Create 3 vifs.
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>     "f0:00:00:00:00:01 192.168.1.1"])
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>     "f0:00:00:00:00:01"])
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2
>>     "f0:00:00:00:00:02 192.168.1.2"])
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif2
>>     "f0:00:00:00:00:02"])
>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif3
>>     "f0:00:00:00:00:03 192.168.1.3"])
>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif3
>>     "f0:00:00:00:00:03"])
>>     -
>>     -# Bind the localvif1 to hv1.
>>     -as hv1
>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>     localvif1 external_ids:iface-id=localvif1])
>>     -
>>     -# On hv1, check that there are no flows outputting bcast to tunnel
>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>     ofctl_strip | grep output | wc -l` -eq 0])
>>     -
>>     -# On hv2, check that no flow outputs bcast to tunnel to hv1.
>>     -as hv2
>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>     ofctl_strip | grep output | wc -l` -eq 0])
>>     -
>>     -# Now bind vif2 on hv2.
>>     -AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface
>>     localvif2 external_ids:iface-id=localvif2])
>>     -
>>     -# At this point, the broadcast flow on vif2 should be deleted.
>>     -# because, there is now a localnet vif bound (table=32
>>     programming logic)
>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>     ofctl_strip | grep output | wc -l` -eq 0])
>>     -
>>     -# Verify that the local net patch port exists on hv2.
>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>     -
>>     -# Now bind vif3 on hv2.
>>     -AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface
>>     localvif3 external_ids:iface-id=localvif3])
>>     -
>>     -# Verify that the local net patch port still exists on hv2
>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>     -
>>     -# Delete localvif2
>>     -AT_CHECK([ovn-nbctl lsp-del localvif2])
>>     -
>>     -# Verify that the local net patch port still exists on hv2,
>>     -# because, localvif3 is still bound.
>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -
>>     -AT_SETUP([ovn -- ACL logging])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -for i in lp1 lp2; do
>>     -    ovs-vsctl -- add-port br-int $i -- \
>>     -        set interface $i external-ids:iface-id=$i \
>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>     -done
>>     -
>>     -lp1_mac="f0:00:00:00:00:01"
>>     -lp1_ip="192.168.1.2"
>>     -
>>     -lp2_mac="f0:00:00:00:00:02"
>>     -lp2_ip="192.168.1.3"
>>     -
>>     -ovn-nbctl ls-add lsw0
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>     -ovn-nbctl --wait=sb sync
>>     -
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>     -ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0
>>     to-lport 1000 'tcp.dst==81' drop
>>     -
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
>>     -ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0
>>     to-lport 1000 'tcp.dst==83' allow
>>     -
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
>>     -ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85'
>>     allow-related
>>     -
>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
>>     -ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow
>>     acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
>>     -
>>     -ovn-sbctl dump-flows
>>     -
>>     -
>>     -# Send packet that should be dropped without logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should be dropped with logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should be allowed without logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should be allowed with logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should allow related flows without logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should allow related flows with logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should be rejected without logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Send packet that should be rejected with logging.
>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
>>     -        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log'
>>     hv/ovn-controller.log) ])
>>     -
>>     -AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed
>>     's/.*name=/name=/'], [0], [dnl
>>     -name="drop-flow", verdict=drop, severity=alert:
>>     
>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn 
>>
>>     -name="allow-flow", verdict=allow, severity=info:
>>     
>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn 
>>
>>     -name="<unnamed>", verdict=allow, severity=info:
>>     
>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn 
>>
>>     -name="reject-flow", verdict=reject, severity=alert:
>>     
>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn 
>>
>>     -])
>>     -
>>     -OVN_CLEANUP([hv])
>>     -AT_CLEANUP
>>     -
>>     -
>>     -AT_SETUP([ovn -- ACL rate-limited logging])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -for i in lp1 lp2; do
>>     -    ovs-vsctl -- add-port br-int $i -- \
>>     -        set interface $i external-ids:iface-id=$i \
>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>     -done
>>     -
>>     -lp1_mac="f0:00:00:00:00:01"
>>     -lp1_ip="192.168.1.2"
>>     -
>>     -lp2_mac="f0:00:00:00:00:02"
>>     -lp2_ip="192.168.1.3"
>>     -
>>     -ovn-nbctl ls-add lsw0
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>     -ovn-nbctl --wait=sb sync
>>     -
>>     -
>>     -# Add an ACL that rate-limits logs at 10 per second.
>>     -ovn-nbctl meter-add http-rl1 drop 10 pktps
>>     -ovn-nbctl --log --severity=alert --meter=http-rl1
>>     --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>     -
>>     -# Add an ACL that rate-limits logs at 5 per second.
>>     -ovn-nbctl meter-add http-rl2 drop 5 pktps
>>     -ovn-nbctl --log --severity=alert --meter=http-rl2
>>     --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
>>     -
>>     -# Add an ACL that doesn't rate-limit logs.
>>     -ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0
>>     to-lport 1000 'tcp.dst==82' drop
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -# For each ACL, send 100 packets.
>>     -for i in `seq 1 100`; do
>>     -    ovs-appctl netdev-dummy/receive lp1
>>     
>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)' 
>>
>>     -
>>     -    ovs-appctl netdev-dummy/receive lp1
>>     
>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)' 
>>
>>     -
>>     -    ovs-appctl netdev-dummy/receive lp1
>>     
>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)' 
>>
>>     -done
>>     -
>>     -# The rate at which packets are sent is highly system-dependent,
>>     so we
>>     -# can't count on precise drop counts.  To work around that, we just
>>     -# check that exactly 100 "http-acl3" actions were logged and that
>>     there
>>     -# were more "http-acl1" actions than "http-acl2" ones.
>>     -OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3'
>>     hv/ovn-controller.log) ])
>>     -
>>     -# On particularly slow or overloaded systems, the transmission
>>     rate may
>>     -# be lower than the configured meter rate.  To prevent false test
>>     -# failures, we check the duration count of the meter, and if it's
>>     -# greater than nine seconds, just skip the test.
>>     -d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep
>>     "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
>>     -
>>     -echo "Meter duration: $d_secs"
>>     -AT_SKIP_IF([test $d_secs -gt 9])
>>     -
>>     -# Print some information that may help debugging.
>>     -as hv ovs-appctl -t ovn-controller meter-table-list
>>     -as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
>>     -
>>     -n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
>>     -n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
>>     -n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
>>     -
>>     -AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
>>     -AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
>>     -
>>     -OVN_CLEANUP([hv])
>>     -AT_CLEANUP
>>     -
>>     -
>>     -AT_SETUP([ovn -- DSCP marking and meter check])
>>     -AT_KEYWORDS([ovn])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add lsw0
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp3
>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>     -ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
>>     -ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
>>     -ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
>>     -ovn-nbctl --wait=sb sync
>>     -net_add n1
>>     -sim_add hv
>>     -as hv
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap
>>     options:rxq_pcap=vif1-rx.pcap ofport-request=1
>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>     external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap
>>     options:rxq_pcap=vif2-rx.pcap ofport-request=2
>>     -
>>     -AT_CAPTURE_FILE([trace])
>>     -ovn_trace () {
>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>     -}
>>     -
>>     -# Extracts nw_tos from the final flow from ofproto/trace output
>>     and prints
>>     -# it on stdout.  Prints "none" if no nw_tos was included.
>>     -get_final_nw_tos() {
>>     -    if flow=$(grep '^Final flow:' stdout); then :; else
>>     -       # The output didn't have a final flow.
>>     -       return 99
>>     -    fi
>>     -
>>     -    tos=$(echo "$flow" | sed -n
>>     's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
>>     -    case $tos in
>>     -        '') echo none ;;
>>     -        *) echo $tos ;;
>>     -    esac
>>     -}
>>     -
>>     -# check_tos TOS
>>     -#
>>     -# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set
>>     to TOS.
>>     -check_tos() {
>>     -    # First check with ovn-trace for logical flows.
>>     -    echo "checking for tos $1"
>>     -    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
>>     -     echo 'output("lp2");') > expout
>>     -    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src
>>     == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src ==
>>     1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
>>     -
>>     -    # Then re-check with ofproto/trace for a physical packet.
>>     -    AT_CHECK([ovs-appctl ofproto/trace br-int
>>     
>> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'], 
>>
>>     [0], [stdout-nolog])
>>     -    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
>>     -])
>>     -}
>>     -
>>     -# check at L2
>>     -AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src ==
>>     f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0],
>>     [output("lp2");
>>     -])
>>     -AT_CHECK([ovs-appctl ofproto/trace br-int
>>     'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'],
>>     [0], [stdout-nolog])
>>     -AT_CHECK([get_final_nw_tos], [0], [none
>>     -])
>>     -
>>     -# check at L3 without dscp marking
>>     -check_tos 0
>>     -
>>     -# Mark DSCP with a valid value
>>     -qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS
>>     priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\
>>     is_chassis_resident(\"lp1\")" direction="from-lport" -- set
>>     Logical_Switch lsw0 qos_rules=@lp1-qos)
>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>     -])
>>     -check_tos 48
>>     -
>>     -# check at hv without qos meter
>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>     meter | wc -l], [0], [0
>>     -])
>>     -
>>     -# Update the meter rate
>>     -ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
>>     -
>>     -# check at hv with a qos meter table
>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>     rate=100 | wc -l], [0], [1
>>     -])
>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>     meter | wc -l], [0], [1
>>     -])
>>     -
>>     -# Update the DSCP marking
>>     -ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
>>     -check_tos 63
>>     -
>>     -# Update the meter rate
>>     -ovn-nbctl --wait=hv set QoS $qos_id
>>     bandwidth=rate=4294967295,burst=4294967295
>>     -
>>     -# check at hv with a qos meter table
>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>     burst_size=4294967295 | wc -l], [0], [1
>>     -])
>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>     meter | wc -l], [0], [1
>>     -])
>>     -
>>     -ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\""
>>     direction="to-lport"
>>     -check_tos 63
>>     -
>>     -# Disable DSCP marking
>>     -ovn-nbctl --wait=hv qos-del lsw0
>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
>>     -])
>>     -check_tos 0
>>     -
>>     -# check at hv without qos meter
>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>     meter | wc -l], [0], [0
>>     -])
>>     -
>>     -# check meter with chassis not resident
>>     -ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" &&
>>     is_chassis_resident("lp3")' rate=11123 burst=111230
>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>     -])
>>     -
>>     -# check no meter table
>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>     meter | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>     rate=11123 | wc -l], [0], [0
>>     -])
>>     -
>>     -OVN_CLEANUP([hv])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- read-only sb db:ptcp access])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -
>>     -: > .$1.db.~lock~
>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>     -
>>     -# Add read-only remote to sb ovsdb-server
>>     -AT_CHECK(
>>     -  [ovsdb-tool transact ovn-sb.db \
>>     -     ['["OVN_Southbound",
>>     -       {"op": "insert",
>>     -        "table": "SB_Global",
>>     -        "row": {
>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>     -       {"op": "insert",
>>     -        "table": "Connection",
>>     -        "uuid-name": "xyz",
>>     -        "row": {"target": "ptcp:0:127.0.0.1",
>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>     -
>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock
>>     --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
>>     -
>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>     -
>>     -# read-only accesses should succeed
>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global],
>>     [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list
>>     Connection], [0], [stdout], [ignore])
>>     -
>>     -# write access should fail
>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch
>>     vxlan 1.2.4.8], [1], [ignore],
>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>     allowed when database server is in read only mode","error":"not
>>     allowed"}
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- read-only sb db:pssl access])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>     -\\]"])
>>     -
>>     -: > .$1.db.~lock~
>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>     -
>>     -# Add read-only remote to sb ovsdb-server
>>     -AT_CHECK(
>>     -  [ovsdb-tool transact ovn-sb.db \
>>     -     ['["OVN_Southbound",
>>     -       {"op": "insert",
>>     -        "table": "SB_Global",
>>     -        "row": {
>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>     -       {"op": "insert",
>>     -        "table": "Connection",
>>     -        "uuid-name": "xyz",
>>     -        "row": {"target": "pssl:0:127.0.0.1",
>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>     -
>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>     - --private-key="$PKIDIR/testpki-privkey2.pem" \
>>     - --certificate="$PKIDIR/testpki-cert2.pem" \
>>     - --ca-cert="$PKIDIR/testpki-cacert.pem" \
>>     -                          ovn-sb.db
>>     -
>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>     -
>>     -# read-only accesses should succeed
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -                    list SB_Global], [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -                    list Connection], [0], [stdout], [ignore])
>>     -
>>     -# write access should fail
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>     allowed when database server is in read only mode","error":"not
>>     allowed"}
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- nb connection/ssl commands])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>     -\\]"])
>>     -
>>     -: > .$1.db.~lock~
>>     -ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
>>     -
>>     -# Start nb db server using db connection/ssl entries (unpopulated
>>     initially)
>>     -start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
>>     - --remote=db:OVN_Northbound,NB_Global,connections \
>>     - --private-key=db:OVN_Northbound,SSL,private_key \
>>     - --certificate=db:OVN_Northbound,SSL,certificate \
>>     - --ca-cert=db:OVN_Northbound,SSL,ca_cert \
>>     -                          ovn-nb.db
>>     -
>>     -# Populate SSL configuration entries in nb db
>>     -AT_CHECK(
>>     -    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>     -                       $PKIDIR/testpki-cert.pem \
>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>     [stdout], [ignore])
>>     -
>>     -# Populate a passive SSL connection in nb db
>>     -AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0],
>>     [stdout], [ignore])
>>     -
>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>     -
>>     -# Verify SSL connetivity to nb db server
>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          list NB_Global],
>>     -         [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          list Connection],
>>     -         [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          get-connection],
>>     -         [0], [stdout], [ignore])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- sb connection/ssl commands])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>     -\\]"])
>>     -
>>     -: > .$1.db.~lock~
>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>     -
>>     -# Start sb db server using db connection/ssl entries (unpopulated
>>     initially)
>>     -start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>     - --private-key=db:OVN_Southbound,SSL,private_key \
>>     - --certificate=db:OVN_Southbound,SSL,certificate \
>>     - --ca-cert=db:OVN_Southbound,SSL,ca_cert \
>>     -                          ovn-sb.db
>>     -
>>     -# Populate SSL configuration entries in sb db
>>     -AT_CHECK(
>>     -    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>     -                       $PKIDIR/testpki-cert.pem \
>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>     [stdout], [ignore])
>>     -
>>     -# Populate a passive SSL connection in sb db
>>     -AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0],
>>     [stdout], [ignore])
>>     -
>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>     -
>>     -# Verify SSL connetivity to sb db server
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          list SB_Global],
>>     -         [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          list Connection],
>>     -         [0], [stdout], [ignore])
>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>     -                    --certificate=$PKIDIR/testpki-cert.pem \
>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>     -          get-connection],
>>     -         [0], [stdout], [ignore])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- nested containers])
>>     -ovn_start
>>     -
>>     -# Physical network:
>>     -# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
>>     -
>>     -# Logical network:
>>     -# 3 Logical switches - "mgmt" (172.16.1.0/24
>>     <http://172.16.1.0/24>), "foo" (192.168.1.0/24
>>     <http://192.168.1.0/24>)
>>     -# and "bar" (192.168.2.0/24 <http://192.168.2.0/24>). They are
>>     all connected to router R1.
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl ls-add mgmt
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -
>>     -# Connect mgmt to R1
>>     -ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt
>>     type=router \
>>     -          options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>     type=router \
>>     -          options:router-port=bar addresses=\"00:00:00:01:02:04\"
>>     -
>>     -# "mgmt" has VM1 and VM2 connected
>>     -ovn-nbctl lsp-add mgmt vm1 \
>>     --- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
>>     -
>>     -ovn-nbctl lsp-add mgmt vm2 \
>>     --- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# "foo1" and "foo2" are containers belonging to switch "foo"
>>     -# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as
>>     parent_port.
>>     -ovn-nbctl lsp-add foo foo1 vm1 1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
>>     -
>>     -ovn-nbctl lsp-add foo foo2 vm2 2 \
>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>     -
>>     -# "bar1" and "bar2" are containers belonging to switch "bar"
>>     -# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as
>>     parent_port.
>>     -ovn-nbctl lsp-add bar bar1 vm1 2 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
>>     -
>>     -ovn-nbctl lsp-add bar bar2 vm2 1 \
>>     --- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>>     -
>>     -# bar3 is a standalone VM belonging to switch "bar"
>>     -ovn-nbctl lsp-add bar bar3 \
>>     --- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int vm1 -- \
>>     -    set interface vm1 external-ids:iface-id=vm1 \
>>     -    options:tx_pcap=hv1/vm1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vm1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int bar3 -- \
>>     -    set interface bar3 external-ids:iface-id=bar3 \
>>     -    options:tx_pcap=hv1/bar3-tx.pcap \
>>     -    options:rxq_pcap=hv1/bar3-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int vm2 -- \
>>     -    set interface vm2 external-ids:iface-id=vm2 \
>>     -    options:tx_pcap=hv2/vm2-tx.pcap \
>>     -    options:rxq_pcap=hv2/vm2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and foo2 (same switch, different
>>     HVs and
>>     -# different VLAN tags).
>>     -src_mac="f00000010205"
>>     -dst_mac="f00000010206"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at foo2
>>     
>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet > expected
>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>     -
>>     -# Send ip packets between foo1 and bar2 (different switch,
>>     different HV)
>>     -src_mac="f00000010205"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at bar2
>>     -src_mac="000000010204"
>>     -dst_mac="f00000010208"
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet >> expected
>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>     -
>>     -# Send ip packets between foo1 and bar1
>>     -# (different switch, loopback to same vm but different tag)
>>     -src_mac="f00000010205"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at bar1
>>     -src_mac="000000010204"
>>     -dst_mac="f00000010207"
>>     
>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet > expected1
>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>     -
>>     -# Send ip packets between bar1 and bar3
>>     -# (same switch. But one is container and another is a standalone VM)
>>     -src_mac="f00000010207"
>>     -dst_mac="f00000010209"
>>     -src_ip=`ip_to_hex 192 168 2 2`
>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>     
>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at bar3
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet > expected
>>     -OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
>>     -
>>     -# Send ip packets between foo1 and vm1.
>>     -(different switch, container to the VM hosting it.)
>>     -src_mac="f00000010205"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at vm1
>>     -src_mac="000000010202"
>>     -dst_mac="f00000010203"
>>     
>> -packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet >> expected1
>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>     -
>>     -# Send packets from vm1 to bar1.
>>     -(different switch, A hosting VM to a container inside it)
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010202"
>>     -src_ip=`ip_to_hex 172 16 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at vm1
>>     -src_mac="000000010204"
>>     -dst_mac="f00000010207"
>>     
>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo  $packet >> expected1
>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>     -
>>     -# Send broadcast packet from foo1. foo1 should not receive the
>>     same packet.
>>     -src_mac="f00000010205"
>>     -dst_mac="ffffffffffff"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>     
>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>     -
>>     -# expected packet at VM1
>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based
>>     routes])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>     LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and bar
>>     -# (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>     -#
>>     -# R2 and R3 are gateway routers.
>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and R3 has
>>     bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>     -# connected to it. Note how both alice and bob have the same
>>     subnet behind it.
>>     -# We are trying to simulate external network via those 2
>>     switches. In real
>>     -# world the switch ports of these switches will have addresses
>>     set as "unknown"
>>     -# to make them learning switches. Or those switches will be
>>     "localnet" ones.
>>     -
>>     -# Create three hypervisors and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=bar1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>     -    set interface hv3-vif1 external-ids:iface-id=bob1 \
>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>     -ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add bob
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>     type=router \
>>     -    options:router-port=bar addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect bob to R3
>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>     <http://172.16.1.2/24>
>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>     -    type=router options:router-port=bob
>>     addresses=\"00:00:03:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Connect R3 to join
>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>     <http://20.0.0.3/24>
>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>>     -    type=router options:router-port=R3_join
>>     addresses='"00:00:04:01:02:05"'
>>     -
>>     -# Install static routes with source ip address as the policy for
>>     routing.
>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>     go via R3.
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>     <http://192.168.1.0/24> 20.0.0.2
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>     <http://192.168.2.0/24> 20.0.0.3
>>     -
>>     -# Install static routes with destination ip address as the policy
>>     for routing.
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port bar1 in bar
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
>>     -
>>     -# Create logical port bob1 in bob
>>     -ovn-nbctl lsp-add bob bob1 \
>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -# Send ip packets between foo1 and bar1
>>     -# (East-west traffic should flow normally)
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>     -
>>     -# Send ip packets between bar1 and bob1
>>     -src_mac="f00000010204"
>>     -dst_mac="000001010204"
>>     -src_ip=`ip_to_hex 192 168 2 2`
>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>     -#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
>>     -
>>     -# Packet to expect at bar1
>>     -src_mac="000001010204"
>>     -dst_mac="f00000010204"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo $expected > expected
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -
>>     -# Packet to Expect at alice1
>>     -src_mac="000002010203"
>>     -dst_mac="f00000010205"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo $expected > expected
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Packet to Expect at bob1
>>     -src_mac="000003010203"
>>     -dst_mac="f00000010206"
>>     -src_ip=`ip_to_hex 192 168 2 2`
>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>
>>     -echo $expected > expected
>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>     10.0.0.4 aef0::4"
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>     10.0.0.6 20.0.0.4"
>>     -
>>     -DNS1=`ovn-nbctl create DNS records={}`
>>     -DNS2=`ovn-nbctl create DNS records={}`
>>     -
>>     -ovn-nbctl set DNS $DNS1 records:vm1.ovn.org
>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>     -ovn-nbctl set DNS $DNS1 records:vm2.ovn.org
>>     <http://vm2.ovn.org>="10.0.0.6 20.0.0.4"
>>     -ovn-nbctl set DNS $DNS2 records:vm3.ovn.org
>>     <http://vm3.ovn.org>="40.0.0.4"
>>     -
>>     -ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -OVN_POPULATE_ARP
>>     -sleep 2
>>     -as hv1 ovs-vsctl show
>>     -
>>     -echo "*************************"
>>     -ovn-sbctl list DNS
>>     -echo "*************************"
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -# set_dns_params host_name
>>     -# Sets the dns_req_data and dns_resp_data
>>     -set_dns_params() {
>>     -    local hname=$1
>>     -    local ttl=00000e10
>>     -    an_count=0001
>>     -    type=0001
>>     -    case $hname in
>>     -    vm1)
>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>     -        query_name=03766d31036f766e036f726700
>>     -        # IPv4 address - 10.0.0.4
>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>     -        ;;
>>     -    vm2)
>>     -        # vm2.ovn.org <http://vm2.ovn.org>
>>     -        query_name=03766d32036f766e036f726700
>>     -        # IPv4 address - 10.0.0.6
>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000006
>>     -        # IPv4 address - 20.0.0.4
>>     -
>>     
>> expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004 
>>
>>     -        an_count=0002
>>     -        ;;
>>     -    vm3)
>>     -        # vm3.ovn.org <http://vm3.ovn.org>
>>     -        query_name=03766d33036f766e036f726700
>>     -        # IPv4 address - 40.0.0.4
>>     - expected_dns_answer=${query_name}00010001${ttl}000428000004
>>     -        ;;
>>     -    vm1_ipv6_only)
>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>     -        query_name=03766d31036f766e036f726700
>>     -        # IPv6 address - aef0::4
>>     -        type=001c
>>     -
>>     
>> expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004 
>>
>>     -        ;;
>>     -    vm1_ipv4_v6)
>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>     -        query_name=03766d31036f766e036f726700
>>     -        type=00ff
>>     -        an_count=0002
>>     -        # IPv4 address - 10.0.0.4
>>     -        # IPv6 address - aef0::4
>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>     -
>>     
>> expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
>>     -
>>     
>> expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004 
>>
>>     -        ;;
>>     -    vm1_invalid_type)
>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>     -        query_name=03766d31036f766e036f726700
>>     -        # IPv6 address - aef0::4
>>     -        type=0002
>>     -        ;;
>>     -    vm1_incomplete)
>>     -        # set type to none
>>     -        type=''
>>     -    esac
>>     -    # TTL - 3600
>>     -    local dns_req_header=010201200001000000000000
>>     -    local dns_resp_header=010281200001${an_count}00000000
>>     -    dns_req_data=${dns_req_header}${query_name}${type}0001
>>     -
>>     
>> dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} 
>>
>>     -}
>>     -
>>     -# This shell function sends a DNS request packet
>>     -# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
>>     -test_dns() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     dns_reply=$6
>>     -    local dns_query_data=$7
>>     -    shift; shift; shift; shift; shift; shift; shift;
>>     -    # Packet size => IPv4 header (20) + UDP header (8) +
>>     -    #                DNS data (header + query)
>>     -    ip_len=`expr 28 + ${#dns_query_data} / 2`
>>     -    udp_len=`expr $ip_len - 20`
>>     -    ip_len=$(printf "%x" $ip_len)
>>     -    udp_len=$(printf "%x" $udp_len)
>>     -    local
>>     request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
>>     - request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
>>     -    # dns data
>>     -    request=${request}${dns_query_data}
>>     -
>>     -    if test $dns_reply != 0; then
>>     -        local dns_reply=$1
>>     -        ip_len=`expr 28 + ${#dns_reply} / 2`
>>     -        udp_len=`expr $ip_len - 20`
>>     -        ip_len=$(printf "%x" $ip_len)
>>     -        udp_len=$(printf "%x" $udp_len)
>>     -        local
>>     reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
>>     - 
>> reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
>>     -        echo $reply >> $inport.expected
>>     -    else
>>     -        for outport; do
>>     -            echo $request >> $outport.expected
>>     -        done
>>     -    fi
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>     -}
>>     -
>>     -test_dns6() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     dns_reply=$6
>>     -    local dns_query_data=$7
>>     -    shift; shift; shift; shift; shift; shift; shift;
>>     -    # Packet size => UDP header (8) +
>>     -    #                DNS data (header + query)
>>     -    ip_len=`expr 8 + ${#dns_query_data} / 2`
>>     -    udp_len=$ip_len
>>     -    ip_len=$(printf "%x" $ip_len)
>>     -    udp_len=$(printf "%x" $udp_len)
>>     -    local
>>     
>> request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
>>     -    request=${request}9234003500${udp_len}0000
>>     -    #dns data
>>     -    request=${request}${dns_query_data}
>>     -
>>     -    if test $dns_reply != 0; then
>>     -        local dns_reply=$1
>>     -        ip_len=`expr 8 + ${#dns_reply} / 2`
>>     -        udp_len=$ip_len
>>     -        ip_len=$(printf "%x" $ip_len)
>>     -        udp_len=$(printf "%x" $udp_len)
>>     -        local
>>     
>> reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
>>     -        reply=${reply}0035923400${udp_len}0000${dns_reply}
>>     -        echo $reply >> $inport.expected
>>     -    else
>>     -        for outport; do
>>     -            echo $request >> $outport.expected
>>     -        done
>>     -    fi
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>     -}
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>     -
>>     -set_dns_params vm2
>>     -src_ip=`ip_to_hex 10 0 0 4`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=1
>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 1.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap > 1.packets
>>     -cat 1.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 1.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -set_dns_params vm1
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=1
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Clear the query name options for ls1-lp2
>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
>>     <http://vm2.ovn.org>
>>     -
>>     -set_dns_params vm2
>>     -src_ip=`ip_to_hex 10 0 0 4`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=0
>>     -test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply
>>     $dns_req_data
>>     -
>>     -# NXT_RESUMEs should be 3.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap > 1.packets
>>     -AT_CHECK([cat 1.packets], [0], [])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Clear the query name for ls1-lp1
>>     -# Since ls1 has no query names configued,
>>     -# ovn-northd should not add the DNS flows.
>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
>>     <http://vm1.ovn.org>
>>     -
>>     -set_dns_params vm1
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=0
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data
>>     -
>>     -# NXT_RESUMEs should be 3 only.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Test IPv6 (AAAA records) using IPv4 packet.
>>     -# Add back the DNS options for ls1-lp1.
>>     -ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org
>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>     -
>>     -set_dns_params vm1_ipv6_only
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=1
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 4.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
>>     -set_dns_params vm1_ipv4_v6
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=1
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 5.
>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -cat 2.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 2.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Invalid type.
>>     -set_dns_params vm1_invalid_type
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=0
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data
>>     -
>>     -# NXT_RESUMEs should be 6.
>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Incomplete DNS packet.
>>     -set_dns_params vm1_incomplete
>>     -src_ip=`ip_to_hex 10 0 0 6`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=0
>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data
>>     -
>>     -# NXT_RESUMEs should be 7.
>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Add one more DNS record to the ls1.
>>     -ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
>>     -
>>     -set_dns_params vm3
>>     -src_ip=`ip_to_hex 10 0 0 4`
>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>     -dns_reply=1
>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 8.
>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap > 1.packets
>>     -cat 1.expected | cut -c -48 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat 1.expected | cut -c 53- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -# Try DNS query over IPv6
>>     -set_dns_params vm1
>>     -src_ip=aef00000000000000000000000000004
>>     -dst_ip=aef00000000000000000000000000001
>>     -dns_reply=1
>>     -test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>     $dns_req_data $dns_resp_data
>>     -
>>     -# NXT_RESUMEs should be 9.
>>     -OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap > 1.packets
>>     -# Skipping the UDP checksum.
>>     -cat 1.expected | cut -c 1-120,125- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
>>     -
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -rm -f 1.expected
>>     -rm -f 2.expected
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA
>>     distributed router gateway port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add gw1
>>     -as gw1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -sim_add gw2
>>     -as gw2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.4
>>     -
>>     -sim_add ext1
>>     -as ext1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add outside
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl \
>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>     -                                     chassis_name=gw1 \
>>     -                                     priority=20 -- \
>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>     -                                     chassis_name=gw2 \
>>     -                                     priority=10 -- \
>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port outside1 in outside
>>     -ovn-nbctl lsp-add outside outside1 \
>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# Create localnet port in alice
>>     -ovn-nbctl lsp-add alice ln-alice
>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>     -# mapping to the external network, is the one generating packets
>>     -as gw1 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -as gw2 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -as ext1 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 2
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -test_ip_packet()
>>     -{
>>     -    local active_gw=$1
>>     -    local backup_gw=$2
>>     -    local backup_vswitchd_dead=$3
>>     -
>>     -    # Send ip packet between foo1 and outside1
>>     -    src_mac="f00000010203" # foo1 mac
>>     -    dst_mac="000001010203" # rp-foo mac (internal router leg)
>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -    # ARP request packet to expect at outside1
>>     -
>>     
>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -    # Send ARP reply from outside1 back to the router
>>     -    # XXX: note, we could avoid this if we plug this port into a
>>     netns
>>     -    # and setup the IP address into the port, so the kernel would
>>     simply reply
>>     -    src_mac="000002010203"
>>     -    reply_mac="f00000010204"
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>     -
>>     
>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>
>>     -
>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>     -
>>     -    OVS_WAIT_UNTIL([
>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>     table=66 | \
>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>     -    ])
>>     -
>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>     -    src_mac="000002010203"
>>     -    dst_mac="f00000010204"
>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -
>>     
>> expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -    echo $expected > ext1-vif1.expected
>>     -
>>     
>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>
>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>>     -
>>     -    if test $backup_vswitchd_dead != 1; then
>>     -        # Reset the file only if vswitchd in backup gw is alive
>>     -        as $backup_gw reset_pcap_file br-phys_n1
>>     $backup_gw/br-phys_n1
>>     -    fi
>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>     -
>>     -    # Resend packet from foo1 to outside1
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -    sleep 1
>>     -
>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap  > packets
>>     -    cat packets | grep $expected > exp
>>     -    # Its possible that $active_gw/br-phys_n1-tx.pcap may have
>>     received multiple
>>     -    # garp packets. So consider only the first packet.
>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>     -    AT_CHECK([cat exp], [0], [expout])
>>     -    rm -f expout
>>     -    if test $backup_vswitchd_dead != 1; then
>>     -        # Check for backup gw only if vswitchd is alive
>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap  > packets
>>     -        AT_CHECK([grep $expected packets | sort], [0], [])
>>     -    fi
>>     -}
>>     -
>>     -test_ip_packet gw1 gw2 0
>>     -
>>     -ovn-nbctl --timeout=3 --wait=hv \
>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>     -                                     chassis_name=gw1 \
>>     -                                     priority=10 -- \
>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>     -                                     chassis_name=gw2 \
>>     -                                     priority=20 -- \
>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -test_ip_packet gw2 gw1 0
>>     -
>>     -# Get the claim count of both gw1 and gw2.
>>     -gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log |
>>     wc -l`
>>     -gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log |
>>     wc -l`
>>     -
>>     -# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
>>     -as gw2
>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>     -
>>     -# gw1 should claim the cr-alice and the claim count of gw1 should be
>>     -# incremented by 1.
>>     -gw1_claim_ct=$((gw1_claim_ct+1))
>>     -
>>     -OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
>>     -| grep -c "cr-alice: Claiming"`])
>>     -
>>     -AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
>>     -grep -c "cr-alice: Claiming"`])
>>     -
>>     -test_ip_packet gw1 gw2 1
>>     -
>>     -as gw2
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>     -
>>     -OVN_CLEANUP([hv1],[gw1],[ext1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA
>>     distributed router gateway port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add gw1
>>     -as gw1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -sim_add gw2
>>     -as gw2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.4
>>     -
>>     -sim_add ext1
>>     -as ext1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -ovn-nbctl create Logical_Router name=R0
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add join
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add outside
>>     -
>>     -#Connect foo to R0
>>     -ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
>>     -    type=router options:router-port=R0-foo \
>>     -    -- lsp-set-addresses foo-R0 router
>>     -
>>     -#Connect R0 to join
>>     -ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
>>     <http://100.60.1.1/24>
>>     -ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port join-R0 \
>>     -    type=router options:router-port=R0-join \
>>     -    -- lsp-set-addresses join-R0 router
>>     -
>>     -#Connect join to R1
>>     -ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
>>     <http://100.60.1.2/24>
>>     -ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port join-R1 \
>>     -    type=router options:router-port=R1-join \
>>     -    -- lsp-set-addresses join-R1 router
>>     -
>>     -#add route rules
>>     -ovn-nbctl lr-route-add R0 0.0.0.0/0 <http://0.0.0.0/0> 100.60.1.2
>>     -ovn-nbctl lr-route-add R1 192.168.0.0/16 <http://192.168.0.0/16>
>>     100.60.1.1
>>     -
>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -
>>     -ovn-nbctl \
>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>     -                                     chassis_name=gw1 \
>>     -                                     priority=20 -- \
>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>     -                                     chassis_name=gw2 \
>>     -                                     priority=10 -- \
>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port outside1 in outside
>>     -ovn-nbctl lsp-add outside outside1 \
>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# Create localnet port in alice
>>     -ovn-nbctl lsp-add alice ln-alice
>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>     -# mapping to the external network, is the one generating packets
>>     -as gw1 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -as gw2 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -as ext1 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>     -
>>     -# hv1 should be in 'ref_chassis' of the ha_chasssi_group as logical
>>     -# switch 'foo' can reach the router 'R1' (which has gw router port)
>>     -# via foo1 -> foo -> R0 -> join -> R1
>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="hv1"`
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$hv1_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 2
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -test_ip_packet()
>>     -{
>>     -    local active_gw=$1
>>     -    local backup_gw=$2
>>     -
>>     -    # Send ip packet between foo1 and outside1
>>     -    src_mac="f00000010203" # foo1 mac
>>     -    dst_mac="000001010203" # foo-R0 mac (internal router leg)
>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -    # ARP request packet to expect at outside1
>>     -
>>     
>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -    # Send ARP reply from outside1 back to the router
>>     -    # XXX: note, we could avoid this if we plug this port into a
>>     netns
>>     -    # and setup the IP address into the port, so the kernel would
>>     simply reply
>>     -    src_mac="000002010203"
>>     -    reply_mac="f00000010204"
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>     -
>>     
>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>
>>     -
>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>     -
>>     -    OVS_WAIT_UNTIL([
>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>     table=66 | \
>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>     -    ])
>>     -
>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>     -    src_mac="000002010203"
>>     -    dst_mac="f00000010204"
>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>     -
>>     
>> expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>
>>     -    echo $expected > ext1-vif1.expected
>>     -
>>     
>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>
>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>     -
>>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>>     -    as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>     -
>>     -    # Resend packet from foo1 to outside1
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap  > packets
>>     -    cat packets | grep $expected > exp
>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>     -    AT_CHECK([cat exp], [0], [expout])
>>     -
>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap  > packets
>>     -    AT_CHECK([grep $expected packets | sort], [0], [])
>>     -}
>>     -
>>     -test_ip_packet gw1 gw2
>>     -
>>     -ovn-nbctl --timeout=3 --wait=hv \
>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>     -                                     chassis_name=gw1 \
>>     -                                     priority=10 -- \
>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>     -                                     chassis_name=gw2 \
>>     -                                     priority=20 -- \
>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -test_ip_packet gw2 gw1
>>     -
>>     -OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 1 LR with distributed router gateway port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR R1 that has switches foo (192.168.1.0/24
>>     <http://192.168.1.0/24>) and
>>     -# alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>     The logical port
>>     -# between R1 and alice has a "redirect-chassis" specified,
>>     -# i.e. it is the distributed router gateway port.
>>     -# Switch alice also has a localnet port defined.
>>     -# An additional switch outside has a localnet port and the
>>     -# same subnet as alice (172.16.1.0/24 <http://172.16.1.0/24>).
>>     -
>>     -# Physical network:
>>     -# Three hypervisors hv[123].
>>     -# hv1 hosts vif foo1.
>>     -# hv2 is the "redirect-chassis" that hosts the distributed
>>     -# router gateway port.
>>     -# hv3 hosts vif outside1.
>>     -# In order to show that connectivity works only through hv2,
>>     -# an initial round of tests is run without any bridge-mapping
>>     -# defined for the localnet on hv2.  These tests are expected
>>     -# to fail.
>>     -# Subsequent tests are run after defining the bridge-mapping
>>     -# for the localnet on hv2. These tests are expected to succeed.
>>     -
>>     -# Create three hypervisors and create OVS ports corresponding
>>     -# to logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -# 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
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add outside
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24> \
>>     -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port outside1 in outside
>>     -ovn-nbctl lsp-add outside outside1 \
>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# Create localnet port in alice
>>     -ovn-nbctl lsp-add alice ln-alice
>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
>>     -as hv1 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -as hv3 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 2
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -ovn-sbctl list chassis
>>     -ovn-sbctl list encap
>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>     -ovn-sbctl list Gateway_Chassis
>>     -echo "------ Port_Binding chassisredirect -------"
>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>     -echo "-------------------------------------------"
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -echo "------ hv3 dump ----------"
>>     -as hv3 ovs-ofctl show br-int
>>     -as hv3 ovs-ofctl dump-flows br-int
>>     -echo "--------------------------"
>>     -
>>     -
>>     -# Check that redirect mapping is programmed only on hv2
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep
>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep
>>     =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
>>     -])
>>     -# Check that hv1 sends chassisredirect port traffic to hv2
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep
>>     =0x3,metadata=0x1 | grep output | wc -l], [0], [1
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep
>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>     -])
>>     -# Check that arp reply on distributed gateway port is only
>>     programmed on hv2
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep
>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep
>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
>>     -])
>>     -
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -
>>     -: > hv2-vif1.expected
>>     -: > hv3-vif1.expected
>>     -
>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>     -#
>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>     provided, then
>>     -# it should be the hardware address of the target to expect to
>>     receive in an
>>     -# ARP reply; otherwise no reply is expected.
>>     -#
>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>     -# SHA and REPLY_HA are each 12 hex digits.
>>     -# SPA and TPA are each 8 hex digits.
>>     -test_arp() {
>>     -    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
>>     -    local
>>     
>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>
>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>     $request
>>     -
>>     -    if test X$reply_ha != X; then
>>     -        # Expect to receive the reply, if any.
>>     -        local
>>     
>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>>     -        echo $reply >> hv${hv}-vif$inport.expected
>>     -    fi
>>     -}
>>     -
>>     -rtr_ip=$(ip_to_hex 172 16 1 1)
>>     -foo_ip=$(ip_to_hex 192 168 1 2)
>>     -outside_ip=$(ip_to_hex 172 16 1 3)
>>     -
>>     -echo $rtr_ip
>>     -echo $foo_ip
>>     -echo $outside_ip
>>     -
>>     -# ARP for router IP address from outside1, no response expected
>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>     -
>>     -# Send ip packet between foo1 and outside1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>     -
>>     -# Now add bridge-mappings on hv2, which should make everything work
>>     -as hv2 ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>     to br-phys
>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>     -grep "Port patch-br-int-to-ln-alice" | wc -l`])
>>     -
>>     -# ARP for router IP address from outside1
>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
>>     -
>>     -# hv3-vif1.expected should also have the gw router port garp packet.
>>     
>> -exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>
>>     -echo $exp_gw_ip_garp >> hv3-vif1.expected
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>     -
>>     -# Send ip packet between foo1 and outside1
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -# Packet to Expect at outside1
>>     -src_mac="000002010203"
>>     -dst_mac="f00000010204"
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -echo "------ hv1 dump ----------"
>>     -as hv1 ovs-ofctl show br-int
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -echo "------ hv2 dump ----------"
>>     -as hv2 ovs-ofctl show br-int
>>     -as hv2 ovs-ofctl dump-flows br-int
>>     -echo "------ hv3 dump ----------"
>>     -as hv3 ovs-ofctl show br-int
>>     -as hv3 ovs-ofctl dump-flows br-int
>>     -echo "----------------------------"
>>     -
>>     -echo $expected >> hv3-vif1.expected
>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>     -
>>     -#Check ovn-trace over "chassisredirect" port
>>     -AT_CAPTURE_FILE([trace])
>>     -ovn_trace () {
>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>     -}
>>     -
>>     -echo 'ip.ttl--;' > expout
>>     -echo 'eth.src = 00:00:02:01:02:03;' >> expout
>>     -echo 'eth.dst = f0:00:00:01:02:04;' >> expout
>>     -echo 'output("ln-alice");' >> expout
>>     -AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src ==
>>     f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src ==
>>     192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0],
>>     [expout])
>>     -
>>     -# Create logical port alice1 in alice on hv1
>>     -as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
>>     -
>>     -# Create logical port foo2 in foo on hv2
>>     -as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=foo2 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovn-nbctl lsp-add foo foo2 \
>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -: > hv1-vif2.expected
>>     -
>>     -# Send ip packet between alice1 and foo2
>>     -src_mac="f00000010205"
>>     -dst_mac="000002010203"
>>     -src_ip=`ip_to_hex 172 16 1 4`
>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>     -
>>     -# Packet to Expect at foo2
>>     -src_mac="000001010203"
>>     -dst_mac="f00000010206"
>>     -src_ip=`ip_to_hex 172 16 1 4`
>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>     
>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -echo $expected >> hv2-vif1.expected
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
>>     -
>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding
>>     logical_port=cr-alice | wc -l], [0], [1
>>     -])
>>     -
>>     -ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice
>>     options redirect-chassis
>>     -
>>     -AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc
>>     -l], [0], [0
>>     -])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed
>>     router])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -# Create logical switches
>>     -ovn-nbctl ls-add ls0
>>     -ovn-nbctl ls-add ls1
>>     -# Create distributed router
>>     -ovn-nbctl create Logical_Router name=lr0
>>     -# Add distributed gateway port to distributed router
>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>     <http://192.168.0.1/24> \
>>     -    -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>     -    type=router options:router-port=lrp0 addresses="router"
>>     -# Add router port to ls1
>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>     <http://10.0.0.1/24>
>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>>     -    type=router options:router-port=lrp1 addresses="router"
>>     -# Add logical ports for NAT rules
>>     -ovn-nbctl lsp-add ls1 foo1 \
>>     --- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
>>     -ovn-nbctl lsp-add ls1 foo2 \
>>     --- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
>>     -# Add nat-addresses option
>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="router"
>>     -# Add NAT rules
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>     <http://10.0.0.0/24>])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3
>>     10.0.0.3 foo1 f0:00:00:00:00:03])
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4
>>     10.0.0.4 foo2 f0:00:00:00:00:04])
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -# Initially test with no bridge-mapping on hv2, expect to receive
>>     no packets
>>     -
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -# Initially test with no bridge-mapping on hv3
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port
>>     network_name=physnet1])
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 2
>>     -
>>     -# Expect no packets when hv2 bridge-mapping is not present
>>     -: > packets
>>     -OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
>>     -
>>     -# Add bridge-mapping on hv2
>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -
>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>     to br-phys
>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>     -
>>     -# Wait for packets to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>
>>     -echo $expected > expout
>>     
>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>
>>     -echo $expected >> expout
>>     -AT_CHECK([sort packets], [0], [expout])
>>     -sort packets | cat
>>     -
>>     -# Temporarily remove nat-addresses option to avoid race conditions
>>     -# due to GARP backoff
>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses=""
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>     -
>>     -# Add OVS ports for foo1 and foo2 on hv3
>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>     -    set interface hv3-vif1 external-ids:iface-id=foo1 \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv3-vif2 -- \
>>     -    set interface hv3-vif2 external-ids:iface-id=foo2 \
>>     -    ofport-request=2
>>     -
>>     -# Add bridge-mapping on hv3
>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -
>>     -# Wait until the patch ports are created in hv3 to connect br-int
>>     to br-phys
>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>     -
>>     -# Re-add nat-addresses option
>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="router"
>>     -
>>     -# Wait for packets to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>     
>> -garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003" 
>>
>>     -echo $garp_1 > expout
>>     
>> -garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004" 
>>
>>     -echo $garp_2 >> expout
>>     -
>>     -cat packets | grep $garp_1 | head -1 > exp
>>     -cat packets | grep $garp_2 | head -1 >> exp
>>     -AT_CHECK([cat exp], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# VLAN traffic for external network redirected through
>>     distributed router
>>     -# gateway port should use vlans(i.e input network vlan tag)
>>     across hypervisors
>>     -# instead of tunneling.
>>     -AT_SETUP([ovn -- vlan traffic for external network with
>>     distributed router gateway port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# # One LR R1 that has switches foo (192.168.1.0/24
>>     <http://192.168.1.0/24>) and
>>     -# # alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>     it.  The logical port
>>     -# # between R1 and alice has a "redirect-chassis" specified,
>>     -# # i.e. it is the distributed router gateway port(172.16.1.6).
>>     -# # Switch alice also has a localnet port defined.
>>     -# # An additional switch outside has the same subnet as alice
>>     -# # (172.16.1.0/24 <http://172.16.1.0/24>), a localnet port and
>>     nexthop port(172.16.1.1)
>>     -# # which will receive the packet destined for external network
>>     -# # (i.e 8.8.8.8 as destination ip).
>>     -
>>     -# Physical network:
>>     -# # Four hypervisors hv[1234].
>>     -# # hv1 hosts vif foo1.
>>     -# # hv2 is the "redirect-chassis" that hosts the distributed
>>     router gateway port.
>>     -# # Later to test GARPs for the router port - foo, hv2 and hv4
>>     are added to the ha_chassis_group
>>     -# # hv3 hosts nexthop port vif outside1.
>>     -# # All other tests connect hypervisors to network n1 through
>>     br-phys for tunneling.
>>     -# # But in this test, hv1 won't connect to n1(and no br-phys in
>>     hv1), and
>>     -# # in order to show vlans(instead of tunneling) used between hv1
>>     and hv2,
>>     -# # a new network n2 created and hv1 and hv2 connected to this
>>     network through br-ex.
>>     -# # hv2 and hv3 are still connected to n1 network through br-phys.
>>     -net_add n1
>>     -
>>     -# We are not calling ovn_attach for hv1, to avoid adding br-phys.
>>     -# Tunneling won't work in hv1 as ovn-encap-ip is not added to any
>>     bridge in hv1
>>     -sim_add hv1
>>     -as hv1
>>     -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,vxlan \
>>     -    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
>>     -    -- add-br br-int \
>>     -    -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true \
>>     -    -- set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=public:br-ex
>>     -
>>     -start_daemon ovn-controller
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>     -
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings="phys:br-phys"
>>     -
>>     -sim_add hv4
>>     -as hv4
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.4
>>     -ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>     -
>>     -# Create network n2 for vlan connectivity between hv1 and hv2
>>     -net_add n2
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-ex
>>     -net_attach n2 br-ex
>>     -
>>     -as hv2
>>     -ovs-vsctl add-br br-ex
>>     -net_attach n2 br-ex
>>     -
>>     -as hv4
>>     -ovs-vsctl add-br br-ex
>>     -net_attach n2 br-ex
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add outside
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect alice to R1 as distributed router gateway port
>>     (172.16.1.6) on hv2
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24
>>     <http://172.16.1.6/24> \
>>     -    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router \
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port outside1 in outside, which is a nexthop 
>> address
>>     -# for 172.16.1.0/24 <http://172.16.1.0/24>
>>     -ovn-nbctl lsp-add outside outside1 \
>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
>>     -
>>     -# Set default gateway (nexthop) to 172.16.1.1
>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>"
>>     172.16.1.1 alice
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24
>>     <http://192.168.1.1/24>])
>>     -ovn-nbctl set Logical_Switch_Port rp-alice
>>     options:nat-addresses=router
>>     -
>>     -ovn-nbctl lsp-add foo ln-foo
>>     -ovn-nbctl lsp-set-addresses ln-foo unknown
>>     -ovn-nbctl lsp-set-options ln-foo network_name=public
>>     -ovn-nbctl lsp-set-type ln-foo localnet
>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
>>     -
>>     -# Create localnet port in alice
>>     -ovn-nbctl lsp-add alice ln-alice
>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -# Check that there is a logical flow in logical switch foo's 
>> pipeline
>>     -# to set the outport to rp-foo (which is expected).
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>     ls_in_l2_lkup | \
>>     -grep rp-foo | grep -v is_chassis_resident | wc -l`])
>>     -
>>     -# Set the option 'reside-on-redirect-chassis' for foo
>>     -ovn-nbctl set logical_router_port foo
>>     options:reside-on-redirect-chassis=true
>>     -# Check that there is a logical flow in logical switch foo's 
>> pipeline
>>     -# to set the outport to rp-foo with the condition
>>     is_chassis_redirect.
>>     -ovn-sbctl dump-flows foo
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>     ls_in_l2_lkup | \
>>     -grep rp-foo | grep is_chassis_resident | wc -l`])
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list nat
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -ovn-sbctl list chassis
>>     -echo "---------------------"
>>     -
>>     -for chassis in hv1 hv2 hv3; do
>>     -    as $chassis
>>     -    echo "------ $chassis dump ----------"
>>     -    ovs-vsctl show br-int
>>     -    ovs-ofctl show br-int
>>     -    ovs-ofctl dump-flows br-int
>>     -    echo "--------------------------"
>>     -done
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -foo1_ip=$(ip_to_hex 192 168 1 2)
>>     -gw_ip=$(ip_to_hex 172 16 1 6)
>>     -dst_ip=$(ip_to_hex 8 8 8 8)
>>     -nexthop_ip=$(ip_to_hex 172 16 1 1)
>>     -
>>     -foo1_mac="f00000010203"
>>     -foo_mac="000001010203"
>>     -gw_mac="000002010203"
>>     -nexthop_mac="f00000010204"
>>     -
>>     -# Send ip packet from foo1 to 8.8.8.8
>>     -src_mac="f00000010203"
>>     -dst_mac="000001010203"
>>     
>> -packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -# Wait for GARPs announcing gw IP to arrive
>>     -OVS_WAIT_UNTIL([
>>     -    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>     -    ])
>>     -
>>     -# VLAN tagged packet with router port(192.168.1.1) MAC as
>>     destination MAC
>>     -# is expected on bridge connecting hv1 and hv2
>>     
>> -expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>
>>     -echo $expected > hv1-br-ex_n2.expected
>>     -
>>     -# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
>>     -# As connection tracking not enabled for this test, snat can't be
>>     done on the packet.
>>     -# We still see foo1 as the source ip address. But source
>>     mac(gateway MAC) and
>>     -# dest mac(nexthop mac) are properly configured.
>>     
>> -expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000 
>>
>>     -echo $expected > hv3-vif1.expected
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
>>     -as hv3 reset_pcap_file hv3-vif1 hv3/vif1
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -sleep 2
>>     -
>>     -# On hv1, table 32 check that no packet goes via the tunnel port
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
>>     -| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -ip_packet() {
>>     -    grep "1010203f00000010203"
>>     -}
>>     -
>>     -# Check vlan tagged packet on the bridge connecting hv1 and hv2
>>     with the
>>     -# foo1's mac.
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
>>     -cat hv1-br-ex_n2.expected > expout
>>     -AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
>>     -
>>     -# Check expected packet on nexthop interface
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
>>     -cat hv3-vif1.expected > expout
>>     -AT_CHECK([sort hv3-vif1], [0], [expout])
>>     -
>>     -# Test the GARP for the router port ip - 192.168.1.1
>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>     -
>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>     -
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
>>     -
>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>     ha_chassis_group name=hagrp1`
>>     -ovn-nbctl remove logical_router_port alice options redirect-chassis
>>     -ovn-nbctl --wait=sb set logical_router_port alice
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -# When hv2 claims the gw router port cr-alice, it should send out
>>     -# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
>>     -
>>     -# foo1 (on hv1) should receive GARP without VLAN tag
>>     
>> -exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101" 
>>
>>     -echo $exp_garp_on_foo1 > foo1.expout
>>     -
>>     -# ovn-controller on hv2 should send garp with VLAN tag
>>     
>> -sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101" 
>>
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>     -# Wait until we receive atleast 1 packet
>>     -OVS_WAIT_UNTIL([test 1=`$PYTHON
>>     "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-ex_n2-tx.pcap | wc -l`])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-ex_n2-tx.pcap | head -1 > packets
>>     -echo $sent_garp > expout
>>     -AT_CHECK([cat packets], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv4/br-ex_n2-tx.pcap > empty
>>     -AT_CHECK([cat empty], [0], [])
>>     -
>>     -# Make hv4 master
>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
>>     -
>>     -# Wait till cr-alice is claimed by hv4
>>     -hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>> name=hv4)
>>     -# check that the chassis redirect port has been claimed by the
>>     gw1 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -# Reset the pcap file for hv2/br-ex_n2. From now on
>>     ovn-controller in hv2
>>     -# should not send GARPs for the router ports.
>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>     -
>>     -echo $sent_garp > br-ex_n2.expout
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>     -OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
>>     -
>>     -sleep 2
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-ex_n2-tx.pcap > empty
>>     -AT_CHECK([cat empty], [0], [])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
>>     -AT_KEYWORDS([ovn-nd_ra])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# In this test case we create 1 lswitch with 3 VIF ports attached,
>>     -# and a lrouter connected to the lswitch.
>>     -# We generate the Router solicitation packet and verify the
>>     Router Advertisement
>>     -# reply packet from the ovn-controller.
>>     -
>>     -# Create hypervisor and logical switch lsw0, logical router lr0,
>>     attach lsw0
>>     -# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode
>>     column to
>>     -# 'slaac' to allow lrp0 send RA for SLAAC mode.
>>     -ovn-nbctl ls-add lsw0
>>     -ovn-nbctl lr-add lr0
>>     -ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
>>     -ovn-nbctl set Logical_Router_Port lrp0
>>     ipv6_ra_configs:address_mode="slaac"
>>     -ovn-nbctl \
>>     -    -- lsp-add lsw0 lsp0 \
>>     -    -- set Logical_Switch_Port lsp0 type=router \
>>     -                     options:router-port=lrp0 \
>>     -                     addresses='"fa:16:3e:00:00:01
>>     fdad:1234:5678::1"'
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp1
>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp2
>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>     -
>>     -ovn-nbctl lsp-add lsw0 lp3
>>     -ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>     -ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>     -
>>     -# Add ACL rule for ICMPv6 on lsw0
>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>     icmp6'  allow-related
>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>     icmp6'  allow-related
>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 &&
>>     icmp6'  allow-related
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>     -    set interface hv1-vif3 external-ids:iface-id=lp3 \
>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>     -    ofport-request=3
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -# Make sure that ovn-controller has installed the corresponding
>>     OF Flow.
>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>     -
>>     -# This shell function sends a Router Solicitation packet.
>>     -# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
>>     -test_ipv6_ra() {
>>     -    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
>>     prefix_opt=$6
>>     -    local
>>     
>> request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac} 
>>
>>     -
>>     -    local len=24
>>     -    local mtu_opt=""
>>     -    if test $mtu != 0; then
>>     -        len=`expr $len + 8`
>>     -        mtu_opt=05010000${mtu}
>>     -    fi
>>     -
>>     -    if test ${#prefix_opt} != 0; then
>>     - prefix_opt=${prefix_opt}fdad1234567800000000000000000000
>>     -        len=`expr $len + ${#prefix_opt} / 2`
>>     -    fi
>>     -
>>     -    len=$(printf "%x" $len)
>>     -    local lrp_mac=fa163e000001
>>     -    local lrp_lla=fe80000000000000f8163efffe000001
>>     -    local
>>     
>> reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt} 
>>
>>     -    echo $reply >> $inport.expected
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
>>     -}
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>     -
>>     -# MTU is not set and the address mode is set to slaac
>>     -addr_mode=00
>>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>     -src_mac=fa163e000002
>>     -src_lla=fe80000000000000f8163efffe000002
>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
>>     $default_prefix_option_config
>>     -
>>     -# NXT_RESUME should be 1.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap  > 1.packets
>>     -
>>     -cat 1.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum.
>>     -cat 1.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>     -
>>     -rm -f *.expected
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>     -
>>     -# Set the MTU to 1500
>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>     ipv6_ra_configs:mtu=1500
>>     -
>>     -# Make sure that ovn-controller has installed the corresponding
>>     OF Flow.
>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>     -
>>     -addr_mode=00
>>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>     -src_mac=fa163e000003
>>     -src_lla=fe80000000000000f8163efffe000003
>>     -mtu=000005dc
>>     -
>>     -test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
>>     $default_prefix_option_config
>>     -
>>     -# NXT_RESUME should be 2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap  > 2.packets
>>     -
>>     -cat 2.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum.
>>     -cat 2.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>     -
>>     -rm -f *.expected
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>     -
>>     -# Set the address mode to dhcpv6_stateful
>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>     -# Make sure that ovn-controller has installed the corresponding
>>     OF Flow.
>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>     -
>>     -addr_mode=80
>>     -default_prefix_option_config=03044080ffffffffffffffff00000000
>>     -src_mac=fa163e000004
>>     -src_lla=fe80000000000000f8163efffe000004
>>     -mtu=000005dc
>>     -
>>     -test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
>>     $default_prefix_option_config
>>     -
>>     -# NXT_RESUME should be 3.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif3-tx.pcap  > 3.packets
>>     -
>>     -cat 3.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum.
>>     -cat 3.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
>>     -
>>     -rm -f *.expected
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>     -
>>     -# Set the address mode to dhcpv6_stateless
>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>     -# Make sure that ovn-controller has installed the corresponding
>>     OF Flow.
>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>     -
>>     -addr_mode=40
>>     -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>     -src_mac=fa163e000002
>>     -src_lla=fe80000000000000f8163efffe000002
>>     -mtu=000005dc
>>     -
>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>     $default_prefix_option_config
>>     -
>>     -# NXT_RESUME should be 4.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap  > 1.packets
>>     -
>>     -cat 1.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum.
>>     -cat 1.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>     -
>>     -rm -f *.expected
>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>     -
>>     -# Set the address mode to invalid.
>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>     ipv6_ra_configs:address_mode=invalid
>>     -# Make sure that ovn-controller has not installed any OF Flow for
>>     IPv6 ND RA.
>>     -OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int |
>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>     -
>>     -addr_mode=40
>>     -default_prefix_option_config=""
>>     -src_mac=fa163e000002
>>     -src_lla=fe80000000000000f8163efffe000002
>>     -mtu=000005dc
>>     -
>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>     $default_prefix_option_config
>>     -
>>     -# NXT_RESUME should be 4 only.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif1-tx.pcap  > 1.packets
>>     -AT_CHECK([cat 1.packets], [0], [])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- /32 router IP address])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# 2 LS 'foo' and 'alice' connected via router R1.
>>     -# R1 connects to 'alice' with a /32 IP address. We use static
>>     routes and
>>     -# nexthop to push traffic to a logical port in switch 'alice'
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>     type=router \
>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>     -
>>     -# Connect alice to R1.
>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
>>     <http://172.16.1.1/32>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -          type=router options:router-port=alice
>>     addresses=\"00:00:00:01:02:04\"
>>     -
>>     -# Create logical port foo1 in foo
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical port alice1 in alice
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
>>     -
>>     -#install default route in R1 to use alice1's IP address as nexthop
>>     -ovn-nbctl lr-route-add R1 0.0.0.0/0 <http://0.0.0.0/0> 10.0.0.2 
>> alice
>>     -
>>     -# Create two hypervisor and create OVS ports corresponding to
>>     logical ports.
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -
>>     -# 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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -# Send ip packets between foo1 and alice1
>>     -src_mac="f00000010203"
>>     -dst_mac="000000010203"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>     
>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -
>>     -# Send the first packet to trigger a ARP response and population of
>>     -# mac_bindings table.
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" |
>>     wc -l` -gt 0])
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -# Packet to Expect at 'alice1'
>>     -src_mac="000000010204"
>>     -dst_mac="f00000010204"
>>     -src_ip=`ip_to_hex 192 168 1 2`
>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>     -echo
>>     
>> "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>
>>     > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -# Add localport to the switch
>>     -ovn-nbctl lsp-add ls1 lp01
>>     -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
>>     -ovn-nbctl lsp-set-type lp01 localport
>>     -
>>     -net_add n1
>>     -
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -    ovs-vsctl add-port br-int vif01 -- \
>>     -        set Interface vif01 external-ids:iface-id=lp01 \
>>     - options:tx_pcap=hv${i}/vif01-tx.pcap \
>>     - options:rxq_pcap=hv${i}/vif01-rx.pcap \
>>     -                              ofport-request=${i}0
>>     -
>>     -    ovs-vsctl add-port br-int vif${i}1 -- \
>>     -        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
>>     - options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
>>     - options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
>>     -                              ofport-request=${i}1
>>     -
>>     -    ovn-nbctl lsp-add ls1 lp${i}1
>>     -    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
>>     -    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
>>     -
>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup])
>>     -done
>>     -
>>     -ovn-nbctl --wait=sb sync
>>     -ovn-sbctl dump-flows
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    echo hv${1%?}
>>     -}
>>     -#
>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is
>>     specified as
>>     -# logical switch port numbers, e.g. 11 for vif11.
>>     -#
>>     -# EOUT is the end-to-end output port, that is, where the packet
>>     will end up
>>     -# after possibly bouncing through one or more localnet ports.
>>     LOUT is the
>>     -# logical output port, which might be a localnet port, as seen by
>>     ovn-trace
>>     -# (which doesn't know what localnet ports are connected to and
>>     therefore can't
>>     -# figure out the end-to-end answer).
>>     -#
>>     -# DEFHV is the default hypervisor from where the packet is going
>>     to be sent
>>     -# if the source port is a localport.
>>     -for i in 1 2; do
>>     -    for j in 0 1; do
>>     -        : > $i$j.expected
>>     -    done
>>     -done
>>     -test_packet() {
>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
>>     -    echo "$@"
>>     -
>>     -    # First try tracing the packet.
>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>     eth.src==$src && eth.type==0x$eth"
>>     -    if test $lout != drop; then
>>     -        echo "output(\"$lout\");"
>>     -    fi > expout
>>     -    AT_CAPTURE_FILE([trace])
>>     -    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed
>>     '1,/Minimal trace/d'], [0], [expout])
>>     -
>>     -    # Then actually send a packet, for an end-to-end test.
>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>     -    hv=`vif_to_hv $inport`
>>     -    # If hypervisor 0 (localport) use the defhv parameter
>>     -    if test $hv = hv0; then
>>     -        hv=$defhv
>>     -    fi
>>     -    vif=vif$inport
>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>     -    if test $eout != drop; then
>>     -        echo $packet >> ${eout#lp}.expected
>>     -    fi
>>     -}
>>     -
>>     -
>>     -# lp11 and lp21 are on different hypervisors
>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>     -
>>     -# Both VIFs should be able to reach the localport on their own HV
>>     -test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
>>     -test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
>>     -
>>     -# Packet sent from localport on same hv should reach the vif
>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 lp11 
>> hv1
>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 lp21 
>> hv2
>>     -
>>     -# Packet sent from localport on different hv should be dropped
>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop lp21 
>> hv1
>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop lp11 
>> hv2
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2; do
>>     -    for j in 0 1; do
>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>     -    done
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -# create gateways with external network connectivity
>>     -
>>     -for i in 1 2; do
>>     -    sim_add gw$i
>>     -    as gw$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -    ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -done
>>     -
>>     -ovn-nbctl ls-add inside
>>     -ovn-nbctl ls-add outside
>>     -
>>     -# create hypervisors with a vif port each to an internal network
>>     -
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.1$i
>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>     -        ofport-request=1
>>     -
>>     -        ovn-nbctl lsp-add inside inside$i \
>>     -            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i
>>     192.168.1.10$i"
>>     -
>>     -done
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -# Connect inside to R1
>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>     rp-inside \
>>     -    type=router options:router-port=inside \
>>     -    -- lsp-set-addresses rp-inside router
>>     -
>>     -# Connect outside to R1 as distributed router gateway port on 
>> gw1+gw2
>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>     <http://192.168.0.101/24>
>>     -
>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>     -- \
>>     -          --id=@gc1 create Gateway_Chassis \
>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>     -- \
>>     -          set Logical_Router_Port outside
>>     'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>     rp-outside \
>>     -    type=router options:router-port=outside \
>>     -    -- lsp-set-addresses rp-outside router
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -echo "---------NB dump-----"
>>     -ovn-nbctl show
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router
>>     -echo "---------------------"
>>     -ovn-nbctl list logical_router_port
>>     -echo "---------------------"
>>     -
>>     -echo "---------SB dump-----"
>>     -ovn-sbctl list datapath_binding
>>     -echo "---------------------"
>>     -ovn-sbctl list port_binding
>>     -echo "---------------------"
>>     -ovn-sbctl dump-flows
>>     -echo "---------------------"
>>     -ovn-sbctl list chassis
>>     -ovn-sbctl list encap
>>     -echo "---------------------"
>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>     -ovn-sbctl list Gateway_Chassis
>>     -echo "------ Port_Binding chassisredirect -------"
>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>     -echo "-------------------------------------------"
>>     -
>>     -# There should be one ha_chassis_group with the name "outside"
>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>     -ha_chassis_group name="outside"`
>>     -
>>     -AT_CHECK([test $ha_chassi_grp_name = outside])
>>     -
>>     -# There should be 2 ha_chassis rows in SB DB.
>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
>>     -grep -v chassis-name | awk '{print $3}' \
>>     -| grep '-' | wc -l ], [0], [2
>>     -])
>>     -
>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
>>     -# Trim the spaces.
>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>     -
>>     -ha_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>     -do
>>     -    ha_ch_list="$ha_ch_list $i"
>>     -done
>>     -
>>     -# Trim the spaces.
>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>     -
>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>     -
>>     -for chassis in gw1 gw2 hv1 hv2; do
>>     -    as $chassis
>>     -    echo "------ $chassis dump ----------"
>>     -    ovs-ofctl show br-int
>>     -    ovs-ofctl dump-flows br-int
>>     -    echo "--------------------------"
>>     -done
>>     -bfd_dump() {
>>     -    for chassis in gw1 gw2 hv1 hv2; do
>>     -        as $chassis
>>     -        echo "------ $chassis dump (BFD)----"
>>     -        echo "BFD (from $chassis):"
>>     -        # dump BFD config and status to the other chassis
>>     -        for chassis2 in gw1 gw2 hv1 hv2; do
>>     -            if [[ "$chassis" != "$chassis2" ]]; then
>>     -                echo " -> $chassis2:"
>>     -                echo "   $(ovs-vsctl --bare --columns
>>     bfd,bfd_status find Interface name=ovn-$chassis2-0)"
>>     -            fi
>>     -        done
>>     -        echo "--------------------------"
>>     -    done
>>     -}
>>     -
>>     -bfd_dump
>>     -
>>     -hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>     Interface name=ovn-gw1-0)
>>     -hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>     Interface name=ovn-gw2-0)
>>     -hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>     Interface name=ovn-gw1-0)
>>     -hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>     Interface name=ovn-gw2-0)
>>     -
>>     -echo $hv1_gw1_ofport
>>     -echo $hv1_gw2_ofport
>>     -echo $hv2_gw1_ofport
>>     -echo $hv2_gw2_ofport
>>     -
>>     -echo "--- hv1 ---"
>>     -as hv1 ovs-ofctl dump-flows br-int table=32
>>     -
>>     -echo "--- hv2 ---"
>>     -as hv2 ovs-ofctl dump-flows br-int table=32
>>     -
>>     -gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>> name=gw1)
>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>> name=gw2)
>>     -
>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw1
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# make sure ARP responder flows for outside router port reside on
>>     gw1 too
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# check that the chassis redirect port has been claimed by the
>>     gw1 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="hv1"`
>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="hv2"`
>>     -
>>     -exp_ref_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>     -do
>>     -    if test $i = $hv1_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    elif test $i = $hv2_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    fi
>>     -done
>>     -
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -
>>     -# at this point, we invert the priority of the gw chassis between
>>     gw1 and gw2
>>     -
>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>     -                    name=outside_gw1 chassis_name=gw1 priority=10
>>     -- \
>>     -          --id=@gc1 create Gateway_Chassis \
>>     -                    name=outside_gw2 chassis_name=gw2 priority=20
>>     -- \
>>     -          set Logical_Router_Port outside
>>     'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -
>>     -# XXX: Let the change propagate down to the ovn-controllers
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -# we make sure that the hypervisors noticed, and inverted the
>>     slave ports
>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -# check that the chassis redirect port has been reclaimed by the
>>     gw2 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -# check BFD enablement on tunnel ports from gw1 #########
>>     -as gw1
>>     -for chassis in gw2 hv1 hv2; do
>>     -    echo "checking gw1 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -
>>     -
>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>     -as gw2
>>     -for chassis in gw1 hv1 hv2; do
>>     -    echo "checking gw2 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -
>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>     -as hv1
>>     -for chassis in gw1 gw2; do
>>     -    echo "checking hv1 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -# make sure BFD is not enabled to hv2, we don't need it
>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-hv2-0],[0],
>>     -         [[
>>     -]])
>>     -
>>     -
>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>     -as hv2
>>     -for chassis in gw1 gw2; do
>>     -    echo "checking hv2 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -# make sure BFD is not enabled to hv1, we don't need it
>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-hv1-0],[0],
>>     -         [[
>>     -]])
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw2 now
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# disconnect GW2 from the network, GW1 should take over
>>     -as gw2
>>     -port=${sandbox}_br-phys
>>     -as main ovs-vsctl del-port n1 $port
>>     -
>>     -bfd_dump
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw2 now
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# check that the chassis redirect port has been reclaimed by the
>>     gw1 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
>>     -as gw2
>>     -for chassis in gw1 hv1 hv2; do
>>     -    echo "checking gw2 -> $chassis"
>>     -    OVS_WAIT_UNTIL([
>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0)
>>     -    test "$bfd_cfg" = "enable=true min_rx=2000"
>>     -])
>>     -done
>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
>>     -for chassis in gw1 hv1 hv2; do
>>     -    echo "checking gw2 -> $chassis"
>>     -    OVS_WAIT_UNTIL([
>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0)
>>     -    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
>>     -])
>>     -done
>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
>>     -for chassis in gw1 hv1 hv2; do
>>     -    echo "checking gw2 -> $chassis"
>>     -    OVS_WAIT_UNTIL([
>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0)
>>     -    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
>>     -])
>>     -done
>>     -
>>     -# Delete the inside1 vif. The ref_chassis in ha_chassis_group
>>     shouldn't have
>>     -# reference to hv1.
>>     -as hv1 ovs-vsctl del-port hv1-vif1
>>     -
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$hv2_ch_uuid" = "$ref_ch_list"])
>>     -
>>     -# Delete the inside2 vif.
>>     -ovn-sbctl show
>>     -
>>     -echo "Deleting hv2-vif1"
>>     -as hv2 ovs-vsctl del-port hv2-vif1
>>     -
>>     -# ref_chassis of ha_chassis_group should be empty
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     exp_ref_ch_list=""
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# Delete the Gateway_Chassis for lrp - outside
>>     -ovn-nbctl clear Logical_Router_Port outside gateway_chassis
>>     -
>>     -# There shoud be no ha_chassis_group rows in SB DB.
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc -l`])
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>     -
>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>     -ovn-nbctl remove NB_Global . options "bfd-min-tx"
>>     -ovn-nbctl remove NB_Global . options "bfd-mult"
>>     -
>>     -# Now test with HA chassis group instead of Gateway chassis in NB DB
>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>     -
>>     -ovn-nbctl list ha_chassis_group
>>     -ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>     ha_chassis_group name=hagrp1`
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
>>     -
>>     -# ovn-northd should not create HA chassis group and HA chassis rows
>>     -# unless the HA chassis group in OVN NB DB is associated to
>>     -# a logical router port.
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>     -
>>     -# Associate hagrp1 to outside logical router port
>>     -ovn-nbctl set Logical_Router_Port outside
>>     ha_chassis_group=$hagrp1_uuid
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>     -find ha_chassis_group | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>     chassis | \
>>     -grep -v chassis-name | wc -l`])
>>     -
>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw1
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# make sure ARP responder flows for outside router port reside on
>>     gw1 too
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# check that the chassis redirect port has been claimed by the
>>     gw1 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -# Re add the ovs ports.
>>     -for i in 1 2; do
>>     -    as hv$i
>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>     -        ofport-request=1
>>     -done
>>     -
>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="hv1"`
>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>     name="hv2"`
>>     -
>>     -exp_ref_ch_list=''
>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>     -do
>>     -    if test $i = $hv1_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    elif test $i = $hv2_ch_uuid; then
>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>     -    fi
>>     -done
>>     -
>>     -OVS_WAIT_UNTIL(
>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>     ha_chassis_group | sort`
>>     -     # Trim the spaces.
>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>     -
>>     -# Increase the priority of gw2
>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
>>     -
>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>     -| wc -l], [0], [1
>>     -])
>>     -
>>     -# check that the chassis redirect port has been reclaimed by the
>>     gw2 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -# check BFD enablement on tunnel ports from gw1 #########
>>     -as gw1
>>     -for chassis in gw2 hv1 hv2; do
>>     -    echo "checking gw1 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -
>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>     -as gw2
>>     -for chassis in gw1 hv1 hv2; do
>>     -    echo "checking gw2 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -
>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>     -as hv1
>>     -for chassis in gw1 gw2; do
>>     -    echo "checking hv1 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -# make sure BFD is not enabled to hv2, we don't need it
>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-hv2-0],[0],
>>     -         [[
>>     -]])
>>     -
>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>     -as hv2
>>     -for chassis in gw1 gw2; do
>>     -    echo "checking hv2 -> $chassis"
>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-$chassis-0],[0],
>>     -             [[enable=true
>>     -]])
>>     -done
>>     -# make sure BFD is not enabled to hv1, we don't need it
>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>     name=ovn-hv1-0],[0],
>>     -         [[
>>     -]])
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw2 now
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# disconnect GW2 from the network, GW1 should take over
>>     -as gw2
>>     -port=${sandbox}_br-phys
>>     -as main ovs-vsctl del-port n1 $port
>>     -
>>     -bfd_dump
>>     -
>>     -# make sure that flows for handling the outside router port
>>     reside on gw2 now
>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>     -]])
>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>     -]])
>>     -
>>     -# check that the chassis redirect port has been reclaimed by the
>>     gw1 chassis
>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>     Port_Binding \
>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>     -]])
>>     -
>>     -OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA
>>     distributed router])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -ovn-nbctl ls-add ls0
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl create Logical_Router name=lr0
>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
>>     <http://192.168.0.100/24>
>>     -
>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>     -                    name=outside_gw1 chassis_name=hv2 priority=10
>>     -- \
>>     -          --id=@gc1 create Gateway_Chassis \
>>     -                    name=outside_gw2 chassis_name=hv3 priority=1 
>> -- \
>>     -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>     -    type=router options:router-port=lrp0 addresses="router"
>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>     <http://10.0.0.1/24>
>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>>     -    type=router options:router-port=lrp1 addresses="router"
>>     -
>>     -# Add NAT rules
>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24
>>     <http://10.0.0.0/24>])
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -
>>     -sim_add hv3
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>     -
>>     -# Create a localnet port.
>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
>>     -
>>     -# wait for earlier changes to take effect
>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>     -# add nat-addresses option
>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="router"
>>     -
>>     -# Wait for packets to be received through hv2.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -only_broadcast_from_lrp1() {
>>     -    grep "fffffffffffff00000000001"
>>     -}
>>     -
>>     
>> -garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>
>>     -echo $garp > expout
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv1_snoop_tx
>>     -echo "packets on hv1-snoopvif:"
>>     -cat hv1_snoop_tx
>>     -AT_CHECK([sort hv1_snoop_tx], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv2_br_phys_tx
>>     -echo "packets on hv2 br-phys tx"
>>     -cat hv2_br_phys_tx
>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv3_br_phys_tx
>>     -echo "packets on hv3 br-phys tx"
>>     -cat hv3_br_phys_tx
>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
>>     -
>>     -
>>     -# at this point, we invert the priority of the gw chassis between
>>     hv2 and hv3
>>     -
>>     -ovn-nbctl --wait=hv \
>>     -          --id=@gc0 create Gateway_Chassis \
>>     -                    name=outside_gw1 chassis_name=hv2 priority=1 
>> -- \
>>     -          --id=@gc1 create Gateway_Chassis \
>>     -                    name=outside_gw2 chassis_name=hv3 priority=10
>>     -- \
>>     -          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -
>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>     -
>>     -# Wait for packets to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq >  hv1_snoopvif_tx
>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv3_br_phys_tx
>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv2_br_phys_tx
>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>     -
>>     -# change localnet port tag.
>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
>>     -
>>     -# wait for earlier changes to take effect
>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int
>>     table=65 | \
>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>     -])
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int
>>     table=65 | \
>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>     -])
>>     -
>>     -# update nat-addresses option
>>     -ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
>>     -
>>     -#Wait until the Port_Binding.nat_addresses is cleared.
>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns
>>     nat_addresses find port_binding \
>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>     -
>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>     -
>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>     nat-addresses="router"
>>     -
>>     -#Wait until the Port_Binding.nat_addresses is set.
>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns
>>     nat_addresses find port_binding \
>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>     -
>>     -# Wait for packets to be received.
>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     
>> -garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>
>>     -echo $garp > expout
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq >  hv1_snoopvif_tx
>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv3_br_phys_tx
>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>     uniq > hv2_br_phys_tx
>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't
>>     bounce the master])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -# create two gateways with external network connectivity
>>     -for i in 1 2; do
>>     -    sim_add gw$i
>>     -    as gw$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -    ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -done
>>     -
>>     -ovn-nbctl ls-add inside
>>     -ovn-nbctl ls-add outside
>>     -
>>     -# create one hypervisors with a vif port the internal network
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.11
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=inside1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovn-nbctl lsp-add inside inside1 \
>>     -        -- lsp-set-addresses inside1 "f0:00:00:01:22:01
>>     192.168.1.101"
>>     -
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -
>>     -# Connect inside to R1
>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>     rp-inside \
>>     -    type=router options:router-port=inside \
>>     -    -- lsp-set-addresses rp-inside router
>>     -
>>     -# Connect outside to R1 as distributed router gateway port on 
>> gw1+gw2
>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>     <http://192.168.0.101/24>
>>     -
>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>     -- \
>>     -          --id=@gc1 create Gateway_Chassis \
>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>     -- \
>>     -          set Logical_Router_Port outside
>>     'gateway_chassis=[@gc0,@gc1]'
>>     -
>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>     rp-outside \
>>     -    type=router options:router-port=outside \
>>     -    -- lsp-set-addresses rp-outside router
>>     -
>>     -# Create localnet port in outside
>>     -ovn-nbctl lsp-add outside ln-outside
>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -# currently when ovn-controller is restarted, the old entry is
>>     deleted
>>     -# and a new one is created, which leaves the Gateway_Chassis with
>>     -# an empty chassis for a while. NOTE: restarting ovn-controller
>>     in tests
>>     -# doesn't have the same effect because "name" is conserved, and the
>>     -# Chassis entry is not replaced.
>>     -
>>     -> gw1/ovn-controller.log
>>     -
>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>> name=gw2)
>>     -ovn-sbctl destroy Chassis $gw2_chassis
>>     -
>>     -OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport"
>>     gw1/ovn-controller.log`])
>>     -
>>     -OVN_CLEANUP([gw1],[gw2],[hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
>>     -AT_KEYWORDS([ovn-nd_ns for unknown mac])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add sw0_ip6
>>     -ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
>>     -ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>     -
>>     -ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>     -
>>     -ovn-nbctl lr-add lr0_ip6
>>     -ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01
>>     aef0:0:0:0:0:0:0:0/64
>>     -ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
>>     -ovn-nbctl lsp-set-type lrp0_ip6-attachment router
>>     -ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
>>     -ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
>>     -ovn-nbctl set logical_router_port lrp0_ip6
>>     ipv6_ra_configs:address_mode=slaac
>>     -
>>     -ovn-nbctl ls-add public
>>     -ovn-nbctl lsp-add public ln-public
>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>     -ovn-nbctl lsp-set-type ln-public localnet
>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>     -
>>     -ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
>>     -2001:db8:1:0:200:02ff:fe01:0204/64 \
>>     --- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
>>     -
>>     -#install static route
>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>     -ip_prefix="\:\:/0" 
>> nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
>>     --- add Logical_Router lr0_ip6 static_routes @lrt
>>     -
>>     -ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
>>     -rp-ip6_public  type=router options:router-port=ip6_public \
>>     --- lsp-set-addresses rp-ip6_public router
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
>>     -
>>     -# There should be 2 Neighbor Advertisement flows for the router port
>>     -# aef0:: ip address in logical switch pipeline with action
>>     nd_na_router.
>>     -AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
>>     -grep "nd_na_router" | wc -l], [0], [2
>>     -])
>>     -
>>     -# There should be 4 Neighbor Advertisement flows with action
>>     nd_na_router
>>     -# in the router pipeline for the router lr0_ip6.
>>     -AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
>>     -wc -l], [0], [4
>>     -])
>>     -
>>     -cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public |
>>     grep _uuid | cut -f2 -d ":"`
>>     -
>>     -# There is only one chassis.
>>     -chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d ":"`
>>     -OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding
>>     $cr_uuid chassis`])
>>     -
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for
>>     unknown MAC
>>     -# addresses. ovn-controller should generate an IPv6 NS request
>>     for IPv6
>>     -# packets whose MAC is unknown (in the ARP_REQUEST router
>>     pipeline stage.
>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -# This function sends ipv6 packet
>>     -test_ipv6() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
>>     -
>>     -    local
>>     packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
>>     -    packet=${packet}8000000000000000
>>     -
>>     -    src_mac=000002010204
>>     -
>>     
>> expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
>>     - expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
>>     - expected_packet=${expected_packet}${nd_target}0101${src_mac}
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
>>     -    rm -f ipv6_ns.expected
>>     -    echo $expected_packet >> ipv6_ns.expected
>>     -}
>>     -
>>     -src_mac=506400000002
>>     -dst_mac=00000000af01
>>     -src_ip=aef0000000000000526400fffe000002
>>     -dst_ip=20010db800010000020002fffe010205
>>     -dst_mcast_mac=3333ff010205
>>     -mcast_node_ip=ff0200000000000000000001ff010205
>>     -nd_target=20010db800010000020002fffe010205
>>     -# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
>>     -# should be received by the ports attached to br-phys.
>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>     -$mcast_node_ip $nd_target
>>     -
>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>     " " -f1)])
>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>     " -f1)])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-phys_n1-tx.pcap | \
>>     -trim_zeros > 1.packets
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-phys-tx.pcap | \
>>     -trim_zeros > 2.packets
>>     -
>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum
>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>     -
>>     -# Now send a packet with destination ip other than
>>     -# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>     -reset_pcap_file br-phys hv1/br-phys
>>     -
>>     -src_mac=506400000002
>>     -dst_mac=00000000af01
>>     -src_ip=aef0000000000000526400fffe000002
>>     -dst_ip=20020ab8000100000200020000020306
>>     -# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
>>     -dst_mcast_mac=3333ff011305
>>     -mcast_node_ip=ff0200000000000000000001ff011305
>>     -nd_target=20010db800010000020002fffe011305
>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>     -$mcast_node_ip $nd_target
>>     -
>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>     " " -f1)])
>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>     " -f1)])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-phys_n1-tx.pcap | \
>>     -trim_zeros > 1.packets
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-phys-tx.pcap | \
>>     -trim_zeros > 2.packets
>>     -
>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>     -
>>     -# Skipping the ICMPv6 checksum
>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- options:requested-chassis for logical port])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -
>>     -ovn-nbctl ls-add ls0
>>     -ovn-nbctl lsp-add ls0 lsp0
>>     -
>>     -# create two hypervisors, each with one vif port
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.11
>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- \
>>     -set Interface hv1-vif0 ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.12
>>     -ovs-vsctl -- add-port br-int hv2-vif0 -- \
>>     -set Interface hv2-vif0 ofport-request=1
>>     -
>>     -# Allow only chassis hv1 to bind logical port lsp0.
>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -# Retrieve hv1 and hv2 chassis UUIDs from southbound database
>>     -ovn-sbctl wait-until chassis hv1
>>     -ovn-sbctl wait-until chassis hv2
>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
>>     -hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
>>     -
>>     -# (1) Chassis hv2 should not bind lsp0 when requested-chassis is 
>> hv1.
>>     -echo "verifying that hv2 does not bind lsp0 when hv2
>>     physical/logical mapping is added"
>>     -as hv2
>>     -ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0"
>>     hv2/ovn-controller.log)])
>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding logical_port=lsp0) = x], [0], [])
>>     -
>>     -# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and
>>     OFTABLE_LOG_TO_PHY tables.
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [1], [])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>     output], [1], [])
>>     -
>>     -# (3) Chassis hv1 should bind lsp0 when physical to logical
>>     mapping exists on hv1.
>>     -echo "verifying that hv1 binds lsp0 when hv1 physical/logical
>>     mapping is added"
>>     -as hv1
>>     -ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>>     -
>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>     hv1/ovn-controller.log)])
>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>     -
>>     -# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and
>>     OFTABLE_LOG_TO_PHY tables.
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [0], [ignore])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>     actions=output:1], [0], [ignore])
>>     -
>>     -# (5) Chassis hv1 should release lsp0 binding and chassis hv2
>>     should bind lsp0 when
>>     -# the requested chassis for lsp0 is changed from hv1 to hv2.
>>     -echo "verifying that lsp0 binding moves when requested-chassis is
>>     changed"
>>     -
>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>     this chassis" hv1/ovn-controller.log)])
>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding logical_port=lsp0) = x"$hv2_uuid"])
>>     -
>>     -# (6) Chassis hv2 should add flows and hv1 should not.
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [0], [ignore])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>     actions=output:1], [0], [ignore])
>>     -
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [1], [])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>     output], [1], [])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- options:requested-chassis with hostname])
>>     -
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls0
>>     -ovn-nbctl lsp-add ls0 lsp0
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.11
>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0
>>     ofport-request=1
>>     -
>>     -ovn-sbctl wait-until chassis hv1
>>     -hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis
>>     name=hv1)
>>     -echo "hv1_hostname=${hv1_hostname}"
>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>     requested-chassis=${hv1_hostname}
>>     -as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>>     -
>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
>>     -echo "hv1_uuid=${hv1_uuid}"
>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>     hv1/ovn-controller.log)])
>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [0], [ignore])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>     actions=output:1], [0], [ignore])
>>     -
>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>     requested-chassis=non-existant-chassis
>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>     this chassis" hv1/ovn-controller.log)])
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>     port_binding logical_port=lsp0) = x], [0], [])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>     in_port=1], [1], [])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>     output], [1], [])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IPv6 periodic RA])
>>     -ovn_start
>>     -
>>     -# This test sets up two hypervisors.
>>     -# hv1 and hv2 run ovn-controllers, and
>>     -# each has a VIF connected to the same
>>     -# logical switch in OVN. The logical
>>     -# switch is connected to a logical
>>     -# router port that is configured to send
>>     -# periodic router advertisements.
>>     -#
>>     -# The reason for having two ovn-controller
>>     -# hypervisors is to ensure that the
>>     -# periodic RAs being sent by each ovn-controller
>>     -# are kept to their local hypervisors. If the
>>     -# packets are not kept local, then each port
>>     -# will receive too many RAs.
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -sim_add hv2
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -
>>     -ovn-nbctl lr-add ro
>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>>     -
>>     -ovn-nbctl ls-add sw
>>     -ovn-nbctl lsp-add sw sw-ro
>>     -ovn-nbctl lsp-set-type sw-ro router
>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>     -ovn-nbctl lsp-add sw sw-p1
>>     -ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02
>>     aef0::200:ff:fe00:2"
>>     -ovn-nbctl lsp-add sw sw-p2
>>     -ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03
>>     aef0::200:ff:fe00:3"
>>     -
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:send_periodic=true
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:address_mode=slaac
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:max_interval=4
>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:min_interval=3
>>     -
>>     -for i in 1 2 ; do
>>     -    as hv$i
>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>     -        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>     -        ofport-request=1
>>     -done
>>     -
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -
>>     -}
>>     -
>>     -construct_expected_ra() {
>>     -    local src_mac=000000000001
>>     -    local dst_mac=333300000001
>>     -    local src_addr=fe80000000000000020000fffe000001
>>     -    local dst_addr=ff020000000000000000000000000001
>>     -
>>     -    local mtu=$1
>>     -    local ra_mo=$2
>>     -    local ra_prefix_la=$3
>>     -
>>     -    local slla=0101${src_mac}
>>     -    local mtu_opt=""
>>     -    if test $mtu != 0; then
>>     -        mtu_opt=05010000${mtu}
>>     -    fi
>>     -    shift 3
>>     -
>>     -    local prefix=""
>>     -    while [[ $# -gt 0 ]] ; do
>>     -        local size=$1
>>     -        local net=$2
>>     -
>>     
>> prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
>>     -        shift 2
>>     -    done
>>     -
>>     -    local 
>> ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
>>     -    local icmp=8600XXXX${ra}
>>     -
>>     -    local ip_len=$(expr ${#icmp} / 2)
>>     -    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
>>     -
>>     -    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
>>     -    local eth=${dst_mac}${src_mac}86dd${ip}
>>     -    local packet=${eth}
>>     -    echo $packet >> expected
>>     -}
>>     -
>>     -ra_test() {
>>     -    construct_expected_ra $@
>>     -
>>     -    for i in hv1 hv2 ; do
>>     -        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut
>>     -d " " -f1)])
>>     -
>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" $i/vif1-tx.pcap > packets
>>     -
>>     -        cat expected | cut -c -112 > expout
>>     -        AT_CHECK([cat packets | cut -c -112], [0], [expout])
>>     -
>>     -        # Skip ICMPv6 checksum.
>>     -        cat expected | cut -c 117- > expout
>>     -        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
>>     -
>>     -        rm -f packets
>>     -        as $i reset_pcap_file $i-vif1 $i/vif1
>>     -    done
>>     -
>>     -    rm -f expected
>>     -}
>>     -
>>     -# Baseline test with no MTU
>>     -ra_test 0 00 c0 40 aef00000000000000000000000000000
>>     -
>>     -# Now make sure an MTU option makes it
>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:mtu=1500
>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
>>     -
>>     -# Now test for multiple network prefixes
>>     -ovn-nbctl --wait=hv set Logical_Router_port ro-sw
>>     networks='aef0\:\:1/64 fd0f\:\:1/48'
>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30
>>     fd0f0000000000000000000000000000
>>     -
>>     -# Test a different address mode now
>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>     -ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30
>>     fd0f0000000000000000000000000000
>>     -
>>     -# And the other address mode
>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>     -ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30
>>     fd0f0000000000000000000000000000
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ACL reject rule test])
>>     -AT_KEYWORDS([acl-reject])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>     IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv4 packet with
>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>     of the icmp destination
>>     -# unreachable frame generated from ACL rule hit
>>     -#
>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>     -# HV is a hypervisor number
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>>     -test_ip_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ipv4_dst=$6 ip_chksum=$7
>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>     -    shift 9
>>     -
>>     -    local ip_ttl=ff
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>
>>     -
>>     -    local reply_icmp_ttl=ff
>>     -    local icmp_type_code_response=0301
>>     -    local icmp_data=00000000
>>     -    local
>>     
>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>     EXP_ICMP_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv6 packet with
>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
>>     -# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination
>>     unreachable frame generated from ACL rule hit
>>     -test_ipv6_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>     ipv6_dst=$6 exp_icmp_chksum=$7
>>     -    shift 7
>>     -
>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
>>     -
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>     IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>     EXP_TCP_RST_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an TCP syn segment with
>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT,
>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>     checksums of the tcp reset segment generated from ACL rule hit
>>     -#
>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>     -# HV is an hypervisor number
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>     each 4 hex digits
>>     -test_tcp_syn_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ipv4_dst=$6 ip_chksum=$7
>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>     -    shift 12
>>     -
>>     -    local ip_ttl=ff
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>
>>     -
>>     -    local tcp_rst_ttl=ff
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# Create hypervisors hv[123].
>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>     -# Add all of the vifs to a single logical switch sw0.
>>     -
>>     -net_add n1
>>     -ovn-nbctl ls-add sw0
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2 3; do
>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>     192.168.1.$i$j"
>>     -
>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>     -                set interface vif$i$j \
>>     -                external-ids:iface-id=sw0-p$i$j \
>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>     -                ofport-request=$i$j
>>     -    done
>>     -done
>>     -
>>     -OVN_POPULATE_ARP
>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>     -sleep 1
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -for i in 1 2 3; do
>>     -    : > vif${i}1.expected
>>     -done
>>     -
>>     -ovn-nbctl --log acl-add sw0 to-lport 1000 "outport ==
>>     \"sw0-p12\"" reject
>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>     \"sw0-p11\"" reject
>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>     \"sw0-p21\"" reject
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>     -
>>     -test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168
>>     1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
>>     -test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168
>>     1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
>>     -test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168
>>     1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
>>     -
>>     -test_ipv6_packet 11 1 000000000011 000000000021
>>     fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 
>> 6183
>>     -
>>     -test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex
>>     192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 4486
>>     -test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex
>>     192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 4486
>>     -test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex
>>     192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 4486
>>     -
>>     -for i in 1 2 3; do
>>     -    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], [vif${i}1.expected])
>>     -done
>>     -
>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- Port Groups])
>>     -AT_KEYWORDS([ovnpg])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -#
>>     -# Three logical switches ls1, ls2, ls3.
>>     -# One logical router lr0 connected to ls[123],
>>     -# with nine subnets, three per logical switch:
>>     -#
>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>> <http://192.168.11.0/24>
>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>> <http://192.168.12.0/24>
>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>> <http://192.168.13.0/24>
>>     -#    ...
>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>> <http://192.168.33.0/24>
>>     -#
>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>     first two
>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>     -#
>>     -# This test will create two port groups and uses them in ACL.
>>     -
>>     -get_lsp_uuid () {
>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>     -}
>>     -
>>     -pg1_ports=
>>     -pg2_ports=
>>     -for i in 1 2 3; do
>>     -    ovn-nbctl ls-add ls$i
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            ovn-nbctl \
>>     -                -- lsp-add ls$i lp$i$j$k \
>>     -                -- lsp-set-addresses lp$i$j$k \
>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>     -            if test $i != 3 && test $k == 1; then
>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>     -            fi
>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>     -            if test $i != 1 && test $k == 2; then
>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>     -            fi
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>     192.168.$i$j.254/24
>>     -        ovn-nbctl \
>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>     type=router \
>>     -                             options:router-port=lrp$i$j \
>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>     -
>>     -# create ACLs on all lswitches to drop traffic from pg2 to pg1
>>     -ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src
>>     == $pg2_ip4' drop
>>     -ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src
>>     == $pg2_ip4' drop
>>     -ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src
>>     == $pg2_ip4' drop
>>     -
>>     -# Physical network:
>>     -#
>>     -# Three hypervisors hv[123].
>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>     lp?13 on hv3.
>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>     on hv3.
>>     -# lp?3[123] all on hv3.
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    case $1 in dnl (
>>     -        ?11) echo 1 ;; dnl (
>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>     -    esac
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its
>>     logical router
>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>     -vif_to_lrp() {
>>     -    echo ${1%?}
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its logical
>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>     -vif_to_ls() {
>>     -    echo ${1%??}
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -done
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            hv=`vif_to_hv $i$j$k`
>>     -                as hv$hv ovs-vsctl \
>>     -                -- add-port br-int vif$i$j$k \
>>     -                -- set Interface vif$i$j$k \
>>     -                    external-ids:iface-id=lp$i$j$k \
>>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>     -                    ofport-request=$i$j$k
>>     -        done
>>     -    done
>>     -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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -#
>>     -# This shell function causes a packet to be received on INPORT.
>>     The packet's
>>     -# content has Ethernet destination DST and source SRC (each
>>     exactly 12 hex
>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>     (zero or
>>     -# more) list the VIFs on which the packet should be received.
>>     INPORT and the
>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>     for vif123.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            : > $i$j$k.expected
>>     -        done
>>     -    done
>>     -done
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    in_ls=`vif_to_ls $inport`
>>     -    in_lrp=`vif_to_lrp $inport`
>>     -    for outport; do
>>     -        out_ls=`vif_to_ls $outport`
>>     -        if test $in_ls = $out_ls; then
>>     -            # Ports on the same logical switch receive exactly
>>     the same packet.
>>     -            echo $packet
>>     -        else
>>     -            # Routing decrements TTL and updates source and dest MAC
>>     -            # (and checksum).
>>     -            out_lrp=`vif_to_lrp $outport`
>>     -            echo
>>     
>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>
>>     -        fi >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>     -as hv1 ovn-sbctl list port_binding
>>     -as hv1 ovn-sbctl list datapath_binding
>>     -as hv1 ovn-sbctl list port_group
>>     -as hv1 ovn-sbctl list address_set
>>     -as hv1 ovn-sbctl dump-flows
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Send IP packets between all pairs of source and destination ports,
>>     -# packets matches ACL (pg2 to pg1) should be dropped
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -for is in 1 2 3; do
>>     -  for js in 1 2 3; do
>>     -    for ks in 1 2 3; do
>>     -      bcast=
>>     -      s=$is$js$ks
>>     -      smac=f00000000$s
>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>     -      for id in 1 2 3; do
>>     -          for jd in 1 2 3; do
>>     -              for kd in 1 2 3; do
>>     -                d=$id$jd$kd
>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>     -                if test $is = $id; then dmac=f00000000$d; else
>>     dmac=00000000ff$is$js; fi
>>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>>     -
>>     -                # packets matches ACL should be dropped
>>     -                if test $id != 3 && test $kd == 1; then
>>     -                    if test $is != 1 && test $ks == 2; then
>>     -                        unicast=
>>     -                    fi
>>     -                fi
>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>     -              done
>>     -          done
>>     -        done
>>     -      done
>>     -  done
>>     -done
>>     -
>>     -# Allow some time for packet forwarding.
>>     -# XXX This can be improved.
>>     -sleep 1
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>     -                              [$i$j$k.expected])
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ACLs on Port Groups])
>>     -AT_KEYWORDS([ovnpg_acl])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -#
>>     -# Three logical switches ls1, ls2, ls3.
>>     -# One logical router lr0 connected to ls[123],
>>     -# with nine subnets, three per logical switch:
>>     -#
>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>> <http://192.168.11.0/24>
>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>> <http://192.168.12.0/24>
>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>> <http://192.168.13.0/24>
>>     -#    ...
>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>> <http://192.168.33.0/24>
>>     -#
>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>     first two
>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>     -#
>>     -# This test will create two port groups and ACLs will be applied
>>     on them.
>>     -
>>     -get_lsp_uuid () {
>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>     -}
>>     -
>>     -pg1_ports=
>>     -pg2_ports=
>>     -for i in 1 2 3; do
>>     -    ovn-nbctl ls-add ls$i
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            ovn-nbctl \
>>     -                -- lsp-add ls$i lp$i$j$k \
>>     -                -- lsp-set-addresses lp$i$j$k \
>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>     -            if test $i != 3 && test $k == 1; then
>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>     -            fi
>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>     -            if test $i != 1 && test $k == 2; then
>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>     -            fi
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>     192.168.$i$j.254/24
>>     -        ovn-nbctl \
>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>     type=router \
>>     -                             options:router-port=lrp$i$j \
>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>     -
>>     -# create ACLs on pg1 to drop traffic from pg2 to pg1
>>     -ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
>>     -ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
>>     -        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
>>     -
>>     -# Physical network:
>>     -#
>>     -# Three hypervisors hv[123].
>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>     lp?13 on hv3.
>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>     on hv3.
>>     -# lp?3[123] all on hv3.
>>     -
>>     -# Given the name of a logical port, prints the name of the 
>> hypervisor
>>     -# on which it is located.
>>     -vif_to_hv() {
>>     -    case $1 in dnl (
>>     -        ?11) echo 1 ;; dnl (
>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>     -    esac
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its
>>     logical router
>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>     -vif_to_lrp() {
>>     -    echo ${1%?}
>>     -}
>>     -
>>     -# Given the name of a logical port, prints the name of its logical
>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>     -vif_to_ls() {
>>     -    echo ${1%??}
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2 3; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -done
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            hv=`vif_to_hv $i$j$k`
>>     -                as hv$hv ovs-vsctl \
>>     -                -- add-port br-int vif$i$j$k \
>>     -                -- set Interface vif$i$j$k \
>>     -                    external-ids:iface-id=lp$i$j$k \
>>     -                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>     -                    ofport-request=$i$j$k
>>     -        done
>>     -    done
>>     -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
>>     -
>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>     -# XXX This should be more systematic.
>>     -sleep 1
>>     -
>>     -lsp_to_mac() {
>>     -    echo f0:00:00:00:0${1:0:1}:${1:1:2}
>>     -}
>>     -
>>     -lrp_to_mac() {
>>     -    echo 00:00:00:00:ff:$1
>>     -}
>>     -
>>     -# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE 
>> OUTPORT...
>>     -#
>>     -# This shell function causes a ICMP packet to be received on INPORT.
>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>     should
>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>     switch
>>     -# port numbers, e.g. 123 for vif123.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            : > $i$j$k.expected
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -test_icmp() {
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     icmp_type=$6
>>     -    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
>>     -                  eth.dst==$dst_mac && ip.ttl==64 && 
>> ip4.src==$src_ip
>>     -                  && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
>>     -                  icmp4.code==0"
>>     -    shift; shift; shift; shift; shift; shift
>>     -    hv=hv`vif_to_hv $inport`
>>     -    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -    in_ls=`vif_to_ls $inport`
>>     -    in_lrp=`vif_to_lrp $inport`
>>     -    for outport; do
>>     -        out_ls=`vif_to_ls $outport`
>>     -        if test $in_ls = $out_ls; then
>>     -            # Ports on the same logical switch receive exactly
>>     the same packet.
>>     -            echo $packet | ovstest test-ovn expr-to-packets
>>     -        else
>>     -            # Routing decrements TTL and updates source and dest MAC
>>     -            # (and checksum).
>>     -            out_lrp=`vif_to_lrp $outport`
>>     -            exp_smac=`lrp_to_mac $out_lrp`
>>     -            exp_dmac=`lsp_to_mac $outport`
>>     -            exp_packet="eth.src==$exp_smac && eth.dst==$exp_dmac &&
>>     -                ip.ttl==63 && ip4.src==$src_ip && 
>> ip4.dst==$dst_ip &&
>>     -                icmp4.type==$icmp_type && icmp4.code==0"
>>     -            echo $exp_packet | ovstest test-ovn expr-to-packets
>>     -
>>     -        fi >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>     -as hv1 ovn-sbctl list port_binding
>>     -as hv1 ovn-sbctl list datapath_binding
>>     -as hv1 ovn-sbctl list port_group
>>     -as hv1 ovn-sbctl list address_set
>>     -as hv1 ovn-sbctl dump-flows
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Send IP packets between all pairs of source and destination ports,
>>     -# packets matches ACL1 but not ACL2 should be dropped
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -for is in 1 2 3; do
>>     -  for js in 1 2 3; do
>>     -    for ks in 1 2 3; do
>>     -      bcast=
>>     -      s=$is$js$ks
>>     -      slsp_mac=`lsp_to_mac $s`
>>     -      slrp_mac=`lrp_to_mac $is$js`
>>     -      sip=192.168.$is$js.$ks
>>     -      for id in 1 2 3; do
>>     -          for jd in 1 2 3; do
>>     -              for kd in 1 2 3; do
>>     -                d=$id$jd$kd
>>     -                dlsp_mac=`lsp_to_mac $d`
>>     -                dlrp_mac=`lrp_to_mac $id$jd`
>>     -                dip=192.168.$id$jd.$kd
>>     -                if test $is = $id; then dmac=$dlsp_mac; else
>>     dmac=$slrp_mac; fi
>>     -                if test $d != $s; then unicast=$d; else unicast=; fi
>>     -
>>     -                # packets matches ACL1 but not ACL2 should be 
>> dropped
>>     -                if test $id != 3 && test $kd == 1; then
>>     -                    if test $is == 1 || test $ks != 2; then
>>     -                        unicast=
>>     -                    fi
>>     -                fi
>>     -                # icmp request (type = 8)
>>     -                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
>>     -
>>     -                # if packets are not dropped, test the return
>>     traffic (icmp echo)
>>     -                # to make sure stateful works, too.
>>     -                if test x$unicast != x; then
>>     -                    if test $is = $id; then dmac=$slsp_mac; else
>>     dmac=$dlrp_mac; fi
>>     -                    # icmp echo (type = 0)
>>     -                    test_icmp $unicast $dlsp_mac $dmac $dip $sip 
>> 0 $s
>>     -                fi
>>     -              done
>>     -          done
>>     -        done
>>     -      done
>>     -  done
>>     -done
>>     -
>>     -# Allow some time for packet forwarding.
>>     -# XXX This can be improved.
>>     -sleep 1
>>     -
>>     -# Now check the packets actually received against the ones expected.
>>     -for i in 1 2 3; do
>>     -    for j in 1 2 3; do
>>     -        for k in 1 2 3; do
>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>     -                              [$i$j$k.expected])
>>     -        done
>>     -    done
>>     -done
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (static
>>     addressing)])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -ovn-nbctl lsp-add ls1 lp1
>>     -ovn-nbctl lsp-add ls1 lp2
>>     -ovn-nbctl lsp-add ls1 lp3
>>     -
>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1
>>     2001:db8::1"
>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2
>>     2001:db8::2"
>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3
>>     2001:db8::3"
>>     -
>>     -ovn-nbctl create Port_Group name=pg1
>>     -ovn-nbctl create Port_Group name=pg2
>>     -
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>     pg1 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>     pg1 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>     pg2 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>     pg2 ports @p
>>     -
>>     -ovn-nbctl --wait=sb sync
>>     -
>>     -dnl Check if port group address sets were populated with ports'
>>     addresses
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>     -         [0], [[["10.0.0.1", "10.0.0.2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>     -         [0], [[["10.0.0.2", "10.0.0.3"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>     -         [0], [[["2001:db8::1", "2001:db8::2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>     -         [0], [[["2001:db8::2", "2001:db8::3"]]
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-set-addresses lp1 \
>>     -    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
>>     -
>>     -dnl Check if updated address got propagated to the port group
>>     address sets
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>     -         [0], [[["10.0.0.11", "10.0.0.2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>     -         [0], [[["2001:db8::11", "2001:db8::2"]]
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic
>>     addressing)])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl ls-add ls2
>>     -ovn-nbctl ls-add ls3
>>     -
>>     -ovn-nbctl set Logical_Switch ls1 \
>>     -    other_config:subnet=10.1.0.0/24 <http://10.1.0.0/24>
>>     other_config:ipv6_prefix="2001:db8:1::"
>>     -ovn-nbctl set Logical_Switch ls2 \
>>     -    other_config:subnet=10.2.0.0/24 <http://10.2.0.0/24>
>>     other_config:ipv6_prefix="2001:db8:2::"
>>     -ovn-nbctl set Logical_Switch ls3 \
>>     -    other_config:subnet=10.3.0.0/24 <http://10.3.0.0/24>
>>     other_config:ipv6_prefix="2001:db8:3::"
>>     -
>>     -ovn-nbctl lsp-add ls1 lp1
>>     -ovn-nbctl lsp-add ls2 lp2
>>     -ovn-nbctl lsp-add ls3 lp3
>>     -
>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
>>     -
>>     -ovn-nbctl create Port_Group name=pg1
>>     -ovn-nbctl create Port_Group name=pg2
>>     -
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>     pg1 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>     pg1 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>     pg2 ports @p
>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>     pg2 ports @p
>>     -
>>     -ovn-nbctl --wait=sb sync
>>     -
>>     -dnl Check if port group address sets were populated with ports'
>>     addresses
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>     -         [0], [[["10.1.0.2", "10.2.0.2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>     -         [0], [[["10.2.0.2", "10.3.0.2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>     -         [0], [[["2001:db8:1::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>     -         [0], [[["2001:db8:2::ff:fe00:2", "2001:db8:3::ff:fe00:3"]]
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb set Logical_Switch ls1 \
>>     -    other_config:subnet=10.11.0.0/24 <http://10.11.0.0/24>
>>     other_config:ipv6_prefix="2001:db8:11::"
>>     -
>>     -dnl Check if updated address got propagated to the port group
>>     address sets
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>     -         [0], [[["10.11.0.2", "10.2.0.2"]]
>>     -])
>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>     -         [0], [[["2001:db8:11::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ACL conjunction])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>>     -
>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=2
>>     -
>>     -ovn-nbctl create Address_Set name=set1 \
>>     -addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
>>     -ovn-nbctl create Address_Set name=set2 \
>>     -addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
>>     -ovn-nbctl acl-add ls1 to-lport 1002 \
>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
>>     -ovn-nbctl acl-add ls1 to-lport 1001 \
>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
>>     -
>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>     -#
>>     -# This shell function causes an ip packet to be received on INPORT.
>>     -# The packet's content has Ethernet destination DST and source SRC
>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>     digits).
>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>     should
>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>     switch
>>     -# port numbers, e.g. 11 for vif11.
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
>>     -${dst_ip}0035111100080000
>>     -    shift; shift; shift; shift; shift
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -    for outport; do
>>     -        echo $packet >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -
>>     -sip=`ip_to_hex 10 0 0 4`
>>     -dip=`ip_to_hex 10 0 0 6`
>>     -
>>     -test_ip 1 f00000000001 f00000000002 $sip $dip 2
>>     -
>>     -cat 2.expected > expout
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [expout])
>>     -
>>     -# There should be total of 12 flows present with conjunction
>>     action and 2 flows
>>     -# with conj match. Eg.
>>     -# table=44, priority=2002,conj_id=2,metadata=0x1
>>     actions=resubmit(,45)
>>     -# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6
>>     actions=conjunction(2,2/2)
>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4
>>     actions=conjunction(2,2/2)
>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5
>>     actions=conjunction(2,2/2)
>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7
>>     actions=conjunction(3,2/2)
>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9
>>     actions=conjunction(3,2/2)
>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8
>>     actions=conjunction(3,2/2)
>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6
>>     actions=conjunction(2,1/2)
>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4
>>     actions=conjunction(2,1/2)
>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5
>>     actions=conjunction(2,1/2)
>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6
>>     actions=conjunction(3,1/2)
>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4
>>     actions=conjunction(3,1/2)
>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5
>>     actions=conjunction(3,1/2)
>>     -
>>     -OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
>>     -grep conjunction | wc -l`])
>>     -OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
>>     -grep conj_id | wc -l`])
>>     -
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -# Set the ip address for ls1-lp2 from set2 so that the drop ACL
>>     flow is hit.
>>     -ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7
>>     20.0.0.4"
>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>     10.0.0.7 20.0.0.4"
>>     -
>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>     -
>>     -rm -f 2.packets
>>     -
>>     -sip=`ip_to_hex 10 0 0 4`
>>     -dip=`ip_to_hex 10 0 0 7`
>>     -
>>     -test_ip 1 f00000000001 f00000000002 $sip $dip
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/vif2-tx.pcap > 2.packets
>>     -AT_CHECK([cat 2.packets], [0], [])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- TTL exceeded])
>>     -AT_KEYWORDS([ttl-exceeded])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>     IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv4 packet with
>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified
>>     and TTL set to 1.
>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>     of the icmp time exceeded frame
>>     -# generated by OVN logical router
>>     -#
>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>     -# HV is a hypervisor number
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>>     -test_ip_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ipv4_dst=$6 ip_router=$7 ip_chksum=$8
>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
>>     -    shift 10
>>     -
>>     -    local ip_ttl=01
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>
>>     -
>>     -    local reply_icmp_ttl=fe
>>     -    local icmp_type_code_response=0b00
>>     -    local icmp_data=00000000
>>     -    local
>>     
>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>     IPV6_ROUTER EXP_ICMP_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv6
>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified.
>>     -# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum
>>     of the icmpv6 ttl exceeded
>>     -# packet sent by OVN logical router
>>     -test_ip6_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>     -    shift 8
>>     -
>>     -    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a 
>>
>>     -
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -for i in 1 2; do
>>     -    net_add n$i
>>     -    ovn-nbctl ls-add sw$i
>>     -
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>     -
>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>     192.168.$i.1 2001:db8:$i::11"
>>     -
>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>     -        set interface vif$i \
>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>     -            ofport-request=$i
>>     -done
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2; do
>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>     192.168.$i.254/24 2001:db8:$i::1/64
>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>     type=router \
>>     -                options:router-port=lrp$i
>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
>>     -done
>>     -
>>     -OVN_POPULATE_ARP
>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>     1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae
>>     f4ff
>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>     20010db8000100000000000000000011 20010db8000200000000000000000011
>>     20010db8000100000000000000000001 d461
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>     -
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- router port unreachable])
>>     -AT_KEYWORDS([router-port-unreachable])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
>>     L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv4 packet with
>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM
>>     as specified.
>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>     of the icmp frame generated by OVN logical router
>>     -# EXP_ICMP_CODE are code and type of the icmp frame generated by
>>     OVN logical router
>>     -#
>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>     -# HV is a hypervisor number
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
>>     -test_ip_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ip_router=$6 l4_proto=$7 ip_chksum=$8
>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10} exp_icmp_code=${11}
>>     -    shift 11
>>     -
>>     -    local ip_ttl=ff
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router} 
>>
>>     -
>>     -    local reply_icmp_ttl=fe
>>     -    local icmp_data=00000000
>>     -    local
>>     reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC
>>     IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>     EXP_TCP_RST_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an TCP syn segment with
>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT,
>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>     checksums of the tcp reset segment generated by OVN logical router
>>     -#
>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>     -# HV is an hypervisor number
>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>     each 4 hex digits
>>     -test_tcp_syn_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ip_router=$6 ip_chksum=$7
>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>     -    shift 12
>>     -
>>     -    local ip_ttl=ff
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>
>>     -
>>     -    local tcp_rst_ttl=fe
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>>     TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is a TCP syn segment with
>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT
>>     and TCP_CHKSUM as specified.
>>     -# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset
>>     segment generated by OVN logical router
>>     -test_tcp6_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>     ipv6_router=$6
>>     -    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
>>     -    local exp_tcp_rst_chksum=${10}
>>     -    shift 10
>>     -
>>     -    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>
>>     -
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>     IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
>>     -#
>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>     The packet is an IPv6
>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO,
>>     IPV6_LEN and DATA as specified.
>>     -# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of
>>     the icmp6 packet sent by OVN logical router
>>     -test_ip6_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>     ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
>>     -    local exp_icmp_code=${10} exp_icmp_chksum=${11}
>>     -    shift 11
>>     -
>>     -    local
>>     ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
>>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
>>     -
>>     -    local
>>     
>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr} 
>>
>>     -    echo $reply >> vif$inport.expected
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -for i in 1 2; do
>>     -    net_add n$i
>>     -    ovn-nbctl ls-add sw$i
>>     -
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>     -
>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>     192.168.$i.1 2001:db8:$i::11"
>>     -
>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>     -        set interface vif$i \
>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>     -            ofport-request=$i
>>     -done
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -for i in 1 2; do
>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>     192.168.$i.254/24 2001:db8:$i::1/64
>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>     type=router \
>>     -                options:router-port=lrp$i
>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
>>     -done
>>     -
>>     -OVN_POPULATE_ARP
>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>     1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>     1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>     20010db8000100000000000000000011 20010db8000100000000000000000001
>>     11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>     -
>>     -test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
>>     -test_ip6_packet 2 2 000000000002 00000000ff02
>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>     84 0004 01020304 0103 627e
>>     -test_tcp6_packet 2 2 000000000002 00000000ff02
>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>     8b40 3039 0000 4486
>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
>>     -
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ovn-controller exit])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -# Logical network:
>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>     -# sw1 has a single port bound on hv1
>>     -# sw2 has a single port bound on hv2
>>     -
>>     -ovn-nbctl lr-add ro
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl ls-add sw2
>>     -
>>     -sw1_ro_mac=00:00:10:00:00:01
>>     -sw1_ro_ip=10.0.0.1
>>     -sw2_ro_mac=00:00:20:00:00:01
>>     -sw2_ro_ip=20.0.0.1
>>     -sw1_p1_mac=00:00:10:00:00:02
>>     -sw1_p1_ip=10.0.0.2
>>     -sw2_p1_mac=00:00:20:00:00:02
>>     -sw2_p1_ip=20.0.0.2
>>     -
>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>     type=router \
>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>     type=router \
>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>     -
>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>     -
>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -sleep 1
>>     -
>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>     eth.dst==$sw1_ro_mac &&
>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>     ip4.dst==$sw2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -
>>     -# Start by Sending the packet and make sure it makes it there as
>>     expected
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>     ip4.dst==$sw2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Stop ovn-controller on hv2
>>     -as hv2 ovs-appctl -t ovn-controller exit
>>     -
>>     -# Now send the packet again. This time, it should not arrive.
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>     -as hv2 start_daemon ovn-controller
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- external logical port])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -sim_add hv2
>>     -sim_add hv3
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>     -
>>     -# Add a couple of external logical port
>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
>>     --- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 
>> ae70::6"
>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
>>     -"f0:00:00:00:00:03 10.0.0.6 ae70::6"
>>     -ovn-nbctl lsp-set-type ls1-lp_ext1 external
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
>>     --- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 
>> ae70::7"
>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
>>     -"f0:00:00:00:00:04 10.0.0.7 ae70::8"
>>     -ovn-nbctl lsp-set-type ls1-lp_ext2 external
>>     -
>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>     <http://10.0.0.0/24> \
>>     -options="\"server_id\"=\"10.0.0.1\"
>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>     -
>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>     -
>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
>>     -
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
>>     -
>>     -# Create a logical router and connect it to ls1
>>     -ovn-nbctl lr-add lr0
>>     -ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
>>     <http://10.0.0.1/24>
>>     -ovn-nbctl lsp-add ls1 ls1-lr0
>>     -ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
>>     -    options:router-port=lr0-ls1 addresses=router
>>     -
>>     -# Create HA chassis group
>>     -ovn-nbctl ha-chassis-group-add hagrp1
>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>     -
>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>     ha_chassis_group name="hagrp1"`
>>     -
>>     -# There should be 1 HA_Chassis rows with chassis sets
>>     -OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk
>>     '{print $3}' \
>>     -| grep '-' | wc -l ], [0], [1
>>     -])
>>     -
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-phys hv1-ext1 -- \
>>     -    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
>>     -    options:rxq_pcap=hv1/ext1-rx.pcap \
>>     -    ofport-request=2
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-phys hv2-ext2 -- \
>>     -    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
>>     -    options:rxq_pcap=hv2/ext2-rx.pcap \
>>     -    ofport-request=2
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -as hv3
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.3
>>     -ovs-vsctl -- add-port br-phys hv3-ext3 -- \
>>     -    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
>>     -    options:rxq_pcap=hv3/ext3-rx.pcap \
>>     -    ofport-request=2
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>     10.0.0.6 in hv1 and
>>     -# hv2 as ha-chassis-group is not set and no localnet port added
>>     to ls1.
>>     -AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
>>     -wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>>     -])
>>     -
>>     -hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print 
>> $3}')
>>     -hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print 
>> $3}')
>>     -hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print 
>> $3}')
>>     -
>>     -# The port_binding row for ls1-lp_ext1 should have empty chassis
>>     -chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -
>>     -AT_CHECK([test x$chassis == x], [0], [])
>>     -
>>     -# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
>>     -ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
>>     -ha-chassis-group=$hagrp1_uuid
>>     -
>>     -# Get the hagrp1 uuid in SB DB.
>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>     ha_chassis_group \
>>     -name="hagrp1"`
>>     -
>>     -# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
>>     -OVS_WAIT_UNTIL(
>>     -    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group find \
>>     -port_binding logical_port=ls1-lp_ext1`
>>     -     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
>>     -
>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>     10.0.0.6 in hv1 and hv2
>>     -# as no localnet port added to ls1 yet.
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>>     -])
>>     -
>>     -# Add the localnet port to the logical switch ls1
>>     -ovn-nbctl lsp-add ls1 ln-public
>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>     -ovn-nbctl lsp-set-type ln-public localnet
>>     -ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
>>     -
>>     -ln_public_key=$(ovn-sbctl list port_binding ln-public | grep
>>     tunnel_key | \
>>     -awk '{print $3}')
>>     -
>>     -# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of the
>>     -# ha chassis group.
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = "$hv1_uuid"])
>>     -
>>     -# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port in hv1
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | grep
>>     reg14=0x$ln_public_key | \
>>     -wc -l], [0], [3
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>     -])
>>     -
>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
>>     -])
>>     -
>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 -
>>     10.0.0.7 in hv1 and
>>     -# hv2 as requested-chassis option is not set.
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
>>     -])
>>     -
>>     -as hv1
>>     -ovs-vsctl show
>>     -
>>     -# This shell function sends a DHCP request packet
>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
>>     -test_dhcp() {
>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
>>     -    shift; shift; shift; shift; shift;
>>     -    if test $use_ip != 0; then
>>     -        src_ip=$1
>>     -        dst_ip=$2
>>     -        shift; shift;
>>     -    else
>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>     -    fi
>>     -    local
>>     
>> request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip} 
>>
>>     -    # udp header and dhcp header
>>     -    request=${request}0044004300fc0000
>>     -
>>     
>> request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac} 
>>
>>     -    # client hardware padding
>>     -    request=${request}00000000000000000000
>>     -    # server hostname
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # boot file name
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # dhcp magic cookie
>>     -    request=${request}63825363
>>     -    # dhcp message type
>>     -    request=${request}3501${dhcp_type}ff
>>     -
>>     -    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
>>     -    # total IP length will be the IP length of the request packet
>>     -    # (which is 272 in our case) + 8 (padding bytes) +
>>     (expected_dhcp_opts / 2)
>>     -    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>     -    udp_len=`expr $ip_len - 20`
>>     -    ip_len=$(printf "%x" $ip_len)
>>     -    udp_len=$(printf "%x" $udp_len)
>>     -    # $ip_len var will be in 3 digits i.e 134. So adding a '0'
>>     before $ip_len
>>     -    local
>>     
>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>
>>     -    # udp header and dhcp header.
>>     -    # $udp_len var will be in 3 digits. So adding a '0' before
>>     $udp_len
>>     -
>>     reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
>>     -    # your ip address
>>     -    reply=${reply}${offer_ip}
>>     -    # next server ip address, relay agent ip address, client mac
>>     address
>>     -    reply=${reply}0000000000000000${src_mac}
>>     -    # client hardware padding
>>     -    reply=${reply}00000000000000000000
>>     -    # server hostname
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # boot file name
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -
>>     
>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>
>>     -    # dhcp magic cookie
>>     -    reply=${reply}63825363
>>     -    # dhcp message type
>>     -    local dhcp_reply_type=02
>>     -    if test $dhcp_type = 03; then
>>     -        dhcp_reply_type=05
>>     -    fi
>>     -
>>     
>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>
>>     -    echo $reply >> ext1_v4.expected
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>     hv${inport}-ext${inport} $request
>>     -}
>>     -
>>     -
>>     -trim_zeros() {
>>     -    sed 's/\(00\)\{1,\}$//'
>>     -}
>>     -
>>     -# This shell function sends a DHCPv6 request packet
>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>     OUTPORT...
>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>     DHCPv6
>>     -# packet should be received twice (one from ovn-controller and
>>     the other
>>     -# from the "ovs-ofctl monitor br-int resume"
>>     -test_dhcpv6() {
>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>     -    local req_pkt_in_expected=$6
>>     -    local
>>     request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
>>     -    # dst ip ff02::1:2
>>     -    request=${request}ff020000000000000000000000010002
>>     -    # udp header and dhcpv6 header
>>     -    request=${request}02220223002affff${msg_code}010203
>>     -    # Client identifier
>>     -    request=${request}0001000a00030001${src_mac}
>>     -    # IA-NA (Identity Association for Non Temporary Address)
>>     -    request=${request}0003000c0102030400000e1000001518
>>     -    shift; shift; shift; shift; shift;
>>     -
>>     -    local server_mac=000000100001
>>     -    local server_lla=fe80000000000000020000fffe100001
>>     -    local reply_code=07
>>     -    if test $msg_code = 01; then
>>     -        reply_code=02
>>     -    fi
>>     -    local msg_len=54
>>     -    if test $offer_ip = 1; then
>>     -        msg_len=28
>>     -    fi
>>     -    local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
>>     -    reply=${reply}${server_lla}${src_lla}
>>     -
>>     -    # udp header and dhcpv6 header
>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>     -    # Client identifier
>>     -    reply=${reply}0001000a00030001${src_mac}
>>     -    # IA-NA
>>     -    if test $offer_ip != 1; then
>>     - reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
>>     -        reply=${reply}ffffffffffffffff
>>     -    fi
>>     -    # Server identifier
>>     -    reply=${reply}0002000a00030001${server_mac}
>>     -
>>     -    echo $reply | trim_zeros >> ext${inport}_v6.expected
>>     -    # The inport also receives the request packet since it is
>>     connected
>>     -    # to the br-phys.
>>     -    #echo $request >> ext${inport}_v6.expected
>>     -
>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>     hv${inport}-ext${inport} $request
>>     -}
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
>>     -as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
>>     -
>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
>>     -as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
>>     -
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -# Send DHCPDISCOVER.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -server_mac=ff1000000001
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>     -$expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 1 in hv1.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 0 in hv2.
>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>     -cat ext1_v4.expected | cut -c -48 > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat ext1_v4.expected | cut -c 53- > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>     -
>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>     to receive
>>     -# the DHCP request packet. So reset the pcap files so that its
>>     easier to test.
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -rm -f ext1_v4.expected
>>     -rm -f ext1_v4.packets
>>     -
>>     -# Send DHCPv6 request
>>     -src_mac=f00000000003
>>     -src_lla=fe80000000000000f20000fffe000003
>>     -offer_ip=ae700000000000000000000000000006
>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>     -
>>     -# NXT_RESUMEs should be 2 in hv1.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 0 in hv2.
>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap | \
>>     -sort > ext1_v6.packets
>>     -cat ext1_v6.expected | cut -c -120 > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>     -# Skipping the UDP checksum
>>     -cat ext1_v6.expected | cut -c 125- > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>     -
>>     -rm -f ext1_v6.expected
>>     -rm -f ext1_v6.packets
>>     -
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -# Delete the ha-chassis hv1.
>>     -ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = ""])
>>     -
>>     -# Add hv2 to the ha chassis group
>>     -ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
>>     -
>>     -ovn-sbctl list ha_chassis_group
>>     -ovn-sbctl list ha_chassis
>>     -
>>     -ovn-sbctl find port_binding logical_port=ls1-lp_ext1
>>     -
>>     -# The ls1-lp_ext1 should be bound to hv2
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = "$hv2_uuid"])
>>     -
>>     -# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port
>>     in hv2
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | grep
>>     reg14=0x$ln_public_key | \
>>     -wc -l], [0], [3
>>     -])
>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>     -])
>>     -
>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>     -])
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>     -grep controller | grep tp_src=546 | grep \
>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>     -grep reg14=0x$ln_public_key | wc -l], [0], [0
>>     -])
>>     -
>>     -# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should
>>     come from
>>     -# hv2 ovn-controller.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -server_mac=ff1000000001
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>     -$expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 2 in hv1.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 1 in hv2.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>     -cat ext1_v4.expected | cut -c -48 > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat ext1_v4.expected | cut -c 53- > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>     -
>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>     to receive
>>     -# the DHCP request packet. So reset the pcap files so that its
>>     easier to test.
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -rm -f ext1_v4.expected
>>     -
>>     -# Send DHCPv6 request again
>>     -src_mac=f00000000003
>>     -src_lla=fe80000000000000f20000fffe000003
>>     -offer_ip=ae700000000000000000000000000006
>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
>>     -
>>     -# NXT_RESUMEs should be 2 in hv1.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap | \
>>     -sort > ext1_v6.packets
>>     -cat ext1_v6.expected | cut -c -120 > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>     -# Skipping the UDP checksum
>>     -cat ext1_v6.expected | cut -c 125- > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>     -
>>     -rm -f ext1_v6.expected
>>     -rm -f ext1_v6.packets
>>     -
>>     -as hv1
>>     -ovs-vsctl show
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>     -reset_pcap_file br-phys hv1/br-phys
>>     -
>>     -as hv2
>>     -ovs-vsctl show
>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -reset_pcap_file br-phys hv2/br-phys
>>     -
>>     -# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
>>     -# response should come from the router pipeline of hv2.
>>     -ext1_mac=f00000000003
>>     -router_mac=a01000000001
>>     -ext1_ip=`ip_to_hex 10 0 0 6`
>>     -router_ip=`ip_to_hex 10 0 0 1`
>>     
>> -arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip} 
>>
>>     -
>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
>>     
>> -expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip} 
>>
>>     -echo $expected_response > expout
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap > ext1_arp_resp
>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>     -
>>     -# Verify that the response came from hv2
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv2/br-phys_n1-tx.pcap > ext1_arp_resp
>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>     -
>>     -# Now add 3 ha chassis to the ha chassis group
>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
>>     -
>>     -# hv1 should be master and claim ls1-lp_ext1
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = "$hv1_uuid"])
>>     -
>>     -as hv1
>>     -ovs-vsctl show
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>     -reset_pcap_file br-phys hv1/br-phys
>>     -
>>     -as hv2
>>     -ovs-vsctl show
>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -reset_pcap_file br-phys hv2/br-phys
>>     -
>>     -as hv3
>>     -ovs-vsctl show
>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>     -reset_pcap_file br-phys hv3/br-phys
>>     -
>>     -# Send DHCPDISCOVER.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -server_mac=ff1000000001
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>     -$expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 3 in hv1.
>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>     -cat ext1_v4.expected | cut -c -48 > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat ext1_v4.expected | cut -c 53- > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>     -
>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>     to receive
>>     -# the DHCP request packet. So reset the pcap files so that its
>>     easier to test.
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -rm -f ext1_v4.expected
>>     -rm -f ext1_v4.packets
>>     -
>>     -# Send DHCPv6 request
>>     -src_mac=f00000000003
>>     -src_lla=fe80000000000000f20000fffe000003
>>     -offer_ip=ae700000000000000000000000000006
>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>     -
>>     -# NXT_RESUMEs should be 4 in hv1.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap | \
>>     -sort > ext1_v6.packets
>>     -cat ext1_v6.expected | cut -c -120 > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>     -# Skipping the UDP checksum
>>     -cat ext1_v6.expected | cut -c 125- > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>     -
>>     -rm -f ext1_v6.expected
>>     -rm -f ext1_v6.packets
>>     -as hv1 reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -# Now increase the priority of hv3 so it becomes master.
>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
>>     -
>>     -# hv3 should be master and claim ls1-lp_ext1
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = "$hv3_uuid"])
>>     -
>>     -as hv1
>>     -ovs-vsctl show
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>     -reset_pcap_file br-phys hv1/br-phys
>>     -
>>     -as hv2
>>     -ovs-vsctl show
>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>     -reset_pcap_file br-phys hv2/br-phys
>>     -
>>     -as hv2
>>     -ovs-vsctl show
>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>     -reset_pcap_file br-phys hv3/br-phys
>>     -
>>     -# Send DHCPDISCOVER.
>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>     -server_ip=`ip_to_hex 10 0 0 1`
>>     -server_mac=ff1000000001
>>     -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>     -$expected_dhcp_opts
>>     -
>>     -# NXT_RESUMEs should be 4 in hv1.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 1 in hv3.
>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>     -cat ext1_v4.expected | cut -c -48 > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>     -# Skipping the IPv4 checksum.
>>     -cat ext1_v4.expected | cut -c 53- > expout
>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>     -
>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>     to receive
>>     -# the DHCP request packet. So reset the pcap files so that its
>>     easier to test.
>>     -as hv1
>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>     -
>>     -rm -f ext1_v4.expected
>>     -rm -f ext1_v4.packets
>>     -
>>     -# Send DHCPv6 request
>>     -src_mac=f00000000003
>>     -src_lla=fe80000000000000f20000fffe000003
>>     -offer_ip=ae700000000000000000000000000006
>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>     -
>>     -# NXT_RESUMEs should be 4 in hv1.
>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv2.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -# NXT_RESUMEs should be 2 in hv3.
>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c
>>     NXT_RESUME`])
>>     -
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/ext1-tx.pcap | \
>>     -sort > ext1_v6.packets
>>     -cat ext1_v6.expected | cut -c -120 > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>     -# Skipping the UDP checksum
>>     -cat ext1_v6.expected | cut -c 125- > expout
>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>     -
>>     -# disconnect hv3 from the network, hv1 should take over
>>     -as hv3
>>     -port=${sandbox}_br-phys
>>     -as main ovs-vsctl del-port n1 $port
>>     -
>>     -# hv1 should be master and claim ls1-lp_ext1
>>     -OVS_WAIT_UNTIL(
>>     -    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>     -logical_port=ls1-lp_ext1`
>>     -    test "$chassis" = "$hv1_uuid"])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- Address Set Incremental Processing])
>>     -AT_KEYWORDS([ovn_as_inc])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.10
>>     -
>>     -ovn-nbctl ls-add ls1
>>     -for i in 1 2; do
>>     -    ovn-nbctl lsp-add ls1 lp$i \
>>     -        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i"
>>     -    as hv1 ovs-vsctl \
>>     -        -- add-port br-int vif$i \
>>     -        -- set Interface vif$i \
>>     -            external-ids:iface-id=lp$i
>>     -done
>>     -
>>     -for i in 1 2 3; do
>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>     -    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>     -            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}'
>>     allow-related
>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>     [0], [ignore])
>>     -
>>     -    # Update address set as1
>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"],
>>     [0], [ignore])
>>     -
>>     -    # Update address set as2
>>     -    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>     [0], [ignore])
>>     -
>>     -    # Add another ACL referencing as1
>>     -    n_flows_before=`ovs-ofctl dump-flows br-int | grep
>>     "10.1.2.10" | wc -l`
>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>     -            'outport=="lp2" && ip4 && ip4.src == $as1' allow-related
>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>     | wc -l`
>>     -    AT_CHECK([test $(expr $n_flows_before \* 2) =
>>     $n_flows_after], [0], [ignore])
>>     -
>>     -    # Remove an ACL
>>     -    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
>>     -            'outport=="lp2" && ip4 && ip4.src == $as1'
>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>     | wc -l`
>>     -    AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore])
>>     -
>>     -    # Remove as1 while it is still used by an ACL, the lflows
>>     should be reparsed and
>>     -    # parsing should fail.
>>     -    echo "before del as1"
>>     -    ovn-nbctl list addr | grep as1
>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid
>>     -    echo "after del as1"
>>     -    ovn-nbctl list addr | grep as1
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>     [1], [ignore])
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>     [1], [ignore])
>>     -
>>     -    # Recreate as1
>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>     [0], [ignore])
>>     -
>>     -    # Remove ACLs and address sets
>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr
>>     $as2_uuid
>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>     [1], [ignore])
>>     -
>>     -    ovn-nbctl --wait=hv acl-del ls1
>>     -done
>>     -
>>     -# Gracefully terminate daemons
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ovn-controller restart])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>     -# sw1 has a single port bound on hv1
>>     -# sw2 has a single port bound on hv2
>>     -
>>     -ovn-nbctl lr-add ro
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl ls-add sw2
>>     -
>>     -sw1_ro_mac=00:00:10:00:00:01
>>     -sw1_ro_ip=10.0.0.1
>>     -sw2_ro_mac=00:00:20:00:00:01
>>     -sw2_ro_ip=20.0.0.1
>>     -sw1_p1_mac=00:00:10:00:00:02
>>     -sw1_p1_ip=10.0.0.2
>>     -sw2_p1_mac=00:00:20:00:00:02
>>     -sw2_p1_ip=20.0.0.2
>>     -
>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>     type=router \
>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>     type=router \
>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>     -
>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>     -
>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -sleep 1
>>     -
>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>     eth.dst==$sw1_ro_mac &&
>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>     ip4.dst==$sw2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -
>>     -# Start by Sending the packet and make sure it makes it there as
>>     expected
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -# Expected packet has TTL decreased by 1
>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>     ip4.dst==$sw2_p1_ip &&
>>     -       udp && udp.src==53 && udp.dst==4369"
>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -# Stop ovn-controller on hv2 with --restart flag
>>     -as hv2 ovs-appctl -t ovn-controller exit --restart
>>     -
>>     -# Now send the packet again. This time, it should still arrive
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -cat expected expected > expected2
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
>>     -
>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>     -as hv2 start_daemon ovn-controller
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
>>     -ovn_start
>>     -
>>     -# Set up a switch with some switch ports of varying address types
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl set logical_switch sw1
>>     other_config:subnet=192.168.0.0/24 <http://192.168.0.0/24>
>>     -
>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>     -ovn-nbctl lsp-add sw1 sw1-p2
>>     -ovn-nbctl lsp-add sw1 sw1-p3
>>     -ovn-nbctl lsp-add sw1 sw1-p4
>>     -
>>     -ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1
>>     aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
>>     -ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
>>     -ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
>>     -ovn-nbctl lsp-set-addresses sw1-p4 "router"
>>     -ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
>>     -
>>     -ovn-nbctl list logical_switch_port
>>     -
>>     -# Now try to add duplicate addresses on a new port. These should
>>     all fail
>>     -ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     10.0.0.1"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     10.0.0.2"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     aef0::1"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     aef0::2"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     192.168.0.2"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2
>>     -])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>     192.168.0.3"], [1], [],
>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3
>>     -])
>>     -
>>     -# Now try re-setting sw1-p1. This should succeed
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01
>>     10.0.0.1 aef0::1"])
>>     -
>>     -# Now create a new switch and try setting IP addresses the same
>>     as the
>>     -# first switch. This should succeed.
>>     -ovn-nbctl ls-add sw2
>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>     -
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>     10.0.0.1"])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>     192.168.0.2"])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>     192.168.0.3"])
>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>     aef0::1"])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- router - check packet length - icmp defrag])
>>     -AT_KEYWORDS([check packet length])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl lsp-add sw0 sw0-port1
>>     -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
>>     -
>>     -ovn-nbctl lr-add lr0
>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
>>     <http://10.0.0.1/24>
>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>     -
>>     -ovn-nbctl ls-add public
>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> lsp-add public
>>     public-lr0
>>     -ovn-nbctl lsp-set-type public-lr0 router
>>     -ovn-nbctl lsp-set-addresses public-lr0 router
>>     -ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
>>     -
>>     -# localnet port
>>     -ovn-nbctl lsp-add public ln-public
>>     -ovn-nbctl lsp-set-type ln-public localnet
>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>     -
>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
>>     -ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
>>     <http://10.0.0.0/24>
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -reset_pcap_file() {
>>     -     local iface=$1
>>     -     local pcap_file=$2
>>     -     ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=dummy-tx.pcap \
>>     - options:rxq_pcap=dummy-rx.pcap
>>     -     rm -f ${pcap_file}*.pcap
>>     -     ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     - options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -     printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -test_ip_packet_larger() {
>>     -    local icmp_pmtu_reply_expected=$1
>>     -
>>     -    # Send ip packet from sw0-port1 to outside
>>     -    src_mac="505400000001" # sw-port1 mac
>>     -    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
>>     -    src_ip=`ip_to_hex 10 0 0 3`
>>     -    dst_ip=`ip_to_hex 172 168 0 3`
>>     -    # Set the packet length to 100.
>>     -    pkt_len=0064
>>     - packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
>>     -    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
>>     - 
>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>     - 
>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>     - 
>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>     - 
>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>     -    packet=${packet}${orig_packet_l3}
>>     -
>>     -
>>     
>> gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064 
>>
>>     -
>>     -    # If icmp_pmtu_reply_expected is 0, it means the packet is
>>     lesser than
>>     -    # the gateway mtu and should be delivered to the provider
>>     bridge via the
>>     -    # localnet port.
>>     -    # If icmp_pmtu_reply_expected is 1, it means the packet is
>>     larger than
>>     -    # the gateway mtu and ovn-controller should drop the packet
>>     and instead
>>     -    # generate ICMPv4  Destination Unreachable message with pmtu
>>     set to 42.
>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>     -        # Packet to expect at br-phys.
>>     -        src_mac="000020201213"
>>     -        dst_mac="00000012af11"
>>     -        src_ip=`ip_to_hex 10 0 0 3`
>>     -        dst_ip=`ip_to_hex 172 168 0 3`
>>     - expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
>>     - expected=${expected}${src_ip}${dst_ip}0304000000000000
>>     - expected=${expected}000000000000000000000000000000000000
>>     - expected=${expected}000000000000000000000000000000000000
>>     - expected=${expected}000000000000000000000000000000000000
>>     - expected=${expected}000000000000000000000000000000000000
>>     -        echo $expected > br_phys_n1.expected
>>     -        echo $gw_ip_garp >> br_phys_n1.expected
>>     -    else
>>     -        # MTU would be 100 - 18 = 82 (hex 0052)
>>     -        mtu=0052
>>     -        src_ip=`ip_to_hex 10 0 0 1`
>>     -        dst_ip=`ip_to_hex 10 0 0 3`
>>     -        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip
>>     + payload))
>>     -        reply_pkt_len=0080
>>     -        ip_csum=bd91
>>     -
>>     
>> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
>>     - icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
>>     - icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
>>     -        icmp_reply=${icmp_reply}${orig_packet_l3}
>>     -        echo $icmp_reply > hv1-vif1.expected
>>     -    fi
>>     -
>>     -    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>     -    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>     -
>>     -    # Send packet from sw0-port1 to outside
>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>     -
>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>     -        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap],
>>     [br_phys_n1.expected])
>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" hv1/vif1-tx.pcap > pkts
>>     -        # hv1/vif1-tx.pcap can receive the GARP packet generated
>>     by ovn-controller
>>     -        # for the gateway router port. So ignore this packet.
>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>     -        AT_CHECK([cat packets], [0], [])
>>     -    else
>>     -        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" hv1/br-phys_n1-tx.pcap  > \
>>     -        pkts
>>     -        # hv1/br-phys_n1-tx.pcap can receive the GARP packet
>>     generated by ovn-controller
>>     -        # for the gateway router port. So ignore this packet.
>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>     -        AT_CHECK([cat packets], [0], [])
>>     -    fi
>>     -}
>>     -
>>     -ovn-nbctl show
>>     -ovn-sbctl show
>>     -
>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
>>     -| grep "check_pkt_larger" | wc -l], [0], [[0
>>     -]])
>>     -dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep
>>     _uuid | \
>>     -awk '{print $3}')
>>     -ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
>>     -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
>>     -
>>     -# Set the gateway mtu to 100. If the packet length is > 100,
>>     ovn-controller
>>     -# should send icmp host not reachable with pmtu set to 100.
>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>     options:gateway_mtu=100
>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>     -OVS_WAIT_UNTIL([
>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>     "check_pkt_larger(100)" | \
>>     -    wc -l` -eq 1
>>     -])
>>     -
>>     -icmp_reply_expected=1
>>     -test_ip_packet_larger $icmp_reply_expected
>>     -
>>     -# Set the gateway mtu to 500.
>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>     options:gateway_mtu=500
>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>     -OVS_WAIT_UNTIL([
>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>     "check_pkt_larger(500)" | \
>>     -    wc -l` -eq 1
>>     -])
>>     -
>>     -# Now the packet should be sent via the localnet port to br-phys.
>>     -icmp_reply_expected=0
>>     -test_ip_packet_larger $icmp_reply_expected
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IP packet buffering])
>>     -AT_KEYWORDS([ip-buffering])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# One LR lr0 that has switches sw0 (192.168.1.0/24
>>     <http://192.168.1.0/24>) and
>>     -# sw1 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>     -#
>>     -# Physical network:
>>     -# Tw0 hypervisors hv[12].
>>     -# hv1 hosts vif sw0-p0.
>>     -# hv1 hosts vif sw1-p0.
>>     -
>>     -send_icmp_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>     ipv4_dst=$6 ip_chksum=$7 data=$8
>>     -    shift 8
>>     -
>>     -    local ip_ttl=ff
>>     -    local ip_len=001c
>>     -    local
>>     
>> packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data} 
>>
>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>> $packet
>>     -}
>>     -
>>     -send_icmp6_packet() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>     -    shift 8
>>     -
>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>> $packet
>>     -}
>>     -
>>     -get_arp_req() {
>>     -    local eth_src=$1 spa=$2 tpa=$3
>>     -    local
>>     
>> request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa} 
>>
>>     -    echo $request
>>     -}
>>     -
>>     -send_arp_reply() {
>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
>>     -    local
>>     
>> request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa} 
>>
>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>     $request
>>     -}
>>     -
>>     -send_na() {
>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 dst_ip=$6
>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>     -    local
>>     
>> request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src} 
>>
>>     -
>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>     $request
>>     -}
>>     -
>>     -get_nd() {
>>     -    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>     -
>>     
>> request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src} 
>>
>>     -
>>     -    echo $request
>>     -}
>>     -
>>     -net_add n1
>>     -
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl ls-add sw1
>>     -
>>     -ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24> 2001:0:0:0:0:0:0:1/64
>>     -ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
>>     -    type=router options:router-port=sw0 \
>>     -    -- lsp-set-addresses rp-sw0 router
>>     -
>>     -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64
>>     -ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
>>     -    type=router options:router-port=sw1 \
>>     -    -- lsp-set-addresses rp-sw1 router
>>     -
>>     -ovn-nbctl lsp-add sw0 sw0-p0 \
>>     -    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2
>>     2001::2"
>>     -
>>     -ovn-nbctl lsp-add sw1 sw1-p0 \
>>     -    -- lsp-set-addresses sw1-p0 unknown
>>     -
>>     -OVN_POPULATE_ARP
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -ip_to_hex() {
>>     -    printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -src_mac=f00000010203
>>     -src_ip=$(ip_to_hex 192 168 1 2)
>>     -src_ip6=20010000000000000000000000000002
>>     -
>>     -router_mac0=000001010203
>>     -router_mac1=000002010203
>>     -router_ip=$(ip_to_hex 172 16 1 1)
>>     -router_ip6=20020000000000000000000000000001
>>     -
>>     -dst_mac=001122334455
>>     -dst_ip=$(ip_to_hex 172 16 1 10)
>>     -dst_ip6=20020000000000000000000000000010
>>     -
>>     -data=0800bee4391a0001
>>     -
>>     -send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 
>> $data
>>     -send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
>>     -echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
>>     -echo
>>     
>> "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}" 
>>
>>     >> expected
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -nd_ip=ff0200000000000000000001ff000010
>>     -ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
>>     -
>>     -send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
>>     -echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
>>     -echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >>
>>     expected
>>     -send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- neighbor update on same HV])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# A public switch (pub) with a localnet port connected to two LRs
>>     (lr0 and lr1)
>>     -# each with a distributed gateway port.
>>     -# Two VMs: lp0 on sw0 connected to lr0
>>     -#          lp1 on sw1 connected to lr1
>>     -#
>>     -# This test adds a floating IP to each VM so when they are bound
>>     to the same
>>     -# hypervisor, it checks that the GARP sent by ovn-controller
>>     causes the
>>     -# MAC_Binding entries to be updated properly on each logical router.
>>     -# It will also capture packets on the physical interface to make
>>     sure that the
>>     -# GARPs have been sent out to the external network as well.
>>     -
>>     -# Create logical switches
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl ls-add pub
>>     -
>>     -# Created localnet port on public switch
>>     -ovn-nbctl lsp-add pub ln-pub
>>     -ovn-nbctl lsp-set-type ln-pub localnet
>>     -ovn-nbctl lsp-set-addresses ln-pub unknown
>>     -ovn-nbctl lsp-set-options ln-pub network_name=phys
>>     -
>>     -# Create logical routers and connect them to public switch
>>     -ovn-nbctl create Logical_Router name=lr0
>>     -ovn-nbctl create Logical_Router name=lr1
>>     -
>>     -ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
>>     <http://172.24.4.220/24>
>>     -ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
>>     -    type=router options:router-port=lr0-pub
>>     options:nat-addresses="router" addresses="router"
>>     -ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
>>     <http://172.24.4.221/24>
>>     -ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
>>     -    type=router options:router-port=lr1-pub
>>     options:nat-addresses="router" addresses="router"
>>     -
>>     -ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
>>     -ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
>>     -
>>     -# Connect sw0 and sw1 to lr0 and lr1
>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>>     <http://10.0.0.254/24>
>>     -ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0
>>     type=router \
>>     -    options:router-port=lr0-sw0 addresses="router"
>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
>>     <http://20.0.0.254/24>
>>     -ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1
>>     type=router \
>>     -    options:router-port=lr1-sw1 addresses="router"
>>     -
>>     -
>>     -# Add SNAT rules
>>     -ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
>>     <http://10.0.0.0/24>
>>     -ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
>>     <http://20.0.0.0/24>
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 172.24.4.1
>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>     -
>>     -ovs-vsctl add-port br-int vif0 -- set Interface vif0
>>     external-ids:iface-id=lp0
>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>     external-ids:iface-id=lp1
>>     -
>>     -ovn-nbctl lsp-add sw0 lp0
>>     -ovn-nbctl lsp-add sw1 lp1
>>     -ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
>>     -ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
>>     -
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>     -
>>     -# Create two floating IPs, one for each VIF
>>     -ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
>>     -ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
>>     -
>>     -# Check that the MAC_Binding entries have been properly created
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>     logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>     logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
>>     -
>>     -# Check that the GARPs went also to the external physical network
>>     -# Wait until at least 4 packets have arrived and copy them to a
>>     separate file as
>>     -# more GARPs are expected in the capture in order to avoid race
>>     conditions.
>>     -OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>     <http://ovs-pcap.in>" hv1/br-phys-tx.pcap | wc -l` -gt 4])
>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>     hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
>>     -
>>     -# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
>>     -echo
>>     
>> "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464" 
>>
>>     > expout
>>     -# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
>>     -echo
>>     
>> "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc" 
>>
>>     >> expout
>>     -# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
>>     -echo
>>     
>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8" 
>>
>>     >> expout
>>     -# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
>>     -echo
>>     
>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd" 
>>
>>     >> expout
>>     -AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
>>     -#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
>>     -
>>     -OVN_CLEANUP([hv1])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ipam to non-ipam])
>>     -ovn_start
>>     -
>>     -ovn-nbctl --wait=hv set NB_Global .
>>     options:mac_prefix="0a:00:00:00:00:00"
>>     -ovn-nbctl ls-add sw0
>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>     subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>     -
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>     dynamic_addresses], [0],
>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>     -])
>>     -
>>     -ovn-nbctl --wait=sb lsp-set-addresses p0 router
>>     -
>>     -ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
>>     -
>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>     dynamic_addresses], [0], [[[]]
>>     -])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- ipam router ports])
>>     -ovn_start
>>     -
>>     -ovn-nbctl ls-add sw
>>     -ovn-nbctl set logical_switch sw
>>     other-config:subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>     -
>>     -for i in 2 3 4; do
>>     -    ovn-nbctl lr-add ro$i
>>     -    ovn-nbctl lsp-add sw swp$i
>>     -    ovn-nbctl --wait=sb lsp-set-addresses swp$i
>>     "02:00:00:00:00:0$i dynamic"
>>     -    cidr=$(ovn-nbctl get logical_switch_port swp$i
>>     dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
>>     -    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 --
>>     set logical_switch_port swp$i type=router
>>     options:router-port=rop$i addresses=router;
>>     -    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i
>>     networks], [0], [[["192.168.1.$i/24"]]
>>     -])
>>     -done
>>     -
>>     -ovn-nbctl list logical_switch_port
>>     -ovn-nbctl list logical_router_port
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- test transport zones])
>>     -ovn_start
>>     -
>>     -net_add n1
>>     -for i in 1 2 3 4 5; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.$i.1
>>     -done
>>     -
>>     -dnl Wait for the changes to be propagated
>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -dnl Assert that each Chassis has a tunnel formed to every other
>>     Chassis
>>     -as hv1
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv2
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv3
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv4
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv5
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -]])
>>     -
>>     -dnl Let's now add some Chassis to different transport zones
>>     -dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
>>     -dnl   should have tunnels formed between the other two Chassis
>>     (hv2 and hv3)
>>     -dnl
>>     -dnl * hv2: Will be part of one transport zone: tz1. It should
>>     have a tunnel
>>     -dnl   to hv1 but not to hv3
>>     -dnl
>>     -dnl * hv3: Will be part of one transport zone: tz2. It should
>>     have a tunnel
>>     -dnl   to hv1 but not to hv2
>>     -dnl
>>     -dnl * hv4 and hv5: Will not have any TZ set so they will keep the
>>     tunnels
>>     -dnl   between themselves and remove the tunnels to other Chassis
>>     which now
>>     -dnl   belongs to some TZs
>>     -dnl
>>     -as hv1
>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
>>     -
>>     -as hv2
>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
>>     -
>>     -as hv3
>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
>>     -
>>     -dnl Wait for the changes to be propagated
>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -as hv1
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv2-0
>>     -ovn-hv3-0
>>     -]])
>>     -
>>     -as hv2
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -]])
>>     -
>>     -as hv3
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -]])
>>     -
>>     -as hv4
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv5-0
>>     -]])
>>     -
>>     -as hv5
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv4-0
>>     -]])
>>     -
>>     -dnl Removing the transport zones should make all Chassis to create
>>     -dnl tunnels between every other Chassis again
>>     -for i in 1 2 3; do
>>     -    as hv$i
>>     -    ovs-vsctl remove open . external-ids ovn-transport-zones
>>     -done
>>     -
>>     -dnl Wait for the changes to be propagated
>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>     -
>>     -as hv1
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv2
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv3
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv4-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv4
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv5-0
>>     -]])
>>     -
>>     -as hv5
>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>     type="geneve" | awk NF | sort], [0],
>>     -[[ovn-hv1-0
>>     -ovn-hv2-0
>>     -ovn-hv3-0
>>     -ovn-hv4-0
>>     -]])
>>     -
>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis
>>     mac])
>>     -ovn_start
>>     -
>>     -
>>     -# In this test cases we create 2 switches, all connected to same
>>     -# physical network (through br-phys on each HV). Each switch has
>>     -# 1 VIF. Each HV has 1 VIF port. The first digit
>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>     -# lp23 means VIF 3 on hv2.
>>     -#
>>     -# Each switch's VLAN tag and their logical switch ports are:
>>     -#   - ls1:
>>     -#       - tagged with VLAN 101
>>     -#       - ports: lp11
>>     -#   - ls2:
>>     -#       - tagged with VLAN 201
>>     -#       - ports: lp22
>>     -#
>>     -# Note: a localnet port is created for each switch to connect to
>>     -# physical network.
>>     -
>>     -for i in 1 2; do
>>     -    ls_name=ls$i
>>     -    ovn-nbctl ls-add $ls_name
>>     -    ln_port_name=ln$i
>>     -    if test $i -eq 1; then
>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>     -    elif test $i -eq 2; then
>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
>>     -    fi
>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>     -done
>>     -
>>     -# lsp_to_ls LSP
>>     -#
>>     -# Prints the name of the logical switch that contains LSP.
>>     -lsp_to_ls () {
>>     -    case $1 in dnl (
>>     -        lp?[[11]]) echo ls1 ;; dnl (
>>     -        lp?[[12]]) echo ls2 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -vif_to_ls () {
>>     -    case $1 in dnl (
>>     -        vif?[[11]]) echo ls1 ;; dnl (
>>     -        vif?[[12]]) echo ls2 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -hv_to_num () {
>>     -    case $1 in dnl (
>>     -        hv1) echo 1 ;; dnl (
>>     -        hv2) echo 2 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -vif_to_num () {
>>     -    case $1 in dnl (
>>     -        vif22) echo 22 ;; dnl (
>>     -        vif21) echo 21 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -vif_to_hv () {
>>     -    case $1 in dnl (
>>     -        vif[[1]]?) echo hv1 ;; dnl (
>>     -        vif[[2]]?) echo hv2 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -vif_to_lrp () {
>>     -    echo router-to-`vif_to_ls $1`
>>     -}
>>     -
>>     -hv_to_chassis_mac () {
>>     -     case $1 in dnl (
>>     -        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
>>     -        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
>>     -        *) AT_FAIL_IF([:]) ;;
>>     -    esac
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -       printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -net_add n1
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovs-vsctl set open .
>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>     -    ovs-vsctl set open .
>>     external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    ovs-vsctl add-port br-int vif$i$i -- \
>>     -        set Interface vif$i$i external-ids:iface-id=lp$i$i \
>>     - options:tx_pcap=hv$i/vif$i$i-tx.pcap \
>>     - options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
>>     -                              ofport-request=$i$i
>>     -
>>     -    lsp_name=lp$i$i
>>     -    ls_name=$(lsp_to_ls $lsp_name)
>>     -
>>     -    ovn-nbctl lsp-add $ls_name $lsp_name
>>     -    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i
>>     192.168.$i.$i"
>>     -    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
>>     -
>>     -    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
>>     -
>>     -done
>>     -
>>     -ovn-nbctl lr-add router
>>     -ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03
>>     192.168.1.3/24
>>     -ovn-nbctl <http://192.168.1.3/24-ovn-nbctl> lrp-add router
>>     router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 
>> <http://192.168.2.3/24>
>>     -
>>     -ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port
>>     ls1-to-router type=router options:router-port=router-to-ls1 --
>>     lsp-set-addresses ls1-to-router router
>>     -ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port
>>     ls2-to-router type=router options:router-port=router-to-ls2 --
>>     lsp-set-addresses ls2-to-router router
>>     -
>>     -ovn-nbctl --wait=sb sync
>>     -#ovn-sbctl dump-flows
>>     -
>>     -ovn-nbctl show
>>     -ovn-sbctl show
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -test_ip() {
>>     -    # This packet has bad checksums but logical L3 routing
>>     doesn't check.
>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>     -    local
>>     
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>
>>     -    shift; shift; shift; shift; shift
>>     -    hv=`vif_to_hv $inport`
>>     -    hv_num=`hv_to_num $hv`
>>     -    chassis_mac=`hv_to_chassis_mac $hv`
>>     -    as $hv ovs-appctl netdev-dummy/receive $inport $packet
>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
>>     -    in_ls=`vif_to_ls $inport`
>>     -    in_lrp=`vif_to_lrp $inport`
>>     -    for outport; do
>>     -        out_ls=`vif_to_ls $outport`
>>     -        if test $in_ls = $out_ls; then
>>     -            # Ports on the same logical switch receive exactly
>>     the same packet.
>>     -            echo $packet
>>     -        else
>>     -            # Routing decrements TTL and updates source and dest MAC
>>     -            # (and checksum).
>>     -            outport_num=`vif_to_num $outport`
>>     -            out_lrp=`vif_to_lrp $outport`
>>     -            echo
>>     
>> f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>
>>     -        fi >> $outport.expected
>>     -    done
>>     -}
>>     -
>>     -# Dump a bunch of info helpful for debugging if there's a failure.
>>     -
>>     -echo "------ OVN dump ------"
>>     -ovn-nbctl show
>>     -ovn-sbctl show
>>     -
>>     -echo "------ hv1 dump ------"
>>     -as hv1 ovs-vsctl show
>>     -as hv1 ovs-vsctl list Open_Vswitch
>>     -
>>     -echo "------ hv2 dump ------"
>>     -as hv2 ovs-vsctl show
>>     -as hv2 ovs-vsctl list Open_Vswitch
>>     -
>>     -echo "Send traffic"
>>     -sip=`ip_to_hex 192 168 1 1`
>>     -dip=`ip_to_hex 192 168 2 2`
>>     -test_ip vif11 f00000000011  000001010203 $sip $dip vif22
>>     -
>>     -echo "----------- Post Traffic hv1 dump -----------"
>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -as hv1 ovs-appctl fdb/show br-phys
>>     -
>>     -echo "----------- Post Traffic hv2 dump -----------"
>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>     -as hv2 ovs-appctl fdb/show br-phys
>>     -
>>     -OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
>>     -
>>     -OVN_CLEANUP([hv1],[hv2])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -# Run ovn-nbctl in daemon mode, change to a backup database and
>>     verify that
>>     -# an insert operation is not allowed.
>>     -AT_SETUP([ovn -- can't write to a backup database server instance])
>>     -ovn_start
>>     -on_exit 'kill $(cat ovn-nbctl.pid)'
>>     -export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
>>     -
>>     -AT_CHECK([ovn-nbctl ls-add sw0])
>>     -as ovn-nb
>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>     grep active | wc -l], [0], [1
>>     -])
>>     -ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server
>>     tcp:192.0.2.2:6641 <http://192.0.2.2:6641>
>>     -ovs-appctl -t ovsdb-server ovsdb-server/connect-active-ovsdb-server
>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>     grep -c backup], [0], [1
>>     -])
>>     -AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
>>     -[ovn-nbctl: transaction error: {"details":"insert operation not
>>     allowed when database server is in read only mode","error":"not
>>     allowed"}
>>     -])
>>     -
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- controller event])
>>     -AT_KEYWORDS([ovn_controller_event])
>>     -ovn_start
>>     -
>>     -# Create hypervisors hv[12].
>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>     -# Add all of the vifs to a single logical switch sw0.
>>     -
>>     -net_add n1
>>     -ovn-nbctl ls-add sw0
>>     -for i in 1 2; do
>>     -    sim_add hv$i
>>     -    as hv$i
>>     -    ovs-vsctl add-br br-phys
>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>     -
>>     -    for j in 1 2; do
>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>     192.168.1.$i$j"
>>     -
>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>     -                set interface vif$i$j \
>>     -                external-ids:iface-id=sw0-p$i$j \
>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>     -                ofport-request=$i$j
>>     -    done
>>     -done
>>     -
>>     -ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
>>     -ovn-nbctl lb-add lb0 192.168.1.100:80 <http://192.168.1.100:80> ""
>>     -ovn-nbctl ls-lb-add sw0 lb0
>>     -uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer
>>     name=lb0)
>>     -
>>     -OVN_POPULATE_ARP
>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>     -ovn-sbctl lflow-list
>>     -as hv1 ovs-ofctl dump-flows br-int
>>     -
>>     -packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 &&
>>     eth.dst==00:00:00:00:00:21 &&
>>     -       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 &&
>>     ip4.dst==192.168.1.100 &&
>>     -       tcp && tcp.src==10000 && tcp.dst==80"
>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>     -
>>     -ovn-sbctl list controller_event
>>     -uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_type], [0], 
>> [dnl
>>     -empty_lb_backends
>>     -])
>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip],
>>     [0], [dnl
>>     -"192.168.1.100:80 <http://192.168.1.100:80>"
>>     -])
>>     -AT_CHECK([ovn-sbctl get controller_event $uuid
>>     event_info:protocol], [0], [dnl
>>     -tcp
>>     -])
>>     -AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid
>>     event_info:load_balancer], [0], [dnl
>>     -"$uuid_lb"
>>     -])
>>     -AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], [dnl
>>     -1
>>     -])
>>     -
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- IGMP snoop/querier])
>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>     -ovn_start
>>     -
>>     -# Logical network:
>>     -# Two independent logical switches (sw1 and sw2).
>>     -# sw1:
>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>     -#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
>>     -#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
>>     -# sw2:
>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>     -#   - 1 port bound on hv1 (sw2-p1)
>>     -#   - 1 port bound on hv2 (sw2-p2)
>>     -#   - IGMP Querier from 20.0.0.254
>>     -
>>     -reset_pcap_file() {
>>     -    local iface=$1
>>     -    local pcap_file=$2
>>     -    ovs-vsctl -- set Interface $iface 
>> options:tx_pcap=dummy-tx.pcap \
>>     -options:rxq_pcap=dummy-rx.pcap
>>     -    rm -f ${pcap_file}*.pcap
>>     -    ovs-vsctl -- set Interface $iface
>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>     -}
>>     -
>>     -ip_to_hex() {
>>     -     printf "%02x%02x%02x%02x" "$@"
>>     -}
>>     -
>>     -#
>>     -# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP 
>> REC_TYPE
>>     -#                     IGMP_CSUM OUTFILE
>>     -#
>>     -# This shell function causes an IGMPv3 report to be received on
>>     INPORT of HV.
>>     -# The packet's content has Ethernet destination 01:00:5E:00:00:22
>>     and source
>>     -# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
>>     -# GROUP is the IP multicast group to be joined/to leave (based on
>>     REC_TYPE).
>>     -# REC_TYPE == 04: join GROUP
>>     -# REC_TYPE == 03: leave GROUP
>>     -# The packet hexdump is also stored in OUTFILE.
>>     -#
>>     -send_igmp_v3_report() {
>>     -    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 group=$6
>>     -    local rec_type=$7 igmp_chksum=$8 outfile=$9
>>     -
>>     -    local eth_dst=01005e000016
>>     -    local ip_dst=$(ip_to_hex 224 0 0 22)
>>     -    local ip_ttl=01
>>     -    local ip_ra_opt=94040000
>>     -
>>     -    local igmp_type=2200
>>     -    local num_rec=00000001
>>     -    local aux_dlen=00
>>     -    local num_src=0000
>>     -
>>     -    local eth=${eth_dst}${eth_src}0800
>>     -    local
>>     
>> ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt}
>>     -    local
>>     
>> igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group} 
>>
>>     -    local packet=${eth}${ip}${igmp}
>>     -
>>     -    echo ${packet} >> ${outfile}
>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>     -}
>>     -
>>     -#
>>     -# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
>>     -#
>>     -# This shell function builds an IGMPv3 general query from ETH_SRC
>>     and IP_SRC
>>     -# and stores the hexdump of the packet in OUTFILE.
>>     -#
>>     -store_igmp_v3_query() {
>>     -    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
>>     -
>>     -    local eth_dst=01005e000001
>>     -    local ip_dst=$(ip_to_hex 224 0 0 1)
>>     -    local ip_ttl=01
>>     -    local igmp_type=11
>>     -    local max_resp=0a
>>     -    local igmp_chksum=eeeb
>>     -    local addr=00000000
>>     -
>>     -    local eth=${eth_dst}${eth_src}0800
>>     -    local
>>     ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
>>     -    local igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
>>     -    local packet=${eth}${ip}${igmp}
>>     -
>>     -    echo ${packet} >> ${outfile}
>>     -}
>>     -
>>     -#
>>     -# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST
>>     IP_LEN
>>     -#    IP_PROTO DATA OUTFILE
>>     -#
>>     -# This shell function causes an IP multicast packet to be
>>     received on INPORT
>>     -# of HV.
>>     -# The hexdump of the packet is stored in OUTFILE.
>>     -#
>>     -send_ip_multicast_pkt() {
>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 ip_dst=$6
>>     -    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} outfile=${11}
>>     -
>>     -    local ip_ttl=20
>>     -
>>     -    local eth=${eth_dst}${eth_src}0800
>>     -    local
>>     
>> ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst}
>>     -    local packet=${eth}${ip}${data}
>>     -
>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>     -    echo ${packet} >> ${outfile}
>>     -}
>>     -
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl ls-add sw2
>>     -
>>     -ovn-nbctl lsp-add sw1 sw1-p11
>>     -ovn-nbctl lsp-add sw1 sw1-p12
>>     -ovn-nbctl lsp-add sw1 sw1-p21
>>     -ovn-nbctl lsp-add sw1 sw1-p22
>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>     -ovn-nbctl lsp-add sw2 sw2-p2
>>     -
>>     -net_add n1
>>     -sim_add hv1
>>     -as hv1
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.1
>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>     -    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>     -    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -sim_add hv2
>>     -as hv2
>>     -ovs-vsctl add-br br-phys
>>     -ovn_attach n1 br-phys 192.168.0.2
>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv2-vif2 -- \
>>     -    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
>>     -    options:tx_pcap=hv2/vif2-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif2-rx.pcap \
>>     -    ofport-request=1
>>     -ovs-vsctl -- add-port br-int hv2-vif3 -- \
>>     -    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
>>     -    options:tx_pcap=hv2/vif3-tx.pcap \
>>     -    options:rxq_pcap=hv2/vif3-rx.pcap \
>>     -    ofport-request=1
>>     -
>>     -OVN_POPULATE_ARP
>>     -
>>     -# Enable IGMP snooping on sw1.
>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>     -
>>     -# No IGMP query should be generated by sw1 (mcast_querier="false").
>>     -truncate -s 0 expected
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
>>     -
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p11.
>>     -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 IGMP Join for 239.0.1.68 on sw1-p21.
>>     -send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0
>>     2) f9f9 \
>>     -    $(ip_to_hex 239 0 1 68) 04 e9b9 \
>>     -    /dev/null
>>     -
>>     -# Check that the IGMP Group is learned on both hv.
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    test "${total_entries}" = "2"
>>     -])
>>     -
>>     -# Send traffic and make sure it gets forwarded only on the two
>>     ports that
>>     -# joined.
>>     -truncate -s 0 expected
>>     -truncate -s 0 expected_empty
>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>     -    000000000001 01005e000144 \
>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>     -    e518e518000a3b3a0000 \
>>     -    expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>     -
>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
>>     -send_igmp_v3_report hv1-vif1 hv1 \
>>     -    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
>>     -    $(ip_to_hex 239 0 1 68) 03 eab9 \
>>     -    /dev/null
>>     -
>>     -# Check IGMP_Group table on both HV.
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    test "${total_entries}" = "1"
>>     -])
>>     -
>>     -# Send traffic traffic and make sure it gets forwarded only on
>>     the port that
>>     -# joined.
>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>     -as hv2 reset_pcap_file hv2-vif1 hv2/vif1
>>     -truncate -s 0 expected
>>     -truncate -s 0 expected_empty
>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>     -    000000000001 01005e000144 \
>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>     -    e518e518000a3b3a0000 \
>>     -    expected
>>     -
>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>     -
>>     -# Flush IGMP groups.
>>     -ovn-sbctl ip-multicast-flush sw1
>>     -ovn-nbctl --wait=hv -t 3 sync
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    test "${total_entries}" = "0"
>>     -])
>>     -
>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>     to minimum.
>>     -ovn-nbctl set Logical_Switch sw2 \
>>     -    other_config:mcast_snoop="true" \
>>     -    other_config:mcast_querier="true" \
>>     -    other_config:mcast_query_interval=1 \
>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>     -
>>     -# Wait for 1 query interval (1 sec) and check that two queries
>>     are generated.
>>     -truncate -s 0 expected
>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>     expected
>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>     expected
>>     -
>>     -sleep 1
>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
>>     -
>>     -OVN_CLEANUP([hv1], [hv2])
>>     -AT_CLEANUP
>>     diff --git a/tests/system-ovn.at <http://system-ovn.at>
>>     b/tests/system-ovn.at <http://system-ovn.at>
>>     deleted file mode 100644
>>     index f88ad31..0000000
>>     --- a/tests/system-ovn.at <http://system-ovn.at>
>>     +++ /dev/null
>>     @@ -1,1667 +0,0 @@
>>     -AT_BANNER([system-ovn])
>>     -
>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and
>>     DNAT])
>>     -AT_KEYWORDS([ovnnat])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>     -# to it.  R2 is a gateway router on which we add NAT rules.
>>     -#
>>     -#    foo -- R1 -- join - R2 -- alice
>>     -#           |
>>     -#    bar ----
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Static routes.
>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>     -"192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>     -
>>     -# Add a DNAT rule.
>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>     logical_ip=192.168.1.2 \
>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>     -
>>     -# Add a SNAT rule
>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>     logical_ip=192.168.2.2 \
>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>     -
>>     -# wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>     'nat(src=30.0.0.1)'])
>>     -
>>     -# 'alice1' should be able to ping 'foo1' directly.
>>     -NS_CHECK_EXEC([alice1], [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
>>     -])
>>     -
>>     -# North-South DNAT: 'alice1' should also be able to ping 'foo1'
>>     via 30.0.0.2
>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# Check conntrack entries.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.2) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>     traffic
>>     -# from 30.0.0.1
>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# Add static routes to handle east-west NAT.
>>     -ovn-nbctl lr-route-add R1 30.0.0.0/24 <http://30.0.0.0/24> 20.0.0.2
>>     -
>>     -# wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -
>>     -# Flush conntrack entries for easier output parsing of next test.
>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>     -
>>     -# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' receives 
>> it.
>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# As we have a static route that sends all packets with destination
>>     -# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to
>>     192.168.1.2
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1,
>>     the source is
>>     -# SNATted and 'foo1' receives it.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy SNAT])
>>     -AT_KEYWORDS([ovnnat])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) connected
>>     -# to it.  R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it.
>>     -# R2 is a gateway router on which we add NAT rules.
>>     -#
>>     -#    foo -- R1 -- join - R2 -- alice
>>     -
>>     -ovn-nbctl lr-add R1
>>     -ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add join
>>     -
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Static routes.
>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Add a SNAT rule
>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>     logical_ip=192.168.1.2 \
>>     -    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
>>     -
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>     'nat(src=172.16.1.1)'])
>>     -
>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>     traffic
>>     -# from 172.16.1.1
>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
>>     -AT_KEYWORDS([ovnnat])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>     LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it. Note how both alice and
>>     -# bob have the same subnet behind it.  We are trying to simulate
>>     external
>>     -# network via those 2 switches. In real world the switch ports of
>>     these
>>     -# switches will have addresses set as "unknown" to make them
>>     learning switches.
>>     -# Or those switches will be "localnet" ones.
>>     -#
>>     -#    foo -- R1 -- join - R2 -- alice
>>     -#           |          |
>>     -#    bar ----          - R3 --- bob
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add bob
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect bob to R3
>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>     <http://172.16.1.2/24>
>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>     -    type=router options:router-port=bob
>>     addresses=\"00:00:03:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Connect R3 to join
>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>     <http://20.0.0.3/24>
>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>>     -    type=router options:router-port=R3_join
>>     addresses='"00:00:04:01:02:05"'
>>     -
>>     -# Install static routes with source ip address as the policy for
>>     routing.
>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>     go via R3.
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>     <http://192.168.1.0/24> 20.0.0.2
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>     <http://192.168.2.0/24> 20.0.0.3
>>     -
>>     -# Static routes.
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>     -ovn-nbctl set logical_router R2 options:dnat_force_snat_ip=20.0.0.2
>>     -ovn-nbctl set logical_router R3 options:dnat_force_snat_ip=20.0.0.3
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>     -"192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>     -
>>     -# Logical port 'bob1' in switch 'bob'.
>>     -ADD_NAMESPACES(bob1)
>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>     -         "172.16.1.2")
>>     -ovn-nbctl lsp-add bob bob1 \
>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>     -
>>     -# Router R2
>>     -# Add a DNAT rule.
>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>     logical_ip=192.168.1.2 \
>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>     -
>>     -# Add a SNAT rule
>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>     logical_ip=192.168.1.2 \
>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>     -
>>     -# Router R3
>>     -# Add a DNAT rule.
>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>     logical_ip=192.168.1.2 \
>>     -    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
>>     -
>>     -# Add a SNAT rule
>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>     logical_ip=192.168.2.2 \
>>     -    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
>>     -
>>     -# wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>     'nat(src=30.0.0.4)'])
>>     -
>>     -# North-South DNAT: 'alice1' should be able to ping 'foo1' via
>>     30.0.0.2
>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# Check conntrack entries.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# But foo1 should receive traffic from 20.0.0.2
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# North-South DNAT: 'bob1' should be able to ping 'foo1' via 
>> 30.0.0.3
>>     -NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# Check conntrack entries.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# But foo1 should receive traffic from 20.0.0.3
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.3) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives traffic
>>     -# from 30.0.0.4
>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.4) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>     traffic
>>     -# from 30.0.0.1
>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- load-balancing])
>>     -AT_KEYWORDS([ovnlb])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# 2 logical switches "foo" (192.168.1.0/24
>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>     <http://172.16.1.0/24>)
>>     -# connected to a router R1.
>>     -# foo has foo1 to act as a client.
>>     -# bar has bar1, bar2, bar3 to act as servers.
>>     -#
>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Create logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:0f:01:02:03", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
>>     -
>>     -ADD_NAMESPACES(bar2)
>>     -ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24
>>     <http://172.16.1.3/24>", "f0:00:0f:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add bar bar2 \
>>     --- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
>>     -
>>     -ADD_NAMESPACES(bar3)
>>     -ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24
>>     <http://172.16.1.4/24>", "f0:00:0f:01:02:05", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add bar bar3 \
>>     --- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
>>     -
>>     -# Config OVN load-balancer with a VIP.
>>     -uuid=`ovn-nbctl  create load_balancer
>>     vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>     -
>>     -# Create another load-balancer with another VIP.
>>     -uuid=`ovn-nbctl create load_balancer
>>     vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
>>     -ovn-nbctl add logical_switch foo load_balancer $uuid
>>     -
>>     -# Config OVN load-balancer with another VIP (this time with ports).
>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>     <http://30.0.0.2:8000>"'='"172.16.1.2:80
>>     <http://172.16.1.2:80>,172.16.1.3:80
>>     <http://172.16.1.3:80>,172.16.1.4:80 <http://172.16.1.4:80>"'
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>     -grep 'nat(dst=172.16.1.4:80)'])
>>     -
>>     -# Start webservers in 'bar1', 'bar2' and 'bar3'.
>>     -OVS_START_L7([bar1], [http])
>>     -OVS_START_L7([bar2], [http])
>>     -OVS_START_L7([bar3], [http])
>>     -
>>     -dnl Should work with the virtual IP 30.0.0.1 address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Should work with the virtual IP 30.0.0.3 address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>     wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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"])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- load-balancing - same subnet.])
>>     -AT_KEYWORDS([ovnlb])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# 1 logical switch "foo" (192.168.1.0/24 <http://192.168.1.0/24>)
>>     connected to router R1.
>>     -# foo has foo1, foo2, foo3, foo4 as logical ports.
>>     -#
>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>     Router is needed for default
>>     -# gateway. We will test load-balancing with foo1 as a client and
>>     foo2, foo3 and
>>     -# foo4 as servers.
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl ls-add foo
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch
>>     'foo'.
>>     -ADD_NAMESPACES(foo1, foo2, foo3, foo4)
>>     -for i in `seq 1 4`; do
>>     -    j=`expr $i + 1`
>>     -    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24",
>>     "f0:00:00:01:02:0$j", \
>>     -             "192.168.1.1")
>>     -    ovn-nbctl lsp-add foo foo$i \
>>     -        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 192.168.1.$j"
>>     -done
>>     -
>>     -# Config OVN load-balancer with a VIP.
>>     -uuid=`ovn-nbctl  create load_balancer
>>     vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>     -
>>     -# Config OVN load-balancer with another VIP (this time with ports).
>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>     <http://30.0.0.2:8000>"'='"192.168.1.3:80
>>     <http://192.168.1.3:80>,192.168.1.4:80
>>     <http://192.168.1.4:80>,192.168.1.5:80 <http://192.168.1.5:80>"'
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>     -grep 'nat(dst=192.168.1.5:80)'])
>>     -
>>     -# Start webservers in 'foo2', 'foo3' and 'foo4'.
>>     -OVS_START_L7([foo2], [http])
>>     -OVS_START_L7([foo3], [http])
>>     -OVS_START_L7([foo4], [http])
>>     -
>>     -dnl Should work with the virtual IP address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>     wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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"])
>>     -AT_CLEANUP
>>     -
>>     -AT_SETUP([ovn -- load balancing in gateway router])
>>     -AT_KEYWORDS([ovnlb])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Two LRs - R1 and R2 that are connected to each other via LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>     -# to it.  R2 is a gateway router on which we add load-balancing
>>     rules.
>>     -#
>>     -#    foo -- R1 -- join - R2 -- alice
>>     -#           |
>>     -#    bar ----
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Static routes.
>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>     20.0.0.2
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>     -"192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>     -
>>     -# Config OVN load-balancer with a VIP.
>>     -uuid=`ovn-nbctl  create load_balancer
>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>     -
>>     -# Config OVN load-balancer with another VIP (this time with ports).
>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>     <http://30.0.0.2:8000>"'='"192.168.1.2:80
>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>     -
>>     -# Add SNAT rule to make sure that Load-balancing still works with
>>     a SNAT rule.
>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>     logical_ip=192.168.2.2 \
>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>     -
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>     -grep 'nat(dst=192.168.2.2:80)'])
>>     -
>>     -# Start webservers in 'foo1', 'bar1'.
>>     -OVS_START_L7([foo1], [http])
>>     -OVS_START_L7([bar1], [http])
>>     -
>>     -dnl Should work with the virtual IP address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000
>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>     wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- multiple gateway routers, load-balancing])
>>     -AT_KEYWORDS([ovnlb])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>     LS "join"
>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>     connected to it. Note how both alice and
>>     -# bob have the same subnet behind it.  We are trying to simulate
>>     external
>>     -# network via those 2 switches. In real world the switch ports of
>>     these
>>     -# switches will have addresses set as "unknown" to make them
>>     learning switches.
>>     -# Or those switches will be "localnet" ones.
>>     -#
>>     -#    foo -- R1 -- join - R2 -- alice
>>     -#           |          |
>>     -#    bar ----          - R3 --- bob
>>     -
>>     -ovn-nbctl create Logical_Router name=R1
>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -ovn-nbctl ls-add bob
>>     -ovn-nbctl ls-add join
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo
>>     addresses=\"00:00:01:01:02:03\"
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar
>>     addresses=\"00:00:01:01:02:04\"
>>     -
>>     -# Connect alice to R2
>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24>
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice
>>     addresses=\"00:00:02:01:02:03\"
>>     -
>>     -# Connect bob to R3
>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>     <http://172.16.1.2/24>
>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>     -    type=router options:router-port=bob
>>     addresses=\"00:00:03:01:02:03\"
>>     -
>>     -# Connect R1 to join
>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>     <http://20.0.0.1/24>
>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
>>     -    type=router options:router-port=R1_join
>>     addresses='"00:00:04:01:02:03"'
>>     -
>>     -# Connect R2 to join
>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>     <http://20.0.0.2/24>
>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
>>     -    type=router options:router-port=R2_join
>>     addresses='"00:00:04:01:02:04"'
>>     -
>>     -# Connect R3 to join
>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>     <http://20.0.0.3/24>
>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
>>     -    type=router options:router-port=R3_join
>>     addresses='"00:00:04:01:02:05"'
>>     -
>>     -# Install static routes with source ip address as the policy for
>>     routing.
>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>     go via R3.
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>     <http://192.168.1.0/24> 20.0.0.2
>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>     <http://192.168.2.0/24> 20.0.0.3
>>     -
>>     -# Static routes.
>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>     20.0.0.1
>>     -
>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>     -ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
>>     -ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>     -"192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>     -
>>     -# Logical port 'bob1' in switch 'bob'.
>>     -ADD_NAMESPACES(bob1)
>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>     -         "172.16.1.2")
>>     -ovn-nbctl lsp-add bob bob1 \
>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>     -
>>     -# Config OVN load-balancer with a VIP.
>>     -uuid=`ovn-nbctl  create load_balancer
>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>     -ovn-nbctl set logical_router R3 load_balancer=$uuid
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>     -grep 'nat(dst=192.168.2.2)'])
>>     -
>>     -# Start webservers in 'foo1', 'bar1'.
>>     -OVS_START_L7([foo1], [http])
>>     -OVS_START_L7([bar1], [http])
>>     -
>>     -dnl Should work with the virtual IP address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Force SNAT should have worked.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- load balancing in router with gateway router port])
>>     -AT_KEYWORDS([ovnlb])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# One LR R1 with switches foo (192.168.1.0/24
>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>     <http://192.168.2.0/24>),
>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>     it.  The port between R1 and
>>     -# alice is the router gateway port where the R1 LB rules are 
>> applied.
>>     -#
>>     -#    foo -- R1 -- bar
>>     -#           |
>>     -#    alice ----
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24> \
>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar \
>>     -    -- lsp-set-addresses rp-bar router
>>     -
>>     -# Connect alice to R1
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'foo2' in switch 'foo'.
>>     -ADD_NAMESPACES(foo2)
>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo2 \
>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>     -         "192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>     -
>>     -# Config OVN load-balancer with a VIP.
>>     -uuid=`ovn-nbctl  create load_balancer
>>     vips:172.16.1.10="192.168.1.2,192.168.2.2"`
>>     -ovn-nbctl set logical_router R1 load_balancer=$uuid
>>     -
>>     -# Config OVN load-balancer with another VIP (this time with ports).
>>     -ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000
>>     <http://172.16.1.11:8000>"'='"192.168.1.2:80
>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>     -
>>     -# Wait for ovn-controller to catch up.
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>     -grep 'nat(dst=192.168.2.2:80)'])
>>     -
>>     -# Start webservers in 'foo1', 'bar1'.
>>     -OVS_START_L7([foo1], [http])
>>     -OVS_START_L7([bar1], [http])
>>     -
>>     -dnl Should work with the virtual IP address through NAT
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1
>>     --retry-connrefused -v -o wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>     -for i in `seq 1 20`; do
>>     -    echo Request $i
>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000
>>     <http://172.16.1.11:8000> -t 5 -T 1 --retry-connrefused -v -o
>>     wget$i.log])
>>     -done
>>     -
>>     -dnl Each server should have at least one connection.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     
>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
>>     -AT_KEYWORDS([ovnnat])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# One LR R1 with switches foo (192.168.1.0/24
>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>     <http://192.168.2.0/24>),
>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>     it.  The port between R1 and
>>     -# alice is the router gateway port where the R1 NAT rules are
>>     applied.
>>     -#
>>     -#    foo -- R1 -- alice
>>     -#           |
>>     -#    bar ----
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24> \
>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar \
>>     -    -- lsp-set-addresses rp-bar router
>>     -
>>     -# Connect alice to R1
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'foo2' in switch 'foo'.
>>     -ADD_NAMESPACES(foo2)
>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo2 \
>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>     -         "192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>     -
>>     -# Add DNAT rules
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>     192.168.1.3 foo2 00:00:02:02:03:05])
>>     -
>>     -# Add a SNAT rule
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>     <http://192.168.0.0/16>])
>>     -
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>     'nat(src=172.16.1.1)'])
>>     -
>>     -# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that DNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives
>>     traffic
>>     -# from 172.16.1.4
>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>     -
>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>     traffic
>>     -# from 172.16.1.1
>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that SNAT indeed happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
>>     -AT_KEYWORDS([ovnnat])
>>     -
>>     -CHECK_CONNTRACK()
>>     -CHECK_CONNTRACK_NAT()
>>     -ovn_start
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# One LR R1 with switches foo (192.168.1.0/24
>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>     <http://192.168.2.0/24>),
>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>     it.  The port between R1 and
>>     -# alice is the router gateway port where the R1 NAT rules are
>>     applied.
>>     -#
>>     -#    foo -- R1 -- alice
>>     -#           |
>>     -#    bar ----
>>     -
>>     -ovn-nbctl lr-add R1
>>     -
>>     -ovn-nbctl ls-add foo
>>     -ovn-nbctl ls-add bar
>>     -ovn-nbctl ls-add alice
>>     -
>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>     <http://192.168.1.1/24>
>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>     <http://192.168.2.1/24>
>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>     <http://172.16.1.1/24> \
>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>     -
>>     -# Connect foo to R1
>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>     -    type=router options:router-port=foo \
>>     -    -- lsp-set-addresses rp-foo router
>>     -
>>     -# Connect bar to R1
>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>     -    type=router options:router-port=bar \
>>     -    -- lsp-set-addresses rp-bar router
>>     -
>>     -# Connect alice to R1
>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>     rp-alice \
>>     -    type=router options:router-port=alice \
>>     -    -- lsp-set-addresses rp-alice router
>>     -
>>     -# Logical port 'foo1' in switch 'foo'.
>>     -ADD_NAMESPACES(foo1)
>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo1 \
>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>     -
>>     -# Logical port 'foo2' in switch 'foo'.
>>     -ADD_NAMESPACES(foo2)
>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>     -         "192.168.1.1")
>>     -ovn-nbctl lsp-add foo foo2 \
>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>     -
>>     -# Logical port 'bar1' in switch 'bar'.
>>     -ADD_NAMESPACES(bar1)
>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>     -         "192.168.2.1")
>>     -ovn-nbctl lsp-add bar bar1 \
>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>     -
>>     -# Logical port 'alice1' in switch 'alice'.
>>     -ADD_NAMESPACES(alice1)
>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>     -         "172.16.1.1")
>>     -ovn-nbctl lsp-add alice alice1 \
>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>     -
>>     -# Add DNAT rules
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>     192.168.2.2 bar1 00:00:02:02:03:05])
>>     -
>>     -# Add a SNAT rule
>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>     <http://192.168.0.0/16>])
>>     -
>>     -ovn-nbctl --wait=hv sync
>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>     'nat(src=172.16.1.1)'])
>>     -
>>     -echo "------ hv dump ------"
>>     -ovs-ofctl show br-int
>>     -ovs-ofctl dump-flows br-int
>>     -echo "---------------------"
>>     -
>>     -# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>     FORMAT_CT(192.168.2.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>     -])
>>     -
>>     -# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>     FORMAT_CT(192.168.2.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>     -])
>>     -
>>     -# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>     FORMAT_CT(192.168.2.2) | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>     -])
>>     -
>>     -# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# Check conntrack entries.  First SNAT of 'foo1' address happens.
>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     
>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>     -
>>     -# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>     FORMAT_PING], \
>>     -[0], [dnl
>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>     -])
>>     -
>>     -# Check conntrack entries.  First SNAT of 'foo2' address happens.
>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) 
>> | \
>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>     
>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     
>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     -
>>     -AT_SETUP([ovn -- 2 LSs IGMP])
>>     -AT_KEYWORDS([ovnigmp])
>>     -
>>     -ovn_start
>>     -
>>     -OVS_TRAFFIC_VSWITCHD_START()
>>     -ADD_BR([br-int])
>>     -
>>     -# Set external-ids in br-int needed for ovn-controller
>>     -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.0.0.1 \
>>     -        -- set bridge br-int fail-mode=secure
>>     other-config:disable-in-band=true
>>     -
>>     -# Start ovn-controller
>>     -start_daemon ovn-controller
>>     -
>>     -# Logical network:
>>     -# Two independent logical switches (sw1 and sw2).
>>     -# sw1:
>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>     -#   - 2 ports (sw1-p1 - sw1-p2)
>>     -# sw2:
>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>     -#   - 2 port (sw2-p1 - sw2-p2)
>>     -#   - IGMP Querier from 20.0.0.254
>>     -
>>     -ovn-nbctl ls-add sw1
>>     -ovn-nbctl ls-add sw2
>>     -
>>     -for i in `seq 1 2`
>>     -do
>>     -    ADD_NAMESPACES(sw1-p$i)
>>     -    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24",
>>     "00:00:00:00:01:0$i", \
>>     -            "10.0.0.254")
>>     -    ovn-nbctl lsp-add sw1 sw1-p$i \
>>     -        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 10.0.0.$i"
>>     -done
>>     -
>>     -for i in `seq 1 2`
>>     -do
>>     -    ADD_NAMESPACES(sw2-p$i)
>>     -    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24",
>>     "00:00:00:00:02:0$i", \
>>     -            "20.0.0.254")
>>     -    ovn-nbctl lsp-add sw2 sw2-p$i \
>>     -        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 20.0.0.$i"
>>     -done
>>     -
>>     -# Enable IGMP snooping on sw1.
>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>     -
>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p1.
>>     -NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32
>>     <http://239.0.1.68/32> autojoin], [0])
>>     -
>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p2
>>     -NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32
>>     <http://239.0.1.68/32> autojoin], [0])
>>     -
>>     -# Check that the IGMP Group is learned.
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>     ":" | wc -w`
>>     -    test "${total_entries}" = "1"
>>     -    test "${ports}" = "2"
>>     -])
>>     -
>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
>>     -NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32
>>     <http://239.0.1.68/32>], [0])
>>     -
>>     -# Check that only one port is left in the group.
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>     ":" | wc -w`
>>     -    test "${total_entries}" = "1"
>>     -    test "${ports}" = "1"
>>     -])
>>     -
>>     -# Flush IGMP groups.
>>     -ovn-sbctl ip-multicast-flush sw1
>>     -ovn-nbctl --wait=hv -t 3 sync
>>     -OVS_WAIT_UNTIL([
>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>     | wc -l`
>>     -    test "${total_entries}" = "0"
>>     -])
>>     -
>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>     to minimum.
>>     -ovn-nbctl set Logical_Switch sw2 \
>>     -    other_config:mcast_snoop="true" \
>>     -    other_config:mcast_querier="true" \
>>     -    other_config:mcast_query_interval=1 \
>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>     -
>>     -# Check that queries are generated.
>>     -NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp >
>>     sw2-p1.pcap &])
>>     -
>>     -OVS_WAIT_UNTIL([
>>     -    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
>>     -    test "${total_queries}" = "2"
>>     -])
>>     -
>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>     -
>>     -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
>>     diff --git a/tests/test-ovn.c b/tests/test-ovn.c
>>     deleted file mode 100644
>>     index 0b9e824..0000000
>>     --- a/tests/test-ovn.c
>>     +++ /dev/null
>>     @@ -1,1584 +0,0 @@
>>     -/*
>>     - * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
>>     - *
>>     - * Licensed under the Apache License, Version 2.0 (the "License");
>>     - * you may not use this file except in compliance with the License.
>>     - * You may obtain a copy of the License at:
>>     - *
>>     - * http://www.apache.org/licenses/LICENSE-2.0
>>     - *
>>     - * Unless required by applicable law or agreed to in writing,
>>     software
>>     - * distributed under the License is distributed on an "AS IS" BASIS,
>>     - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
>>     or implied.
>>     - * See the License for the specific language governing
>>     permissions and
>>     - * limitations under the License.
>>     - */
>>     -
>>     -#include <config.h>
>>     -#include <errno.h>
>>     -#include <getopt.h>
>>     -#include <sys/wait.h>
>>     -
>>     -#include "command-line.h"
>>     -#include "dp-packet.h"
>>     -#include "fatal-signal.h"
>>     -#include "flow.h"
>>     -#include "openvswitch/dynamic-string.h"
>>     -#include "openvswitch/match.h"
>>     -#include "openvswitch/ofp-actions.h"
>>     -#include "openvswitch/ofpbuf.h"
>>     -#include "openvswitch/vlog.h"
>>     -#include "ovn/actions.h"
>>     -#include "ovn/expr.h"
>>     -#include "ovn/lex.h"
>>     -#include "ovn/logical-fields.h"
>>     -#include "ovn/lib/ovn-l7.h"
>>     -#include "ovn/lib/extend-table.h"
>>     -#include "ovs-thread.h"
>>     -#include "ovstest.h"
>>     -#include "openvswitch/shash.h"
>>     -#include "simap.h"
>>     -#include "util.h"
>>     -
>>     -/* --relops: Bitmap of the relational operators to test, in
>>     exhaustive test. */
>>     -static unsigned int test_relops;
>>     -
>>     -/* --nvars: Number of numeric variables to test, in exhaustive
>>     test. */
>>     -static int test_nvars = 2;
>>     -
>>     -/* --svars: Number of string variables to test, in exhaustive
>>     test. */
>>     -static int test_svars = 2;
>>     -
>>     -/* --bits: Number of bits per variable, in exhaustive test. */
>>     -static int test_bits = 3;
>>     -
>>     -/* --operation: The operation to test, in exhaustive test. */
>>     -static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW }
>>     operation
>>     -    = OP_FLOW;
>>     -
>>     -/* --parallel: Number of parallel processes to use in test. */
>>     -static int test_parallel = 1;
>>     -
>>     -/* -m, --more: Message verbosity */
>>     -static int verbosity;
>>     -
>>     -static void
>>     -compare_token(const struct lex_token *a, const struct lex_token *b)
>>     -{
>>     -    if (a->type != b->type) {
>>     -        fprintf(stderr, "type differs: %d -> %d\n", a->type,
>>     b->type);
>>     -        return;
>>     -    }
>>     -
>>     -    if (!((a->s && b->s && !strcmp(a->s, b->s))
>>     -          || (!a->s && !b->s))) {
>>     -        fprintf(stderr, "string differs: %s -> %s\n",
>>     -                a->s ? a->s : "(null)",
>>     -                b->s ? b->s : "(null)");
>>     -        return;
>>     -    }
>>     -
>>     -    if (a->type == LEX_T_INTEGER || a->type ==
>>     LEX_T_MASKED_INTEGER) {
>>     -        if (memcmp(&a->value, &b->value, sizeof a->value)) {
>>     -            fprintf(stderr, "value differs\n");
>>     -            return;
>>     -        }
>>     -
>>     -        if (a->type == LEX_T_MASKED_INTEGER
>>     -            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
>>     -            fprintf(stderr, "mask differs\n");
>>     -            return;
>>     -        }
>>     -
>>     -        if (a->format != b->format
>>     -            && !(a->format == LEX_F_HEXADECIMAL
>>     -                 && b->format == LEX_F_DECIMAL
>>     -                 && a->value.integer == 0)) {
>>     -            fprintf(stderr, "format differs: %d -> %d\n",
>>     -                    a->format, b->format);
>>     -        }
>>     -    }
>>     -}
>>     -
>>     -static void
>>     -test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    struct ds input;
>>     -    struct ds output;
>>     -
>>     -    ds_init(&input);
>>     -    ds_init(&output);
>>     -    while (!ds_get_test_line(&input, stdin)) {
>>     -        struct lexer lexer;
>>     -
>>     -        lexer_init(&lexer, ds_cstr(&input));
>>     -        ds_clear(&output);
>>     -        while (lexer_get(&lexer) != LEX_T_END) {
>>     -            size_t len = output.length;
>>     -            lex_token_format(&lexer.token, &output);
>>     -
>>     -            /* Check that the formatted version can really be
>>     parsed back
>>     -             * losslessly. */
>>     -            if (lexer.token.type != LEX_T_ERROR) {
>>     -                const char *s = ds_cstr(&output) + len;
>>     -                struct lexer l2;
>>     -
>>     -                lexer_init(&l2, s);
>>     -                lexer_get(&l2);
>>     -                compare_token(&lexer.token, &l2.token);
>>     -                lexer_destroy(&l2);
>>     -            }
>>     -            ds_put_char(&output, ' ');
>>     -        }
>>     -        lexer_destroy(&lexer);
>>     -
>>     -        ds_chomp(&output, ' ');
>>     -        puts(ds_cstr(&output));
>>     -    }
>>     -    ds_destroy(&input);
>>     -    ds_destroy(&output);
>>     -}
>>     -
>>     -static void
>>     -create_symtab(struct shash *symtab)
>>     -{
>>     -    ovn_init_symtab(symtab);
>>     -
>>     -    /* For negative testing. */
>>     -    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0,
>>     "xyzzy", false);
>>     -    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
>>     -                          "self_recurse != 0", false);
>>     -    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
>>     -                          "mutual_recurse_2 != 0", false);
>>     -    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
>>     -                          "mutual_recurse_1 != 0", false);
>>     -    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
>>     -}
>>     -
>>     -static void
>>     -create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
>>     -                struct hmap *nd_ra_opts,
>>     -                struct controller_event_options *event_opts)
>>     -{
>>     -    hmap_init(dhcp_opts);
>>     -    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
>>     -    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
>>     -    dhcp_opt_add(dhcp_opts, "classless_static_route", 121,
>>     "static_routes");
>>     -    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
>>     -    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
>>     -    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
>>     -    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
>>     -    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
>>     -    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
>>     -    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
>>     -    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
>>     -    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
>>     -    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
>>     -    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
>>     -
>>     -    /* DHCPv6 options. */
>>     -    hmap_init(dhcpv6_opts);
>>     -    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
>>     -    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
>>     -    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
>>     -    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
>>     -
>>     -    /* IPv6 ND RA options. */
>>     -    hmap_init(nd_ra_opts);
>>     -    nd_ra_opts_init(nd_ra_opts);
>>     -
>>     -    /* OVN controller events options. */
>>     -    controller_event_opts_init(event_opts);
>>     -}
>>     -
>>     -static void
>>     -create_addr_sets(struct shash *addr_sets)
>>     -{
>>     -    shash_init(addr_sets);
>>     -
>>     -    static const char *const addrs1[] = {
>>     -        "10.0.0.1", "10.0.0.2", "10.0.0.3",
>>     -    };
>>     -    static const char *const addrs2[] = {
>>     -        "::1", "::2", "::3",
>>     -    };
>>     -    static const char *const addrs3[] = {
>>     -        "00:00:00:00:00:01", "00:00:00:00:00:02",
>>     "00:00:00:00:00:03",
>>     -    };
>>     -    static const char *const addrs4[] = { NULL };
>>     -
>>     -    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
>>     -    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
>>     -    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
>>     -    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
>>     -}
>>     -
>>     -static void
>>     -create_port_groups(struct shash *port_groups)
>>     -{
>>     -    shash_init(port_groups);
>>     -
>>     -    static const char *const pg1[] = {
>>     -        "lsp1", "lsp2", "lsp3",
>>     -    };
>>     -    static const char *const pg2[] = { NULL };
>>     -
>>     -    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
>>     -    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
>>     -}
>>     -
>>     -static bool
>>     -lookup_port_cb(const void *ports_, const char *port_name,
>>     unsigned int *portp)
>>     -{
>>     -    const struct simap *ports = ports_;
>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>     -    if (!node) {
>>     -        return false;
>>     -    }
>>     -    *portp = node->data;
>>     -    return true;
>>     -}
>>     -
>>     -static bool
>>     -is_chassis_resident_cb(const void *ports_, const char *port_name)
>>     -{
>>     -    const struct simap *ports = ports_;
>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>     -    if (node) {
>>     -        return true;
>>     -    }
>>     -    return false;
>>     -}
>>     -
>>     -static void
>>     -test_parse_expr__(int steps)
>>     -{
>>     -    struct shash symtab;
>>     -    struct shash addr_sets;
>>     -    struct shash port_groups;
>>     -    struct simap ports;
>>     -    struct ds input;
>>     -
>>     -    create_symtab(&symtab);
>>     -    create_addr_sets(&addr_sets);
>>     -    create_port_groups(&port_groups);
>>     -
>>     -    simap_init(&ports);
>>     -    simap_put(&ports, "eth0", 5);
>>     -    simap_put(&ports, "eth1", 6);
>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>     -    simap_put(&ports, "lsp1", 0x11);
>>     -    simap_put(&ports, "lsp2", 0x12);
>>     -    simap_put(&ports, "lsp3", 0x13);
>>     -
>>     -    ds_init(&input);
>>     -    while (!ds_get_test_line(&input, stdin)) {
>>     -        struct expr *expr;
>>     -        char *error;
>>     -
>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab,
>>     &addr_sets,
>>     -                                 &port_groups, NULL, &error);
>>     -        if (!error && steps > 0) {
>>     -            expr = expr_annotate(expr, &symtab, &error);
>>     -        }
>>     -        if (!error) {
>>     -            if (steps > 1) {
>>     -                expr = expr_simplify(expr,
>>     is_chassis_resident_cb, &ports);
>>     -            }
>>     -            if (steps > 2) {
>>     -                expr = expr_normalize(expr);
>>     -                ovs_assert(expr_is_normalized(expr));
>>     -            }
>>     -        }
>>     -        if (!error) {
>>     -            if (steps > 3) {
>>     -                struct hmap matches;
>>     -
>>     -                expr_to_matches(expr, lookup_port_cb, &ports,
>>     &matches);
>>     -                expr_matches_print(&matches, stdout);
>>     -                expr_matches_destroy(&matches);
>>     -            } else {
>>     -                struct ds output = DS_EMPTY_INITIALIZER;
>>     -                expr_format(expr, &output);
>>     -                puts(ds_cstr(&output));
>>     -                ds_destroy(&output);
>>     -            }
>>     -        } else {
>>     -            puts(error);
>>     -            free(error);
>>     -        }
>>     -        expr_destroy(expr);
>>     -    }
>>     -    ds_destroy(&input);
>>     -
>>     -    simap_destroy(&ports);
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -    expr_const_sets_destroy(&addr_sets);
>>     -    shash_destroy(&addr_sets);
>>     -    expr_const_sets_destroy(&port_groups);
>>     -    shash_destroy(&port_groups);
>>     -}
>>     -
>>     -static void
>>     -test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    test_parse_expr__(0);
>>     -}
>>     -
>>     -static void
>>     -test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    test_parse_expr__(1);
>>     -}
>>     -
>>     -static void
>>     -test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    test_parse_expr__(2);
>>     -}
>>     -
>>     -static void
>>     -test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    test_parse_expr__(3);
>>     -}
>>     -
>>     -static void
>>     -test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    test_parse_expr__(4);
>>     -}
>>     -
>>     -/* Print the symbol table. */
>>     -
>>     -static void
>>     -test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    struct shash symtab;
>>     -    create_symtab(&symtab);
>>     -
>>     -    const struct shash_node **nodes = shash_sort(&symtab);
>>     -    for (size_t i = 0; i < shash_count(&symtab); i++) {
>>     -        const struct expr_symbol *symbol = nodes[i]->data;
>>     -        struct ds s = DS_EMPTY_INITIALIZER;
>>     -        expr_symbol_format(symbol, &s);
>>     -        puts(ds_cstr(&s));
>>     -        ds_destroy(&s);
>>     -    }
>>     -
>>     -    free(nodes);
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -}
>>     -
>>     -/* Evaluate an expression. */
>>     -
>>     -static bool
>>     -lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
>>     -               unsigned int *portp)
>>     -{
>>     -    *portp = atoi(port_name);
>>     -    return true;
>>     -}
>>     -
>>     -static void
>>     -test_evaluate_expr(struct ovs_cmdl_context *ctx)
>>     -{
>>     -    struct shash symtab;
>>     -    struct ds input;
>>     -
>>     -    ovn_init_symtab(&symtab);
>>     -
>>     -    struct flow uflow;
>>     -    char *error = expr_parse_microflow(ctx->argv[1], &symtab,
>>     NULL, NULL,
>>     -                                       lookup_atoi_cb, NULL, 
>> &uflow);
>>     -    if (error) {
>>     -        ovs_fatal(0, "%s", error);
>>     -    }
>>     -
>>     -    ds_init(&input);
>>     -    while (!ds_get_test_line(&input, stdin)) {
>>     -        struct expr *expr;
>>     -
>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL,
>>     NULL, NULL,
>>     -                                 &error);
>>     -        if (!error) {
>>     -            expr = expr_annotate(expr, &symtab, &error);
>>     -        }
>>     -        if (!error) {
>>     -            printf("%d\n", expr_evaluate(expr, &uflow,
>>     lookup_atoi_cb, NULL));
>>     -        } else {
>>     -            puts(error);
>>     -            free(error);
>>     -        }
>>     -        expr_destroy(expr);
>>     -    }
>>     -    ds_destroy(&input);
>>     -
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -}
>>     -
>>     -/* Compositions.
>>     - *
>>     - * The "compositions" of a positive integer N are all of the ways
>>     that one can
>>     - * add up positive integers to sum to N.  For example, the
>>     compositions of 3
>>     - * are 3, 2+1, 1+2, and 1+1+1.
>>     - *
>>     - * We use compositions to find all the ways to break up N terms
>>     of a Boolean
>>     - * expression into subexpressions.  Suppose we want to generate
>>     all expressions
>>     - * with 3 terms.  The compositions of 3 (ignoring 3 itself)
>>     provide the
>>     - * possibilities (x && x) || x, x || (x && x), and x || x || x.
>>     (Of course one
>>     - * can exchange && for || in each case.)  One must recursively
>>     compose the
>>     - * sub-expressions whose values are 3 or greater; that is what
>>     the "tree shape"
>>     - * concept later covers.
>>     - *
>>     - * To iterate through all compositions of, e.g., 5:
>>     - *
>>     - *     unsigned int state;
>>     - *     int s[5];
>>     - *     int n;
>>     - *
>>     - *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
>>     - *          n = next_composition(&state, s, n)) {
>>     - *          // Do something with composition 's' with 'n' elements.
>>     - *     }
>>     - *
>>     - * Algorithm from D. E. Knuth, _The Art of Computer Programming,
>>     Vol. 4A:
>>     - * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to
>>     exercise
>>     - * 12(a).
>>     - */
>>     -
>>     -/* Begins iteration through the compositions of 'n'. Initializes
>>     's' to the
>>     - * number of elements in the first composition of 'n' and returns
>>     that number
>>     - * of elements.  The first composition in fact is always 'n'
>>     itself, so the
>>     - * return value will be 1.
>>     - *
>>     - * Initializes '*state' to some internal state information.  The
>>     caller must
>>     - * maintain this state (and 's') for use by next_composition().
>>     - *
>>     - * 's' must have room for at least 'n' elements. */
>>     -static int
>>     -first_composition(int n, unsigned int *state, int s[])
>>     -{
>>     -    *state = 0;
>>     -    s[0] = n;
>>     -    return 1;
>>     -}
>>     -
>>     -/* Advances 's', with 'sn' elements, to the next composition and
>>     returns the
>>     - * number of elements in this new composition, or 0 if no
>>     compositions are
>>     - * left.  'state' is the same internal state passed to
>>     first_composition(). */
>>     -static int
>>     -next_composition(unsigned int *state, int s[], int sn)
>>     -{
>>     -    int j = sn - 1;
>>     -    if (++*state & 1) {
>>     -        if (s[j] > 1) {
>>     -            s[j]--;
>>     -            s[j + 1] = 1;
>>     -            j++;
>>     -        } else {
>>     -            j--;
>>     -            s[j]++;
>>     -        }
>>     -    } else {
>>     -        if (s[j - 1] > 1) {
>>     -            s[j - 1]--;
>>     -            s[j + 1] = s[j];
>>     -            s[j] = 1;
>>     -            j++;
>>     -        } else {
>>     -            j--;
>>     -            if (!j) {
>>     -                return 0;
>>     -            }
>>     -            s[j] = s[j + 1];
>>     -            s[j - 1]++;
>>     -        }
>>     -    }
>>     -    return j + 1;
>>     -}
>>     -
>>     -static void
>>     -test_composition(struct ovs_cmdl_context *ctx)
>>     -{
>>     -    int n = atoi(ctx->argv[1]);
>>     -    unsigned int state;
>>     -    int s[50];
>>     -
>>     -    for (int sn = first_composition(n, &state, s); sn;
>>     -         sn = next_composition(&state, s, sn)) {
>>     -        for (int i = 0; i < sn; i++) {
>>     -            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
>>     -        }
>>     -    }
>>     -}
>>     -
>>     -/* Tree shapes.
>>     - *
>>     - * This code generates all possible Boolean expressions with a
>>     specified number
>>     - * of terms N (equivalent to the number of external nodes in a 
>> tree).
>>     - *
>>     - * See test_tree_shape() for a simple example. */
>>     -
>>     -/* An array of these structures describes the shape of a tree.
>>     - *
>>     - * A single element of struct tree_shape describes a single node
>>     in the tree.
>>     - * The node has 'sn' direct children.  From left to right, for i
>>     in 0...sn-1,
>>     - * s[i] is 1 if the child is a leaf node, otherwise the child is
>>     a subtree and
>>     - * s[i] is the number of leaf nodes within that subtree. In the
>>     latter case,
>>     - * the subtree is described by another struct tree_shape within
>>     the enclosing
>>     - * array.  The tree_shapes are ordered in the array in in-order.
>>     - */
>>     -struct tree_shape {
>>     -    unsigned int state;
>>     -    int s[50];
>>     -    int sn;
>>     -};
>>     -
>>     -static int
>>     -init_tree_shape__(struct tree_shape ts[], int n)
>>     -{
>>     -    if (n <= 2) {
>>     -        return 0;
>>     -    }
>>     -
>>     -    int n_tses = 1;
>>     -    /* Skip the first composition intentionally. */
>>     -    ts->sn = first_composition(n, &ts->state, ts->s);
>>     -    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
>>     -    for (int i = 0; i < ts->sn; i++) {
>>     -        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
>>     -    }
>>     -    return n_tses;
>>     -}
>>     -
>>     -/* Initializes 'ts[]' as the first in the set of all of possible
>>     shapes of
>>     - * trees with 'n' leaves.  Returns the number of "struct
>>     tree_shape"s in the
>>     - * first tree shape. */
>>     -static int
>>     -init_tree_shape(struct tree_shape ts[], int n)
>>     -{
>>     -    switch (n) {
>>     -    case 1:
>>     -        ts->sn = 1;
>>     -        ts->s[0] = 1;
>>     -        return 1;
>>     -    case 2:
>>     -        ts->sn = 2;
>>     -        ts->s[0] = 1;
>>     -        ts->s[1] = 1;
>>     -        return 1;
>>     -    default:
>>     -        return init_tree_shape__(ts, n);
>>     -    }
>>     -}
>>     -
>>     -/* Advances 'ts', which currently has 'n_tses' elements, to the
>>     next possible
>>     - * tree shape with the number of leaves passed to
>>     init_tree_shape().  Returns
>>     - * the number of "struct tree_shape"s in the next shape, or 0 if
>>     all tree
>>     - * shapes have been visited. */
>>     -static int
>>     -next_tree_shape(struct tree_shape ts[], int n_tses)
>>     -{
>>     -    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1]
>>     == 1) {
>>     -        return 0;
>>     -    }
>>     -    while (n_tses > 0) {
>>     -        struct tree_shape *p = &ts[n_tses - 1];
>>     -        p->sn = p->sn > 1 ? next_composition(&p->state, p->s,
>>     p->sn) : 0;
>>     -        if (p->sn) {
>>     -            for (int i = 0; i < p->sn; i++) {
>>     -                n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
>>     -            }
>>     -            break;
>>     -        }
>>     -        n_tses--;
>>     -    }
>>     -    return n_tses;
>>     -}
>>     -
>>     -static void
>>     -print_tree_shape(const struct tree_shape ts[], int n_tses)
>>     -{
>>     -    for (int i = 0; i < n_tses; i++) {
>>     -        if (i) {
>>     -            printf(", ");
>>     -        }
>>     -        for (int j = 0; j < ts[i].sn; j++) {
>>     -            int k = ts[i].s[j];
>>     -            if (k > 9) {
>>     -                printf("(%d)", k);
>>     -            } else {
>>     -                printf("%d", k);
>>     -            }
>>     -        }
>>     -    }
>>     -}
>>     -
>>     -static void
>>     -test_tree_shape(struct ovs_cmdl_context *ctx)
>>     -{
>>     -    int n = atoi(ctx->argv[1]);
>>     -    struct tree_shape ts[50];
>>     -    int n_tses;
>>     -
>>     -    for (n_tses = init_tree_shape(ts, n); n_tses;
>>     -         n_tses = next_tree_shape(ts, n_tses)) {
>>     -        print_tree_shape(ts, n_tses);
>>     -        putchar('\n');
>>     -    }
>>     -}
>>     -
>>     -/* Iteration through all possible terminal expressions (e.g.
>>     EXPR_T_CMP and
>>     - * EXPR_T_BOOLEAN expressions).
>>     - *
>>     - * Given a tree shape, this allows the code to try all possible
>>     ways to plug in
>>     - * terms.
>>     - *
>>     - * Example use:
>>     - *
>>     - *     struct expr terminal;
>>     - *     const struct expr_symbol *vars = ...;
>>     - *     int n_vars = ...;
>>     - *     int n_bits = ...;
>>     - *
>>     - *     init_terminal(&terminal, vars[0]);
>>     - *     do {
>>     - *         // Something with 'terminal'.
>>     - *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
>>     - */
>>     -
>>     -/* Sets 'expr' to the first possible terminal expression. 'var'
>>     should be the
>>     - * first variable in the ones to be tested. */
>>     -static void
>>     -init_terminal(struct expr *expr, int phase,
>>     -              const struct expr_symbol *nvars[], int n_nvars,
>>     -              const struct expr_symbol *svars[], int n_svars)
>>     -{
>>     -    if (phase < 1 && n_nvars) {
>>     -        expr->type = EXPR_T_CMP;
>>     -        expr->cmp.symbol = nvars[0];
>>     -        expr->cmp.relop = rightmost_1bit_idx(test_relops);
>>     -        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
>>     -        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
>>     -        expr->cmp.value.integer = htonll(0);
>>     -        expr->cmp.mask.integer = htonll(0);
>>     -        return;
>>     -    }
>>     -
>>     -    if (phase < 2 && n_svars) {
>>     -        expr->type = EXPR_T_CMP;
>>     -        expr->cmp.symbol = svars[0];
>>     -        expr->cmp.relop = EXPR_R_EQ;
>>     -        expr->cmp.string = xstrdup("0");
>>     -        return;
>>     -    }
>>     -
>>     -    expr->type = EXPR_T_BOOLEAN;
>>     -    expr->boolean = false;
>>     -}
>>     -
>>     -/* Returns 'x' with the rightmost contiguous string of 1s changed
>>     to 0s,
>>     - * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's
>>     Delight_, 2nd
>>     - * ed., section 2-1. */
>>     -static unsigned int
>>     -turn_off_rightmost_1s(unsigned int x)
>>     -{
>>     -    return ((x & -x) + x) & x;
>>     -}
>>     -
>>     -static const struct expr_symbol *
>>     -next_var(const struct expr_symbol *symbol,
>>     -         const struct expr_symbol *vars[], int n_vars)
>>     -{
>>     -    for (int i = 0; i < n_vars; i++) {
>>     -        if (symbol == vars[i]) {
>>     -            return i + 1 >= n_vars ? NULL : vars[i + 1];
>>     -        }
>>     -    }
>>     -    OVS_NOT_REACHED();
>>     -}
>>     -
>>     -static enum expr_relop
>>     -next_relop(enum expr_relop relop)
>>     -{
>>     -    unsigned int remaining_relops = test_relops & ~((1u << (relop
>>     + 1)) - 1);
>>     -    return (remaining_relops
>>     -            ? rightmost_1bit_idx(remaining_relops)
>>     -            : rightmost_1bit_idx(test_relops));
>>     -}
>>     -
>>     -/* Advances 'expr' to the next possible terminal expression
>>     within the 'n_vars'
>>     - * variables of 'n_bits' bits each in 'vars[]'. */
>>     -static bool
>>     -next_terminal(struct expr *expr,
>>     -              const struct expr_symbol *nvars[], int n_nvars, int
>>     n_bits,
>>     -              const struct expr_symbol *svars[], int n_svars)
>>     -{
>>     -    if (expr->type == EXPR_T_BOOLEAN) {
>>     -        if (expr->boolean) {
>>     -            return false;
>>     -        } else {
>>     -            expr->boolean = true;
>>     -            return true;
>>     -        }
>>     -    }
>>     -
>>     -    if (!expr->cmp.symbol->width) {
>>     -        int next_value = atoi(expr->cmp.string) + 1;
>>     -        free(expr->cmp.string);
>>     -        if (next_value > 1) {
>>     -            expr->cmp.symbol = next_var(expr->cmp.symbol, svars,
>>     n_svars);
>>     -            if (!expr->cmp.symbol) {
>>     -                init_terminal(expr, 2, nvars, n_nvars, svars,
>>     n_svars);
>>     -                return true;
>>     -            }
>>     -            next_value = 0;
>>     -        }
>>     -        expr->cmp.string = xasprintf("%d", next_value);
>>     -        return true;
>>     -    }
>>     -
>>     -    unsigned int next;
>>     -
>>     -    next = (ntohll(expr->cmp.value.integer)
>>     -            + (ntohll(expr->cmp.mask.integer) << n_bits));
>>     -    for (;;) {
>>     -        next++;
>>     -        unsigned m = next >> n_bits;
>>     -        unsigned v = next & ((1u << n_bits) - 1);
>>     -        if (next >= (1u << (2 * n_bits))) {
>>     -            enum expr_relop old_relop = expr->cmp.relop;
>>     -            expr->cmp.relop = next_relop(old_relop);
>>     -            if (expr->cmp.relop <= old_relop) {
>>     -                expr->cmp.symbol = next_var(expr->cmp.symbol,
>>     nvars, n_nvars);
>>     -                if (!expr->cmp.symbol) {
>>     -                    init_terminal(expr, 1, nvars, n_nvars, svars,
>>     n_svars);
>>     -                    return true;
>>     -                }
>>     -            }
>>     -            next = UINT_MAX;
>>     -        } else if (v & ~m) {
>>     -            /* Skip: 1-bits in value correspond to 0-bits in 
>> mask. */
>>     -        } else if ((!m || turn_off_rightmost_1s(m))
>>     -                   && (expr->cmp.relop != EXPR_R_EQ &&
>>     -                       expr->cmp.relop != EXPR_R_NE)) {
>>     -            /* Skip: can't have discontiguous or all-0 mask for >
>>     >= < <=. */
>>     -        } else {
>>     -            expr->cmp.value.integer = htonll(v);
>>     -            expr->cmp.mask.integer = htonll(m);
>>     -            return true;
>>     -        }
>>     -    }
>>     -}
>>     -
>>     -static struct expr *
>>     -make_terminal(struct expr ***terminalp)
>>     -{
>>     -    struct expr *e = expr_create_boolean(true);
>>     -    **terminalp = e;
>>     -    (*terminalp)++;
>>     -    return e;
>>     -}
>>     -
>>     -static struct expr *
>>     -build_simple_tree(enum expr_type type, int n, struct expr
>>     ***terminalp)
>>     -{
>>     -    if (n == 2) {
>>     -        struct expr *e = expr_create_andor(type);
>>     -        for (int i = 0; i < 2; i++) {
>>     -            struct expr *sub = make_terminal(terminalp);
>>     -            ovs_list_push_back(&e->andor, &sub->node);
>>     -        }
>>     -        return e;
>>     -    } else if (n == 1) {
>>     -        return make_terminal(terminalp);
>>     -    } else {
>>     -        OVS_NOT_REACHED();
>>     -    }
>>     -}
>>     -
>>     -static struct expr *
>>     -build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
>>     -                 struct expr ***terminalp)
>>     -{
>>     -    const struct tree_shape *ts = *tsp;
>>     -    (*tsp)++;
>>     -
>>     -    struct expr *e = expr_create_andor(type);
>>     -    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
>>     -    for (int i = 0; i < ts->sn; i++) {
>>     -        struct expr *sub = (ts->s[i] > 2
>>     -                            ? build_tree_shape(t, tsp, terminalp)
>>     -                            : build_simple_tree(t, ts->s[i],
>>     terminalp));
>>     -        ovs_list_push_back(&e->andor, &sub->node);
>>     -    }
>>     -    return e;
>>     -}
>>     -
>>     -struct test_rule {
>>     -    struct cls_rule cr;
>>     -};
>>     -
>>     -static void
>>     -free_rule(struct test_rule *test_rule)
>>     -{
>>     -    cls_rule_destroy(&test_rule->cr);
>>     -    free(test_rule);
>>     -}
>>     -
>>     -static bool
>>     -tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
>>     -                                  const char *port_name OVS_UNUSED)
>>     -{
>>     -    return true;
>>     -}
>>     -
>>     -static int
>>     -test_tree_shape_exhaustively(struct expr *expr, struct shash 
>> *symtab,
>>     -                             struct expr *terminals[], int
>>     n_terminals,
>>     -                             const struct expr_symbol *nvars[],
>>     int n_nvars,
>>     -                             int n_bits,
>>     -                             const struct expr_symbol *svars[],
>>     int n_svars)
>>     -{
>>     -    int n_tested = 0;
>>     -
>>     -    const unsigned int var_mask = (1u << n_bits) - 1;
>>     -    for (int i = 0; i < n_terminals; i++) {
>>     -        init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>     n_svars);
>>     -    }
>>     -
>>     -    struct ds s = DS_EMPTY_INITIALIZER;
>>     -    struct flow f;
>>     -    memset(&f, 0, sizeof f);
>>     -    for (;;) {
>>     -        for (int i = n_terminals - 1; ; i--) {
>>     -            if (!i) {
>>     -                ds_destroy(&s);
>>     -                return n_tested;
>>     -            }
>>     -            if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
>>     -                              svars, n_svars)) {
>>     -                break;
>>     -            }
>>     -            init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>     n_svars);
>>     -        }
>>     -        ovs_assert(expr_honors_invariants(expr));
>>     -
>>     -        n_tested++;
>>     -
>>     -        struct expr *modified;
>>     -        if (operation == OP_CONVERT) {
>>     -            ds_clear(&s);
>>     -            expr_format(expr, &s);
>>     -
>>     -            char *error;
>>     -            modified = expr_parse_string(ds_cstr(&s), symtab, NULL,
>>     -                                         NULL, NULL, &error);
>>     -            if (error) {
>>     -                fprintf(stderr, "%s fails to parse (%s)\n",
>>     -                        ds_cstr(&s), error);
>>     -                exit(EXIT_FAILURE);
>>     -            }
>>     -        } else if (operation >= OP_SIMPLIFY) {
>>     -            modified = expr_simplify(expr_clone(expr),
>>     -  tree_shape_is_chassis_resident_cb,
>>     -                                     NULL);
>>     -            ovs_assert(expr_honors_invariants(modified));
>>     -
>>     -            if (operation >= OP_NORMALIZE) {
>>     -                modified = expr_normalize(modified);
>>     - ovs_assert(expr_honors_invariants(modified));
>>     -                ovs_assert(expr_is_normalized(modified));
>>     -            }
>>     -        }
>>     -
>>     -        struct hmap matches;
>>     -        struct classifier cls;
>>     -        if (operation >= OP_FLOW) {
>>     -            struct expr_match *m;
>>     -            struct test_rule *test_rule;
>>     -
>>     -            expr_to_matches(modified, lookup_atoi_cb, NULL,
>>     &matches);
>>     -
>>     -            classifier_init(&cls, NULL);
>>     -            HMAP_FOR_EACH (m, hmap_node, &matches) {
>>     -                test_rule = xmalloc(sizeof *test_rule);
>>     -                cls_rule_init(&test_rule->cr, &m->match, 0);
>>     -                classifier_insert(&cls, &test_rule->cr,
>>     OVS_VERSION_MIN,
>>     -                                  m->conjunctions, m->n);
>>     -            }
>>     -        }
>>     -        for (int subst = 0; subst < 1 << (n_bits * n_nvars +
>>     n_svars);
>>     -             subst++) {
>>     -            for (int i = 0; i < n_nvars; i++) {
>>     -                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
>>     -            }
>>     -            for (int i = 0; i < n_svars; i++) {
>>     -                f.regs[n_nvars + i] = ((subst >> (n_nvars *
>>     n_bits + i))
>>     -                                       & 1);
>>     -            }
>>     -
>>     -            bool expected = expr_evaluate(expr, &f,
>>     lookup_atoi_cb, NULL);
>>     -            bool actual = expr_evaluate(modified, &f,
>>     lookup_atoi_cb, NULL);
>>     -            if (actual != expected) {
>>     -                struct ds expr_s, modified_s;
>>     -
>>     -                ds_init(&expr_s);
>>     -                expr_format(expr, &expr_s);
>>     -
>>     -                ds_init(&modified_s);
>>     -                expr_format(modified, &modified_s);
>>     -
>>     -                fprintf(stderr,
>>     -                        "%s evaluates to %d, but %s evaluates to
>>     %d, for",
>>     -                        ds_cstr(&expr_s), expected,
>>     -                        ds_cstr(&modified_s), actual);
>>     -                for (int i = 0; i < n_nvars; i++) {
>>     -                    if (i > 0) {
>>     -                        fputs(",", stderr);
>>     -                    }
>>     -                    fprintf(stderr, " n%d = 0x%x", i,
>>     -                            (subst >> (n_bits * i)) & var_mask);
>>     -                }
>>     -                for (int i = 0; i < n_svars; i++) {
>>     -                    fprintf(stderr, ", s%d = \"%d\"", i,
>>     -                            (subst >> (n_bits * n_nvars + i)) & 1);
>>     -                }
>>     -                putc('\n', stderr);
>>     -                exit(EXIT_FAILURE);
>>     -            }
>>     -
>>     -            if (operation >= OP_FLOW) {
>>     -                bool found = classifier_lookup(&cls, 
>> OVS_VERSION_MIN,
>>     -                                               &f, NULL) != NULL;
>>     -                if (expected != found) {
>>     -                    struct ds expr_s, modified_s;
>>     -
>>     -                    ds_init(&expr_s);
>>     -                    expr_format(expr, &expr_s);
>>     -
>>     -                    ds_init(&modified_s);
>>     -                    expr_format(modified, &modified_s);
>>     -
>>     -                    fprintf(stderr,
>>     -                            "%s and %s evaluate to %d, for",
>>     -                            ds_cstr(&expr_s),
>>     ds_cstr(&modified_s), expected);
>>     -                    for (int i = 0; i < n_nvars; i++) {
>>     -                        if (i > 0) {
>>     -                            fputs(",", stderr);
>>     -                        }
>>     -                        fprintf(stderr, " n%d = 0x%x", i,
>>     -                                (subst >> (n_bits * i)) & var_mask);
>>     -                    }
>>     -                    for (int i = 0; i < n_svars; i++) {
>>     -                        fprintf(stderr, ", s%d = \"%d\"", i,
>>     -                                (subst >> (n_bits * n_nvars + i))
>>     & 1);
>>     -                    }
>>     -                    fputs(".\n", stderr);
>>     -
>>     -                    fprintf(stderr, "Converted to classifier:\n");
>>     -                    expr_matches_print(&matches, stderr);
>>     -                    fprintf(stderr,
>>     -                            "However, %s flow was found in the
>>     classifier.\n",
>>     -                            found ? "a" : "no");
>>     -                    exit(EXIT_FAILURE);
>>     -                }
>>     -            }
>>     -        }
>>     -        if (operation >= OP_FLOW) {
>>     -            struct test_rule *test_rule;
>>     -
>>     -            CLS_FOR_EACH (test_rule, cr, &cls) {
>>     -                classifier_remove_assert(&cls, &test_rule->cr);
>>     -                ovsrcu_postpone(free_rule, test_rule);
>>     -            }
>>     -            classifier_destroy(&cls);
>>     -            ovsrcu_quiesce();
>>     -
>>     -            expr_matches_destroy(&matches);
>>     -        }
>>     -        expr_destroy(modified);
>>     -    }
>>     -}
>>     -
>>     -#ifndef _WIN32
>>     -static void
>>     -wait_pid(pid_t *pids, int *n)
>>     -{
>>     -    int status;
>>     -    pid_t pid;
>>     -
>>     -    pid = waitpid(-1, &status, 0);
>>     -    if (pid < 0) {
>>     -        ovs_fatal(errno, "waitpid failed");
>>     -    } else if (WIFEXITED(status)) {
>>     -        if (WEXITSTATUS(status)) {
>>     -            exit(WEXITSTATUS(status));
>>     -        }
>>     -    } else if (WIFSIGNALED(status)) {
>>     -        raise(WTERMSIG(status));
>>     -        exit(1);
>>     -    } else {
>>     -        OVS_NOT_REACHED();
>>     -    }
>>     -
>>     -    for (int i = 0; i < *n; i++) {
>>     -        if (pids[i] == pid) {
>>     -            pids[i] = pids[--*n];
>>     -            return;
>>     -        }
>>     -    }
>>     -    ovs_fatal(0, "waitpid returned unknown child");
>>     -}
>>     -#endif
>>     -
>>     -static void
>>     -test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    int n_terminals = atoi(ctx->argv[1]);
>>     -    struct tree_shape ts[50];
>>     -    int n_tses;
>>     -
>>     -    struct shash symtab;
>>     -    const struct expr_symbol *nvars[4];
>>     -    const struct expr_symbol *svars[4];
>>     -
>>     -    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
>>     -    ovs_assert(test_svars <= ARRAY_SIZE(svars));
>>     -    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
>>     -
>>     -    shash_init(&symtab);
>>     -    for (int i = 0; i < test_nvars; i++) {
>>     -        char *name = xasprintf("n%d", i);
>>     -        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0
>>     + i, NULL,
>>     -                                         false);
>>     -        free(name);
>>     -    }
>>     -    for (int i = 0; i < test_svars; i++) {
>>     -        char *name = xasprintf("s%d", i);
>>     -        svars[i] = expr_symtab_add_string(&symtab, name,
>>     -                                          MFF_REG0 + test_nvars +
>>     i, NULL);
>>     -        free(name);
>>     -    }
>>     -
>>     -#ifndef _WIN32
>>     -    pid_t *children = xmalloc(test_parallel * sizeof *children);
>>     -    int n_children = 0;
>>     -#endif
>>     -
>>     -    int n_tested = 0;
>>     -    for (int i = 0; i < 2; i++) {
>>     -        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
>>     -
>>     -        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
>>     -             n_tses = next_tree_shape(ts, n_tses)) {
>>     -            const struct tree_shape *tsp = ts;
>>     -            struct expr *terminals[50];
>>     -            struct expr **terminalp = terminals;
>>     -            struct expr *expr = build_tree_shape(base_type, &tsp,
>>     &terminalp);
>>     -            ovs_assert(terminalp == &terminals[n_terminals]);
>>     -
>>     -            if (verbosity > 0) {
>>     -                print_tree_shape(ts, n_tses);
>>     -                printf(": ");
>>     -                struct ds s = DS_EMPTY_INITIALIZER;
>>     -                expr_format(expr, &s);
>>     -                puts(ds_cstr(&s));
>>     -                ds_destroy(&s);
>>     -            }
>>     -
>>     -#ifndef _WIN32
>>     -            if (test_parallel > 1) {
>>     -                pid_t pid = xfork();
>>     -                if (!pid) {
>>     -                    test_tree_shape_exhaustively(expr, &symtab,
>>     -                                                 terminals,
>>     n_terminals,
>>     -                                                 nvars,
>>     test_nvars, test_bits,
>>     -                                                 svars, test_svars);
>>     -                    expr_destroy(expr);
>>     -                    exit(0);
>>     -                } else {
>>     -                    if (n_children >= test_parallel) {
>>     -                        wait_pid(children, &n_children);
>>     -                    }
>>     -                    children[n_children++] = pid;
>>     -                }
>>     -            } else
>>     -#endif
>>     -            {
>>     -                n_tested += test_tree_shape_exhaustively(
>>     -                    expr, &symtab, terminals, n_terminals,
>>     -                    nvars, test_nvars, test_bits,
>>     -                    svars, test_svars);
>>     -            }
>>     -            expr_destroy(expr);
>>     -        }
>>     -    }
>>     -#ifndef _WIN32
>>     -    while (n_children > 0) {
>>     -        wait_pid(children, &n_children);
>>     -    }
>>     -    free(children);
>>     -#endif
>>     -
>>     -    printf("Tested ");
>>     -    switch (operation) {
>>     -    case OP_CONVERT:
>>     -        printf("converting");
>>     -        break;
>>     -    case OP_SIMPLIFY:
>>     -        printf("simplifying");
>>     -        break;
>>     -    case OP_NORMALIZE:
>>     -        printf("normalizing");
>>     -        break;
>>     -    case OP_FLOW:
>>     -        printf("converting to flows");
>>     -        break;
>>     -    }
>>     -    if (n_tested) {
>>     -        printf(" %d expressions of %d terminals", n_tested,
>>     n_terminals);
>>     -    } else {
>>     -        printf(" all %d-terminal expressions", n_terminals);
>>     -    }
>>     -    if (test_nvars || test_svars) {
>>     -        printf(" with");
>>     -        if (test_nvars) {
>>     -            printf(" %d numeric vars (each %d bits) in terms of
>>     operators",
>>     -                   test_nvars, test_bits);
>>     -            for (unsigned int relops = test_relops; relops;
>>     -                 relops = zero_rightmost_1bit(relops)) {
>>     -                enum expr_relop r = rightmost_1bit_idx(relops);
>>     -                printf(" %s", expr_relop_to_string(r));
>>     -            }
>>     -        }
>>     -        if (test_nvars && test_svars) {
>>     -            printf (" and");
>>     -        }
>>     -        if (test_svars) {
>>     -            printf(" %d string vars", test_svars);
>>     -        }
>>     -    } else {
>>     -        printf(" in terms of Boolean constants only");
>>     -    }
>>     -    printf(".\n");
>>     -
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -}
>>     -
>>     -static void
>>     -test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    struct shash symtab;
>>     -    struct ds input;
>>     -
>>     -    create_symtab(&symtab);
>>     -
>>     -    ds_init(&input);
>>     -    while (!ds_get_test_line(&input, stdin)) {
>>     -        struct flow uflow;
>>     -        char *error = expr_parse_microflow(ds_cstr(&input),
>>     &symtab, NULL,
>>     -                                           NULL, lookup_atoi_cb,
>>     NULL, &uflow);
>>     -        if (error) {
>>     -            puts(error);
>>     -            free(error);
>>     -            continue;
>>     -        }
>>     -
>>     -        uint64_t packet_stub[128 / 8];
>>     -        struct dp_packet packet;
>>     -        dp_packet_use_stub(&packet, packet_stub, sizeof 
>> packet_stub);
>>     -        flow_compose(&packet, &uflow, NULL, 64);
>>     -
>>     -        struct ds output = DS_EMPTY_INITIALIZER;
>>     -        const uint8_t *buf = dp_packet_data(&packet);
>>     -        for (int i = 0; i < dp_packet_size(&packet); i++) {
>>     -            uint8_t val = buf[i];
>>     -            ds_put_format(&output, "%02"PRIx8, val);
>>     -        }
>>     -        puts(ds_cstr(&output));
>>     -        ds_destroy(&output);
>>     -
>>     -        dp_packet_uninit(&packet);
>>     -    }
>>     -    ds_destroy(&input);
>>     -
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -}
>>     -
>>     -/* Actions. */
>>     -
>>     -static void
>>     -test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>     -{
>>     -    struct shash symtab;
>>     -    struct hmap dhcp_opts;
>>     -    struct hmap dhcpv6_opts;
>>     -    struct hmap nd_ra_opts;
>>     -    struct controller_event_options event_opts;
>>     -    struct simap ports;
>>     -    struct ds input;
>>     -    bool ok = true;
>>     -
>>     -    create_symtab(&symtab);
>>     -    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
>>     &event_opts);
>>     -
>>     -    /* Initialize group ids. */
>>     -    struct ovn_extend_table group_table;
>>     -    ovn_extend_table_init(&group_table);
>>     -
>>     -    /* Initialize meter ids for QoS. */
>>     -    struct ovn_extend_table meter_table;
>>     -    ovn_extend_table_init(&meter_table);
>>     -
>>     -    simap_init(&ports);
>>     -    simap_put(&ports, "eth0", 5);
>>     -    simap_put(&ports, "eth1", 6);
>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>     -
>>     -    ds_init(&input);
>>     -    while (!ds_get_test_line(&input, stdin)) {
>>     -        struct ofpbuf ovnacts;
>>     -        struct expr *prereqs;
>>     -        char *error;
>>     -
>>     -        puts(ds_cstr(&input));
>>     -
>>     -        ofpbuf_init(&ovnacts, 0);
>>     -
>>     -        const struct ovnact_parse_params pp = {
>>     -            .symtab = &symtab,
>>     -            .dhcp_opts = &dhcp_opts,
>>     -            .dhcpv6_opts = &dhcpv6_opts,
>>     -            .nd_ra_opts = &nd_ra_opts,
>>     -            .controller_event_opts = &event_opts,
>>     -            .n_tables = 24,
>>     -            .cur_ltable = 10,
>>     -        };
>>     -        error = ovnacts_parse_string(ds_cstr(&input), &pp,
>>     &ovnacts, &prereqs);
>>     -        if (!error) {
>>     -            /* Convert the parsed representation back to a string
>>     and print it,
>>     -             * if it's different from the input. */
>>     -            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
>>     -            ovnacts_format(ovnacts.data, ovnacts.size, &ovnacts_s);
>>     -            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
>>     -                printf("    formats as %s\n", ds_cstr(&ovnacts_s));
>>     -            }
>>     -
>>     -            /* Encode the actions into OpenFlow and print. */
>>     -            const struct ovnact_encode_params ep = {
>>     -                .lookup_port = lookup_port_cb,
>>     -                .aux = &ports,
>>     -                .is_switch = true,
>>     -                .group_table = &group_table,
>>     -                .meter_table = &meter_table,
>>     -
>>     -                .pipeline = OVNACT_P_INGRESS,
>>     -                .ingress_ptable = 8,
>>     -                .egress_ptable = 40,
>>     -                .output_ptable = 64,
>>     -                .mac_bind_ptable = 65,
>>     -            };
>>     -            struct ofpbuf ofpacts;
>>     -            ofpbuf_init(&ofpacts, 0);
>>     -            ovnacts_encode(ovnacts.data, ovnacts.size, &ep,
>>     &ofpacts);
>>     -            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
>>     -            struct ofpact_format_params fp = { .s = &ofpacts_s };
>>     -            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
>>     -            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
>>     -            ds_destroy(&ofpacts_s);
>>     -            ofpbuf_uninit(&ofpacts);
>>     -
>>     -            /* Print prerequisites if any. */
>>     -            if (prereqs) {
>>     -                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
>>     -                expr_format(prereqs, &prereqs_s);
>>     -                printf("    has prereqs %s\n", ds_cstr(&prereqs_s));
>>     -                ds_destroy(&prereqs_s);
>>     -            }
>>     -
>>     -            /* Now re-parse and re-format the string to verify
>>     that it's
>>     -             * round-trippable. */
>>     -            struct ofpbuf ovnacts2;
>>     -            struct expr *prereqs2;
>>     -            ofpbuf_init(&ovnacts2, 0);
>>     -            error = ovnacts_parse_string(ds_cstr(&ovnacts_s),
>>     &pp, &ovnacts2,
>>     -                                         &prereqs2);
>>     -            if (!error) {
>>     -                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
>>     -                ovnacts_format(ovnacts2.data, ovnacts2.size,
>>     &ovnacts2_s);
>>     -                if (strcmp(ds_cstr(&ovnacts_s),
>>     ds_cstr(&ovnacts2_s))) {
>>     -                    printf("    bad reformat: %s\n",
>>     ds_cstr(&ovnacts2_s));
>>     -                    ok = false;
>>     -                }
>>     -                ds_destroy(&ovnacts2_s);
>>     -            } else {
>>     -                printf("    reparse error: %s\n", error);
>>     -                free(error);
>>     -                ok = false;
>>     -            }
>>     -            expr_destroy(prereqs2);
>>     -
>>     -            ovnacts_free(ovnacts2.data, ovnacts2.size);
>>     -            ofpbuf_uninit(&ovnacts2);
>>     -            ds_destroy(&ovnacts_s);
>>     -        } else {
>>     -            printf("    %s\n", error);
>>     -            free(error);
>>     -        }
>>     -
>>     -        expr_destroy(prereqs);
>>     -        ovnacts_free(ovnacts.data, ovnacts.size);
>>     -        ofpbuf_uninit(&ovnacts);
>>     -    }
>>     -    ds_destroy(&input);
>>     -
>>     -    simap_destroy(&ports);
>>     -    expr_symtab_destroy(&symtab);
>>     -    shash_destroy(&symtab);
>>     -    dhcp_opts_destroy(&dhcp_opts);
>>     -    dhcp_opts_destroy(&dhcpv6_opts);
>>     -    nd_ra_opts_destroy(&nd_ra_opts);
>>     -    controller_event_opts_destroy(&event_opts);
>>     -    ovn_extend_table_destroy(&group_table);
>>     -    ovn_extend_table_destroy(&meter_table);
>>     -    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
>>     -}
>>     -
>>     -static unsigned int
>>     -parse_relops(const char *s)
>>     -{
>>     -    unsigned int relops = 0;
>>     -    struct lexer lexer;
>>     -
>>     -    lexer_init(&lexer, s);
>>     -    lexer_get(&lexer);
>>     -    do {
>>     -        enum expr_relop relop;
>>     -
>>     -        if (expr_relop_from_token(lexer.token.type, &relop)) {
>>     -            relops |= 1u << relop;
>>     -            lexer_get(&lexer);
>>     -        } else {
>>     -            ovs_fatal(0, "%s: relational operator expected at
>>     `%.*s'",
>>     -                      s, (int) (lexer.input - lexer.start),
>>     lexer.start);
>>     -        }
>>     -        lexer_match(&lexer, LEX_T_COMMA);
>>     -    } while (lexer.token.type != LEX_T_END);
>>     -    lexer_destroy(&lexer);
>>     -
>>     -    return relops;
>>     -}
>>     -
>>     -static void
>>     -usage(void)
>>     -{
>>     -    printf("\
>>     -%s: OVN test utility\n\
>>     -usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
>>     -\n\
>>     -lex\n\
>>     -  Lexically analyzes OVN input from stdin and print them back on
>>     stdout.\n\
>>     -\n\
>>     -parse-expr\n\
>>     -annotate-expr\n\
>>     -simplify-expr\n\
>>     -normalize-expr\n\
>>     -expr-to-flows\n\
>>     -  Parses OVN expressions from stdin and prints them back on
>>     stdout after\n\
>>     -  differing degrees of analysis.  Available fields are based on
>>     packet\n\
>>     -  headers.\n\
>>     -\n\
>>     -expr-to-packets\n\
>>     -  Parses OVN expressions from stdin and prints out matching
>>     packets in\n\
>>     -  hexadecimal on stdout.\n\
>>     -\n\
>>     -evaluate-expr MICROFLOW\n\
>>     -  Parses OVN expressions from stdin and evaluates them against
>>     the flow\n\
>>     -  specified in MICROFLOW, which must be an expression that
>>     constrains\n\
>>     -  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with
>>     source\n\
>>     -  port 80, and prints the results on stdout, either 1 for true or
>>     0 for\n\
>>     -  false.  Use quoted integers, e.g. \"123\", for string fields.\n\
>>     -\n\
>>     -  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type
>>     == 0x800\"\n\
>>     -  evaluates to true, \"udp\" evaluates to false, and \"udp ||
>>     tcp\"\n\
>>     -  evaluates to true.\n\
>>     -\n\
>>     -composition N\n\
>>     -  Prints all the compositions of N on stdout.\n\
>>     -\n\
>>     -tree-shape N\n\
>>     -  Prints all the tree shapes with N terminals on stdout.\n\
>>     -\n\
>>     -exhaustive N\n\
>>     -  Tests that all possible Boolean expressions with N terminals
>>     are properly\n\
>>     -  simplified, normalized, and converted to flows. Available
>>     options:\n\
>>     -   Overall options:\n\
>>     -    --operation=OPERATION  Operation to test, one of: convert,
>>     simplify,\n\
>>     -        normalize, flow.  Default: flow.  'normalize' includes
>>     'simplify',\n\
>>     -        'flow' includes 'simplify' and 'normalize'.\n\
>>     -    --parallel=N  Number of processes to use in parallel, default
>>     1.\n\
>>     -   Numeric vars:\n\
>>     -    --nvars=N  Number of numeric vars to test, in range 0...4,
>>     default 2.\n\
>>     -    --bits=N  Number of bits per variable, in range 1...3,
>>     default 3.\n\
>>     -    --relops=OPERATORS   Test only the specified Boolean
>>     operators.\n\
>>     -                         OPERATORS may include == != < <= > >=,
>>     space or\n\
>>     -                         comma separated.  Default is all
>>     operators.\n\
>>     -   String vars:\n\
>>     -    --svars=N  Number of string vars to test, in range 0...4,
>>     default 2.\n\
>>     -\n\
>>     -parse-actions\n\
>>     -  Parses OVN actions from stdin and prints the equivalent
>>     OpenFlow actions\n\
>>     -  on stdout.\n\
>>     -",
>>     -           program_name, program_name);
>>     -    exit(EXIT_SUCCESS);
>>     -}
>>     -
>>     -static void
>>     -test_ovn_main(int argc, char *argv[])
>>     -{
>>     -    enum {
>>     -        OPT_RELOPS = UCHAR_MAX + 1,
>>     -        OPT_NVARS,
>>     -        OPT_SVARS,
>>     -        OPT_BITS,
>>     -        OPT_OPERATION,
>>     -        OPT_PARALLEL
>>     -    };
>>     -    static const struct option long_options[] = {
>>     -        {"relops", required_argument, NULL, OPT_RELOPS},
>>     -        {"nvars", required_argument, NULL, OPT_NVARS},
>>     -        {"svars", required_argument, NULL, OPT_SVARS},
>>     -        {"bits", required_argument, NULL, OPT_BITS},
>>     -        {"operation", required_argument, NULL, OPT_OPERATION},
>>     -        {"parallel", required_argument, NULL, OPT_PARALLEL},
>>     -        {"more", no_argument, NULL, 'm'},
>>     -        {"help", no_argument, NULL, 'h'},
>>     -        {NULL, 0, NULL, 0},
>>     -    };
>>     -    char *short_options =
>>     ovs_cmdl_long_options_to_short_options(long_options);
>>     -
>>     -    set_program_name(argv[0]);
>>     -
>>     -    test_relops = parse_relops("== != < <= > >=");
>>     -    for (;;) {
>>     -        int option_index = 0;
>>     -        int c = getopt_long (argc, argv, short_options, 
>> long_options,
>>     -                             &option_index);
>>     -
>>     -        if (c == -1) {
>>     -            break;
>>     -        }
>>     -        switch (c) {
>>     -        case OPT_RELOPS:
>>     -            test_relops = parse_relops(optarg);
>>     -            break;
>>     -
>>     -        case OPT_NVARS:
>>     -            test_nvars = atoi(optarg);
>>     -            if (test_nvars < 0 || test_nvars > 4) {
>>     -                ovs_fatal(0, "number of numeric variables must be "
>>     -                          "between 0 and 4");
>>     -            }
>>     -            break;
>>     -
>>     -        case OPT_SVARS:
>>     -            test_svars = atoi(optarg);
>>     -            if (test_svars < 0 || test_svars > 4) {
>>     -                ovs_fatal(0, "number of string variables must be "
>>     -                          "between 0 and 4");
>>     -            }
>>     -            break;
>>     -
>>     -        case OPT_BITS:
>>     -            test_bits = atoi(optarg);
>>     -            if (test_bits < 1 || test_bits > 3) {
>>     -                ovs_fatal(0, "number of bits must be between 1
>>     and 3");
>>     -            }
>>     -            break;
>>     -
>>     -        case OPT_OPERATION:
>>     -            if (!strcmp(optarg, "convert")) {
>>     -                operation = OP_CONVERT;
>>     -            } else if (!strcmp(optarg, "simplify")) {
>>     -                operation = OP_SIMPLIFY;
>>     -            } else if (!strcmp(optarg, "normalize")) {
>>     -                operation = OP_NORMALIZE;
>>     -            } else if (!strcmp(optarg, "flow")) {
>>     -                operation = OP_FLOW;
>>     -            } else {
>>     -                ovs_fatal(0, "%s: unknown operation", optarg);
>>     -            }
>>     -            break;
>>     -
>>     -        case OPT_PARALLEL:
>>     -            test_parallel = atoi(optarg);
>>     -            break;
>>     -
>>     -        case 'm':
>>     -            verbosity++;
>>     -            break;
>>     -
>>     -        case 'h':
>>     -            usage();
>>     -            /* fall through */
>>     -
>>     -        case '?':
>>     -            exit(1);
>>     -
>>     -        default:
>>     -            abort();
>>     -        }
>>     -    }
>>     -    free(short_options);
>>     -
>>     -    static const struct ovs_cmdl_command commands[] = {
>>     -        /* Lexer. */
>>     -        {"lex", NULL, 0, 0, test_lex, OVS_RO},
>>     -
>>     -        /* Symbol table. */
>>     -        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
>>     -
>>     -        /* Expressions. */
>>     -        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
>>     -        {"annotate-expr", NULL, 0, 0, test_annotate_expr, OVS_RO},
>>     -        {"simplify-expr", NULL, 0, 0, test_simplify_expr, OVS_RO},
>>     -        {"normalize-expr", NULL, 0, 0, test_normalize_expr, OVS_RO},
>>     -        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, OVS_RO},
>>     -        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, OVS_RO},
>>     -        {"composition", NULL, 1, 1, test_composition, OVS_RO},
>>     -        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
>>     -        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
>>     -        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets,
>>     OVS_RO},
>>     -
>>     -        /* Actions. */
>>     -        {"parse-actions", NULL, 0, 0, test_parse_actions, OVS_RO},
>>     -
>>     -        {NULL, NULL, 0, 0, NULL, OVS_RO},
>>     -    };
>>     -    struct ovs_cmdl_context ctx;
>>     -    ctx.argc = argc - optind;
>>     -    ctx.argv = argv + optind;
>>     -    ovs_cmdl_run_command(&ctx, commands);
>>     -}
>>     -
>>     -OVSTEST_REGISTER("test-ovn", test_ovn_main);
>>     diff --git a/tests/testsuite.at <http://testsuite.at>
>>     b/tests/testsuite.at <http://testsuite.at>
>>     index 4d5e816..e759123 100644
>>     --- a/tests/testsuite.at <http://testsuite.at>
>>     +++ b/tests/testsuite.at <http://testsuite.at>
>>     @@ -19,7 +19,6 @@ m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
>>      m4_include([tests/ovs-macros.at <http://ovs-macros.at>])
>>      m4_include([tests/ovsdb-macros.at <http://ovsdb-macros.at>])
>>      m4_include([tests/ofproto-macros.at <http://ofproto-macros.at>])
>>     -m4_include([tests/ovn-macros.at <http://ovn-macros.at>])
>>
>>      m4_include([tests/completion.at <http://completion.at>])
>>      m4_include([tests/checkpatch.at <http://checkpatch.at>])
>>     @@ -74,13 +73,6 @@ m4_include([tests/rstp.at <http://rstp.at>])
>>      m4_include([tests/vlog.at <http://vlog.at>])
>>      m4_include([tests/vtep-ctl.at <http://vtep-ctl.at>])
>>      m4_include([tests/auto-attach.at <http://auto-attach.at>])
>>     -m4_include([tests/ovn.at <http://ovn.at>])
>>     -m4_include([tests/ovn-northd.at <http://ovn-northd.at>])
>>     -m4_include([tests/ovn-nbctl.at <http://ovn-nbctl.at>])
>>     -m4_include([tests/ovn-sbctl.at <http://ovn-sbctl.at>])
>>     -m4_include([tests/ovn-controller.at <http://ovn-controller.at>])
>>     -m4_include([tests/ovn-controller-vtep.at
>>     <http://ovn-controller-vtep.at>])
>>      m4_include([tests/mcast-snooping.at <http://mcast-snooping.at>])
>>      m4_include([tests/packet-type-aware.at
>>     <http://packet-type-aware.at>])
>>      m4_include([tests/nsh.at <http://nsh.at>])
>>     -m4_include([tests/ovn-performance.at <http://ovn-performance.at>])
>>     --     1.8.3.1
>>
>>     _______________________________________________
>>     dev mailing list
>>     dev@openvswitch.org <mailto:dev@openvswitch.org>
>>     https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Gregory Rose Sept. 8, 2019, 5:18 a.m. UTC | #4
On 9/6/2019 12:10 PM, Mark Michelson wrote:
> On 9/5/19 5:30 PM, Gregory Rose wrote:
>>
>> On 9/5/2019 12:00 PM, Numan Siddique wrote:
>>>
>>> [snip]
>>> Hi Greg,
>>>
>>> This seems reasonable to me. Mark has already submitted a patch to 
>>> delete
>>> the OVN folder. But we may have to keep ovn-nbctl/ovn-sbctl utilities
>>> and OVN schema files for ovsdb-server RAFT tests.
>>>
>>> Until that patch is merged, this seems fine to me.
>>
>> I should have a look at Mark's patch - this work probably needs 
>> integration
>> with that.
>
> FYI, I've just submitted a new version of that patch[1]. The version 
> keeps the ovn-nbctl and ovn-sbctl utilities for the ovsdb-clustering 
> tests. However, all other OVN tests have been removed. Like Numan was
> suggesting, this may be a problem that requires fixing in the OVN repo.
>
> [1] http://patchwork.ozlabs.org/patch/1159033/

Yep, I saw that.  There's a lot of overlap between my RFC and your patch 
- I'll review and test your patch
and then integrate with that.  Then we can work from there.

Thanks!

- Greg

>
>>
>>>
>>> Can you please provide the steps you use to run the system tests ?
>>> I will try to run in the new ovn repo and see if we see failures there.
>>> I tried sometime back and all the tests fail for me. Probably I wasn't
>>> running as expected.
>>
>> Build OVS using the '--with-linux=/lib/modules/$(uname -r)/build 
>> --enable-Werror'
>> to get the kernel datapath and then in the directory where you built 
>> OVS run this
>> command:
>>
>> 'sudo make check-kmod'
>>
>> To only run the ovn tests:
>>
>> 'sudo make check-kmod TESTSUITEFLAGS="-k ovn"'
>>
>> Thanks!
>>
>> - Greg
>>
>>>     ---
>>>      tests/automake.mk <http://automake.mk>         | 23 +-
>>>      tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at> |
>>>      467 --
>>>      tests/ovn-controller.at <http://ovn-controller.at>     |   294 -
>>>      tests/ovn-macros.at <http://ovn-macros.at> |   180 -
>>>      tests/ovn-nbctl.at <http://ovn-nbctl.at>        | 1660 -----
>>>      tests/ovn-northd.at <http://ovn-northd.at> |   900 ---
>>>      tests/ovn-performance.at <http://ovn-performance.at>    |   424 --
>>>      tests/ovn-sbctl.at <http://ovn-sbctl.at>        |  150 -
>>>      tests/ovn.at <http://ovn.at>        | 14702
>>>     -----------------------------------------
>>>      tests/system-ovn.at <http://system-ovn.at> |  1667 -----
>>>      tests/test-ovn.c             |  1584 -----
>>>      tests/testsuite.at <http://testsuite.at>        |    8 -
>>>      12 files changed, 4 insertions(+), 22055 deletions(-)
>>>      delete mode 100644 tests/ovn-controller-vtep.at
>>>     <http://ovn-controller-vtep.at>
>>>      delete mode 100644 tests/ovn-controller.at 
>>> <http://ovn-controller.at>
>>>      delete mode 100644 tests/ovn-macros.at <http://ovn-macros.at>
>>>      delete mode 100644 tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>      delete mode 100644 tests/ovn-northd.at <http://ovn-northd.at>
>>>      delete mode 100644 tests/ovn-performance.at
>>>     <http://ovn-performance.at>
>>>      delete mode 100644 tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>      delete mode 100644 tests/ovn.at <http://ovn.at>
>>>      delete mode 100644 tests/system-ovn.at <http://system-ovn.at>
>>>      delete mode 100644 tests/test-ovn.c
>>>
>>>     diff --git a/tests/automake.mk <http://automake.mk>
>>>     b/tests/automake.mk <http://automake.mk>
>>>     index d6ab517..decca46 100644
>>>     --- a/tests/automake.mk <http://automake.mk>
>>>     +++ b/tests/automake.mk <http://automake.mk>
>>>     @@ -23,8 +23,7 @@ EXTRA_DIST += \
>>>      COMMON_MACROS_AT = \
>>>             tests/ovsdb-macros.at <http://ovsdb-macros.at> \
>>>             tests/ovs-macros.at <http://ovs-macros.at> \
>>>     -       tests/ofproto-macros.at <http://ofproto-macros.at> \
>>>     -       tests/ovn-macros.at <http://ovn-macros.at>
>>>     +       tests/ofproto-macros.at <http://ofproto-macros.at>
>>>
>>>      TESTSUITE_AT = \
>>>             tests/testsuite.at <http://testsuite.at> \
>>>     @@ -104,16 +103,9 @@ TESTSUITE_AT = \
>>>             tests/vlog.at <http://vlog.at> \
>>>             tests/vtep-ctl.at <http://vtep-ctl.at> \
>>>             tests/auto-attach.at <http://auto-attach.at> \
>>>     -       tests/ovn.at <http://ovn.at> \
>>>     -       tests/ovn-northd.at <http://ovn-northd.at> \
>>>     -       tests/ovn-nbctl.at <http://ovn-nbctl.at> \
>>>     -       tests/ovn-sbctl.at <http://ovn-sbctl.at> \
>>>     -       tests/ovn-controller.at <http://ovn-controller.at> \
>>>     -       tests/ovn-controller-vtep.at 
>>> <http://ovn-controller-vtep.at> \
>>>             tests/mcast-snooping.at <http://mcast-snooping.at> \
>>>             tests/packet-type-aware.at <http://packet-type-aware.at> \
>>>     -       tests/nsh.at <http://nsh.at> \
>>>     -       tests/ovn-performance.at <http://ovn-performance.at>
>>>     +       tests/nsh.at <http://nsh.at>
>>>
>>>      EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
>>>      FUZZ_REGRESSION_TESTS = \
>>>     @@ -158,7 +150,6 @@ SYSTEM_KMOD_TESTSUITE_AT = \
>>>
>>>      SYSTEM_USERSPACE_TESTSUITE_AT = \
>>>             tests/system-userspace-testsuite.at
>>>     <http://system-userspace-testsuite.at> \
>>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>>             tests/system-userspace-macros.at
>>>     <http://system-userspace-macros.at> \
>>>             tests/system-userspace-packet-type-aware.at
>>>     <http://system-userspace-packet-type-aware.at>
>>>
>>>     @@ -169,7 +160,6 @@ SYSTEM_AFXDP_TESTSUITE_AT = \
>>>
>>>      SYSTEM_TESTSUITE_AT = \
>>>             tests/system-common-macros.at
>>>     <http://system-common-macros.at> \
>>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>>             tests/system-layer3-tunnels.at
>>>     <http://system-layer3-tunnels.at> \
>>>             tests/system-traffic.at <http://system-traffic.at> \
>>>             tests/system-interface.at <http://system-interface.at>
>>>     @@ -197,7 +187,7 @@ SYSTEM_DPDK_TESTSUITE =
>>>     $(srcdir)/tests/system-dpdk-testsuite
>>>      OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
>>>      DISTCLEANFILES += tests/atconfig tests/atlocal
>>>
>>>     -AUTOTEST_PATH =
>>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller 
>>>
>>>     +AUTOTEST_PATH =
>>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR)
>>>
>>>      check-local:
>>>             set $(SHELL) '$(TESTSUITE)' -C tests
>>>     AUTOTEST_PATH=$(AUTOTEST_PATH); \
>>>     @@ -238,10 +228,6 @@ check-lcov: all $(check_DATA) clean-lcov
>>>      # valgrind support
>>>
>>>      valgrind_wrappers = \
>>>     -       tests/valgrind/ovn-controller \
>>>     -       tests/valgrind/ovn-nbctl \
>>>     -       tests/valgrind/ovn-northd \
>>>     -       tests/valgrind/ovn-sbctl \
>>>             tests/valgrind/ovs-appctl \
>>>             tests/valgrind/ovs-ofctl \
>>>             tests/valgrind/ovs-vsctl \
>>>     @@ -446,7 +432,6 @@ tests_ovstest_SOURCES = \
>>>             tests/test-netflow.c \
>>>             tests/test-odp.c \
>>>             tests/test-ofpbuf.c \
>>>     -       tests/test-ovn.c \
>>>             tests/test-packets.c \
>>>             tests/test-random.c \
>>>             tests/test-rcu.c \
>>>     @@ -474,7 +459,7 @@ tests_ovstest_SOURCES += \
>>>             tests/test-netlink-conntrack.c
>>>      endif
>>>
>>>     -tests_ovstest_LDADD = lib/libopenvswitch.la
>>>     <http://libopenvswitch.la> ovn/lib/libovn.la <http://libovn.la>
>>>     +tests_ovstest_LDADD = lib/libopenvswitch.la
>>>     <http://libopenvswitch.la>
>>>
>>>      noinst_PROGRAMS += tests/test-stream
>>>      tests_test_stream_SOURCES = tests/test-stream.c
>>>     diff --git a/tests/ovn-controller-vtep.at
>>>     <http://ovn-controller-vtep.at> b/tests/ovn-controller-vtep.at
>>>     <http://ovn-controller-vtep.at>
>>>     deleted file mode 100644
>>>     index a3fe8cb..0000000
>>>     --- a/tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at>
>>>     +++ /dev/null
>>>     @@ -1,467 +0,0 @@
>>>     -AT_BANNER([ovn_controller_vtep])
>>>     -
>>>     -# OVN_CONTROLLER_VTEP_START
>>>     -#
>>>     -# Starts the test with a setup with vtep device.  Each test case
>>>     must first
>>>     -# call this macro.
>>>     -#
>>>     -# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two
>>>     physical ports
>>>     -# 'p0', 'p1'.
>>>     -#
>>>     -# Configures ovn-nb with a logical switch 'br-test'.
>>>     -#
>>>     -#
>>>     -m4_define([OVN_CONTROLLER_VTEP_START],
>>>     -  [
>>>     -   AT_KEYWORDS([ovn])
>>>     -   # this will cause skip when 'make check' using Windows setup.
>>>     -   AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -
>>>     -   dnl Create databases (ovn-nb, ovn-sb, vtep).
>>>     -   AT_CHECK([ovsdb-tool create vswitchd.db
>>>     $abs_top_srcdir/vswitchd/vswitch.ovsschema])
>>>     -   for daemon in ovn-nb ovn-sb vtep; do
>>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>>     -   done
>>>     -
>>>     -   dnl Start ovsdb-server.
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>>     --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db
>>>     vtep.db], [0], [], [stderr])
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>     --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log
>>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>>     [stderr])
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>     --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log
>>>     --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db],
>>>     [0], [], [stderr])
>>>     -   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid`
>>>     `cat ovsdb-sb-server.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d
>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>     -
>>>     -   dnl Start ovs-vswitchd.
>>>     -   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system
>>>     --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif],
>>>     [0], [], [stderr])
>>>     -   AT_CAPTURE_FILE([ovs-vswitchd.log])
>>>     -   on_exit "kill `cat ovs-vswitchd.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/ovs_numa|INFO|Discovered /d
>>>     -/vlog|INFO|opened log file/d
>>>     -/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
>>>     -/reconnect|INFO|/d
>>>     -/ofproto|INFO|using datapath ID/d
>>>     -/netlink_socket|INFO|netlink: could not enable listening to all
>>>     nsid/d
>>>     -/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
>>>     -   AT_CHECK([ovs-vsctl -- add-br br-vtep \
>>>     -              -- set bridge br-vtep datapath-type=dummy
>>>     other-config:datapath-id=fedcba9876543210
>>>     other-config:hwaddr=aa:55:aa:55:00:00
>>> protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] 
>>>
>>>     fail-mode=secure \
>>>     -              -- add-port br-vtep p0 -- set Interface p0
>>>     type=dummy ofport_request=1 \
>>>     -              -- add-port br-vtep p1 -- set Interface p1
>>>     type=dummy ofport_request=2])
>>>     -
>>>     -   dnl Start ovs-vtep.
>>>     -   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch
>>>     br-vtep tunnel_ips=1.2.3.4])
>>>     -   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log
>>>     --pidfile=ovs-vtep.pid --detach --no-chdir br-vtep \], [0], [],
>>>     [stderr])
>>>     -   on_exit "kill `cat ovs-vtep.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d']])
>>>     -   # waits until ovs-vtep starts up.
>>>     -   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep 
>>> Physical_Port`"])
>>>     -
>>>     -   dnl Start ovn-northd.
>>>     -   AT_CHECK([ovn-nbctl ls-add br-test])
>>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile
>>>     --log-file], [0], [], [stderr])
>>>     -   on_exit "kill `cat ovn-northd.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d']])
>>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>>     -
>>>     -   dnl Start ovn-controllger-vtep.
>>>     -   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile
>>>     --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock
>>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>>     -   AT_CAPTURE_FILE([ovn-controller-vtep.log])
>>>     -   on_exit "kill `cat ovn-controller-vtep.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d
>>>     -/reconnect|INFO|/d']])
>>>     -])
>>>     -
>>>     -# OVN_CONTROLLER_VTEP_STOP
>>>     -#
>>>     -# So many exits... Yeah, we started a lot daemons~
>>>     -#
>>>     -m4_define([OVN_CONTROLLER_VTEP_STOP],
>>>     -  [AT_CHECK([check_logs "$1"])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
>>>     -
>>>     -# Adds logical port for a vtep gateway chassis in ovn-nb database.
>>>     -#
>>>     -# $1: logical switch name in ovn-nb database
>>>     -# $2: logical port name
>>>     -# $3: physical vtep gateway name
>>>     -# $4: logical switch name on vtep gateway chassis
>>>     -m4_define([OVN_NB_ADD_VTEP_PORT], [
>>>     -AT_CHECK([ovn-nbctl lsp-add $1 $2])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3
>>>     vtep-logical-switch=$4])
>>>     -])
>>>     -
>>>     -##############################################
>>>     -
>>>     -# tests chassis related updates.
>>>     -AT_SETUP([ovn-controller-vtep - chassis])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# verifies the initial ovn-sb db configuration.
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>     -Chassis br-vtep
>>>     -    Encap vxlan
>>>     -        ip: "1.2.3.4"
>>>     -        options: {csum="false"}
>>>     -])
>>>     -
>>>     -# deletes the chassis via ovn-sbctl and check that it is 
>>> readded back
>>>     -# with the log.
>>>     -AT_CHECK([ovn-sbctl chassis-del br-vtep])
>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>     ovn-controller-vtep.log], [0], [dnl
>>>     -|WARN|Chassis for VTEP physical switch (br-vtep) disappears,
>>>     maybe deleted by ovn-sbctl, adding it back
>>>     -])
>>>     -
>>>     -# changes the tunnel_ip on physical switch, watches the update of
>>>     chassis's
>>>     -# encap.
>>>     -AT_CHECK([vtep-ctl set Physical_Switch br-vtep 
>>> tunnel_ips=1.2.3.5])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
>>>     -AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr
>>>     -d ' '], [0], [dnl
>>>     -"1.2.3.5"
>>>     -])
>>>     -
>>>     -# adds vlan_bindings to physical ports.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1
>>>     300 lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>>     lswitch0`"])
>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>     -[[lswitch0]]
>>>     -])
>>>     -
>>>     -# adds another logical switch and new vlan_bindings.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300
>>>     lswitch1])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>>     lswitch1`"])
>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -[[lswitch0,lswitch1]]
>>>     -])
>>>     -
>>>     -# unbinds one port from lswitch0, nothing should change.
>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list
>>>     physical_port p0 | grep -- '200='`"])
>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>     -[[lswitch0,lswitch1]]
>>>     -])
>>>     -
>>>     -# unbinds all ports from lswitch0.
>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep
>>>     p1 300])
>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>     br-vtep_lswitch0`"])
>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>     -[[lswitch1]]
>>>     -])
>>>     -
>>>     -# unbinds all ports from lswitch1.
>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>     br-vtep_lswitch1`"])
>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -[[]]
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch
>>>     (br-vtep) disappears/d])
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -# Tests binding updates.
>>>     -AT_SETUP([ovn-controller-vtep - binding 1])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
>>>     -# adds logical switch port in ovn-nb database, and sets the type
>>>     and options.
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>     [lswitch0])
>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>     chassis!='[[]]'
>>>     -# should see one binding, associated to chassis of 'br-vtep'.
>>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>>     cut -d ':' -f2 | tr -d ' ')
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -${chassis_uuid}
>>>     -])
>>>     -
>>>     -# adds another logical switch 'lswitch1' and vlan_bindings.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>>     lswitch1])
>>>     -# adds logical switch port in ovn-nb database for lswitch1.
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep],
>>>     [lswitch1])
>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1
>>>     chassis!='[[]]'
>>>     -# This is allowed, but not recommended, to have two vlan_bindings
>>>     (to different vtep logical switches)
>>>     -# from one vtep gateway physical port in one ovn-nb logical 
>>> swithch.
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>>     -
>>>     -${chassis_uuid}
>>>     -${chassis_uuid}
>>>     -])
>>>     -
>>>     -# adds another logical switch port in ovn-nb database for 
>>> lswitch0.
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup],
>>>     [br-vtep], [lswitch0])
>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding
>>>     br-vtep_lswitch0_dup chassis!='[[]]'
>>>     -# it is not allowed to have more than one ovn-nb logical port for
>>>     the same
>>>     -# vtep logical switch on a vtep gateway chassis, so should still
>>>     see only
>>>     -# two port_binding entries bound.
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>     | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
>>>     -
>>>     -
>>>     -[[]]
>>>     -${chassis_uuid}
>>>     -${chassis_uuid}
>>>     -])
>>>     -# confirms the warning log.
>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>     ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g'
>>>     | uniq], [0], [dnl
>>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>>     been associated with logical port (), ignore logical port ()
>>>     -])
>>>     -
>>>     -# deletes physical ports from vtep.
>>>     -AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>     br-vtep_lswitch`"])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
>>>     -# should see empty chassis column in both binding entries.
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>>     -
>>>     -
>>>     -[[]]
>>>     -[[]]
>>>     -[[]]
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>>     logical port/d])
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -# Tests corner case: Binding the vtep logical switch from two
>>>     different
>>>     -# datapath.
>>>     -AT_SETUP([ovn-controller-vtep - binding 2])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0])
>>>     -# adds logical switch port in ovn-nb database, and sets the type
>>>     and options.
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>     [lswitch0])
>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>     chassis!='[[]]'
>>>     -
>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>>     p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
>>>     -# adds a conflicting logical port (both br-vtep_lswitch0 and
>>>     br-vtep-void_lswitch0
>>>     -# are bound to the same logical switch, but they are on different
>>>     datapath).
>>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0],
>>>     [br-vtep-void], [lswitch0])
>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>     -# confirms the warning log.
>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>     ovn-controller-vtep.log | sed
>>>     's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key
>>>     [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
>>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>>     been associated with logical datapath (), ignore logical port ()
>>>     which belongs to logical datapath ()
>>>     -])
>>>     -
>>>     -# then deletes 'br-void' and 'br-vtep-void', should see
>>>     'br-vtep_lswitch0'
>>>     -# bound correctly.
>>>     -AT_CHECK([ovn-nbctl ls-del br-void])
>>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep
>>>     br-vtep-void_lswitch0`"])
>>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>>     cut -d ':' -f2 | tr -d ' ')
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -${chassis_uuid}
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>>     logical datapath/d])
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -# Tests vtep module vtep logical switch tunnel key update.
>>>     -AT_SETUP([ovn-controller-vtep - vtep-lswitch])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# creates the logical switch in vtep and adds the corresponding
>>>     logical
>>>     -# port to 'br-test'.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0])
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>     [lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>>>     br-vtep_lswitch0`"])
>>>     -
>>>     -# retrieves the expected tunnel key.
>>>     -datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding
>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
>>>     -tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding
>>>     ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>>     Logical_Switch | grep 0`"])
>>>     -# checks the vtep logical switch tunnel key configuration.
>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -${tunnel_key}
>>>     -])
>>>     -
>>>     -# creates a second physical switch in vtep database, and binds
>>>     its p0 vlan-100
>>>     -# to the same logical switch 'lswitch0'.
>>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>>     p0 -- bind-ls br-vtep-void p0 100 lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis
>>>     | grep -- br-vtep-void`"])
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0],
>>>     [br-vtep-void], [lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep --
>>>     br-vtep-void_lswitch0`"])
>>>     -
>>>     -# checks the vtep logical switch tunnel key configuration.
>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -${tunnel_key}
>>>     -])
>>>     -
>>>     -# now, deletes br-vtep-void.
>>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis
>>>     | grep -- br-vtep-void`"])
>>>     -# checks the vtep logical switch tunnel key configuration.
>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -${tunnel_key}
>>>     -])
>>>     -
>>>     -# changes the ovn-nb logical port type so that it is no longer
>>>     -# vtep port.
>>>     -AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>>     Logical_Switch | grep 1`"])
>>>     -# now should see the tunnel key reset.
>>>     -AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut
>>>     -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -0
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -# Tests vtep module 'Ucast_Macs_Remote's.
>>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 1])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# creates a simple logical network with the vtep device and a
>>>     fake hv chassis
>>>     -# 'ch0'.
>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>     -
>>>     -# creates the logical switch in vtep and adds the corresponding
>>>     logical
>>>     -# port to 'br-test'.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0])
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>     [lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>>     br-vtep_lswitch0`"])
>>>     -
>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>     -# adds fake hv chassis 'ch1'.
>>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>>     -
>>>     -# checks Ucast_Macs_Remote creation.
>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>     _uuid`"])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' '], [0], [dnl
>>>     -"f0:ab:cd:ef:01:02"
>>>     -])
>>>     -
>>>     -# checks physical locator creation.
>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep
>>>     _uuid`"])
>>>     -AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut
>>>     -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
>>>     -"1.2.3.5"
>>>     -])
>>>     -
>>>     -# checks tunnel creation by ovs-vtep.
>>>     -OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
>>>     -AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 |
>>>     cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>     -{remote_ip="1.2.3.5"}
>>>     -])
>>>     -
>>>     -# adds another mac to logical switch port.
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02
>>>     f0:ab:cd:ef:01:03])
>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>     03`"])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>     -
>>>     -"f0:ab:cd:ef:01:02"
>>>     -"f0:ab:cd:ef:01:03"
>>>     -])
>>>     -
>>>     -# removes one mac to logical switch port.
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>>     Ucast_Macs_Remote | grep 02`"])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>     -"f0:ab:cd:ef:01:03"
>>>     -])
>>>     -
>>>     -# migrates mac to logical switch port vif1 on 'br-void'.
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>>     Ucast_Macs_Remote | grep 03`"])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
>>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 2])
>>>     -OVN_CONTROLLER_VTEP_START
>>>     -
>>>     -# creates a simple logical network with the vtep device and a
>>>     fake hv chassis
>>>     -# 'ch0'.
>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>     -
>>>     -# creates another vif in the same logical switch with duplicate 
>>> mac.
>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>>     -
>>>     -# creates the logical switch in vtep and adds the corresponding
>>>     logical
>>>     -# port to 'br-test'.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>     lswitch0])
>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>     [lswitch0])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>>     br-vtep_lswitch0`"])
>>>     -
>>>     -# checks Ucast_Macs_Remote creation.  Should still only be one
>>>     entry, since duplicate
>>>     -# mac in the same logical switch is not allowed.
>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>     _uuid`"])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' '], [0], [dnl
>>>     -"f0:ab:cd:ef:01:02"
>>>     -])
>>>     -# confirms the warning log.
>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>     ovn-controller-vtep.log | sed
>>>     's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
>>>     -|WARN|MAC address () has already been known to be on logical port
>>>     () in the same logical datapath, so just ignore this logical 
>>> port ()
>>>     -])
>>>     -
>>>     -# deletes vif1.
>>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>>     -
>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>     -# adds fake hv chassis 'ch1' and vif1 with same mac address as 
>>> vif0.
>>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep 
>>> vif1`"])
>>>     -
>>>     -# creates another logical switch in vtep and adds the
>>>     corresponding logical
>>>     -# port to 'br-void'.
>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>>     lswitch1])
>>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep],
>>>     [lswitch1])
>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep
>>>     br-void_lswitch1`"])
>>>     -
>>>     -# checks Ucast_Macs_Remote creation.  Should see two entries
>>>     since it is allowed
>>>     -# to have duplicate macs in different logical switches.
>>>     -OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list
>>>     Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>     -
>>>     -"f0:ab:cd:ef:01:02"
>>>     -"f0:ab:cd:ef:01:02"
>>>     -])
>>>     -
>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been known to be on
>>>     logical port/d])
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn-controller.at <http://ovn-controller.at>
>>>     b/tests/ovn-controller.at <http://ovn-controller.at>
>>>     deleted file mode 100644
>>>     index 343c2ab..0000000
>>>     --- a/tests/ovn-controller.at <http://ovn-controller.at>
>>>     +++ /dev/null
>>>     @@ -1,294 +0,0 @@
>>>     -AT_BANNER([ovn-controller])
>>>     -
>>>     -AT_SETUP([ovn-controller - ovn-bridge-mappings])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_init_db ovn-sb
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0 \
>>>     -    -- add-br br-eth1 \
>>>     -    -- add-br br-eth2
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -# Waits until the OVS database contains exactly the specified
>>>     patch ports.
>>>     -# Each argument should be of the form BRIDGE PORT PEER.
>>>     -check_patches () {
>>>     -    # Generate code to check that the set of patch ports is
>>>     exactly as
>>>     -    # specified.
>>>     -    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name
>>>     find Interface type=patch | sort' > query
>>>     -    for patch
>>>     -    do
>>>     -        echo $patch
>>>     -    done | cut -d' ' -f 2 | sort > expout
>>>     -
>>>     -    # Generate code to verify that the configuration of each patch
>>>     -    # port is correct.
>>>     -    for patch
>>>     -    do
>>>     -        set $patch; bridge=$1 port=$2 peer=$3
>>>     -        echo >>query "ovs-vsctl iface-to-br $port -- get
>>>     Interface $port type options"
>>>     -        echo >>expout "$bridge
>>>     -patch
>>>     -{peer=$peer}"
>>>     -    done
>>>     -
>>>     -    # Run the query until we get the expected result (or until a
>>>     timeout).
>>>     -    #
>>>     -    # (We use sed to drop all "s from output because ovs-vsctl
>>>     quotes some
>>>     -    # of the port names but not others.)
>>>     -    AT_CAPTURE_FILE([query])
>>>     -    AT_CAPTURE_FILE([expout])
>>>     -    AT_CAPTURE_FILE([stdout])
>>>     -    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
>>>     -                    diff -u stdout expout >/dev/null])
>>>     -}
>>>     -
>>>     -# Make sure that the configured bridge mappings in the
>>>     Open_vSwitch db
>>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>>     -check_bridge_mappings () {
>>>     -    local_mappings=$1
>>>     -    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>>     -    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get
>>>     Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e
>>>     's/\"//g')])
>>>     -}
>>>     -
>>>     -# Initially there should be no patch ports.
>>>     -check_patches
>>>     -
>>>     -# Configure two ovn-bridge mappings, but no patch ports should be
>>>     created yet
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>> external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
>>>     -check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
>>>     -check_patches
>>>     -
>>>     -# Create a localnet port, but we should still have no patch
>>>     ports, as they
>>>     -# won't be created until there's a localnet port on a logical
>>>     switch with
>>>     -# another logical port bound to this chassis.
>>>     -ovn-sbctl \
>>>     -    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
>>>     -    -- create Port_Binding datapath=@dp101 logical_port=localnet1
>>>     tunnel_key=1 \
>>>     -        type=localnet options:network_name=physnet1
>>>     -check_patches
>>>     -
>>>     -# Create a localnet port on a logical switch with a port bound to
>>>     this chassis.
>>>     -# Now we should get some patch ports created.
>>>     -ovn-sbctl \
>>>     -    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
>>>     -    -- create Port_Binding datapath=@dp102 logical_port=localnet2
>>>     tunnel_key=1 \
>>>     -        type=localnet options:network_name=physnet1 \
>>>     -    -- create Port_Binding datapath=@dp102 logical_port=localvif2
>>>     tunnel_key=2
>>>     -ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
>>>     external_ids:iface-id=localvif2
>>>     -check_patches \
>>>     -    'br-int  patch-br-int-to-localnet2 
>>> patch-localnet2-to-br-int' \
>>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>>     -
>>>     -# Add logical patch ports to connect new logical datapath.
>>>     -#
>>>     -# OVN no longer uses OVS patch ports to implement logical patch
>>>     ports, so
>>>     -# the set of OVS patch ports doesn't change.
>>>     -AT_CHECK([ovn-sbctl \
>>>     -    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
>>>     -    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
>>>     -    -- create Port_Binding datapath=@dp1 logical_port=foo
>>>     tunnel_key=1 type=patch options:peer=bar \
>>>     -    -- create Port_Binding datapath=@dp2 logical_port=bar
>>>     tunnel_key=2 type=patch options:peer=foo \
>>>     -    -- create Port_Binding datapath=@dp1 logical_port=dp1vif
>>>     tunnel_key=3 \
>>>     -| uuidfilt], [0], [<0>
>>>     -<1>
>>>     -<2>
>>>     -<3>
>>>     -<4>
>>>     -])
>>>     -ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif
>>>     external_ids:iface-id=dp1vif
>>>     -check_patches \
>>>     -    'br-int  patch-br-int-to-localnet2 
>>> patch-localnet2-to-br-int' \
>>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>>     -
>>>     -# Delete the mapping and the ovn-bridge-mapping patch ports
>>>     should go away.
>>>     -AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids
>>>     ovn-bridge-mappings])
>>>     -check_bridge_mappings
>>>     -check_patches
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP_SBOX([hv])
>>>     -OVN_CLEANUP_VSWITCH([main])
>>>     -as ovn-sb
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# Checks that ovn-controller populates datapath-type and 
>>> iface-types
>>>     -# correctly in the Chassis external-ids column.
>>>     -AT_SETUP([ovn-controller - Chassis external_ids])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_init_db ovn-sb
>>>     -
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0 \
>>>     -    -- add-br br-eth1 \
>>>     -    -- add-br br-eth2
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>>     -
>>>     -# Make sure that the datapath_type set in the Bridge table
>>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>>     -check_datapath_type () {
>>>     -    datapath_type=$1
>>>     -    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid}
>>>     external_ids:datapath-type | sed -e 's/"//g') #"
>>>     -    test "${datapath_type}" = "${chassis_datapath_type}"
>>>     -}
>>>     -
>>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>>     -
>>>     -ovs-vsctl set Bridge br-int datapath-type=foo
>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>     -
>>>     -# Change "ovn-bridge-mappings" value. It should not change the
>>>     "datapath-type".
>>>     -ovs-vsctl set Open_vSwitch .
>>>     external_ids:ovn-bridge-mappings=foo-mapping
>>>     -check_datapath_type foo
>>>     -
>>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>>     -OVS_WAIT_UNTIL([check_datapath_type bar])
>>>     -
>>>     -ovs-vsctl set Bridge br-int datapath-type=\"\"
>>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>>     -
>>>     -# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
>>>     -ovs-vsctl set Open_vSwitch .
>>>     external_ids:ovn-bridge-datapath-type=foo
>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>     -
>>>     -# Change the br-int's datapath type to bar.
>>>     -# It should be reset to foo since ovn-bridge-datapath-type is
>>>     configured.
>>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>>     -OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int
>>>     datapath-type`])
>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>     -
>>>     -ovs-vsctl set Open_vSwitch .
>>>     external_ids:ovn-bridge-datapath-type=foobar
>>>     -OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int
>>>     datapath-type`])
>>>     -OVS_WAIT_UNTIL([check_datapath_type foobar])
>>>     -
>>>     -expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types |
>>>     tr -d '[[]] ""')
>>>     -echo "expected_iface_types = ${expected_iface_types}"
>>>     -chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>>     external_ids:iface-types | sed -e 's/\"//g')
>>>     -echo "chassis_iface_types = ${chassis_iface_types}"
>>>     -AT_CHECK([test "${expected_iface_types}" = 
>>> "${chassis_iface_types}"])
>>>     -
>>>     -# Change the value of external_ids:iface-types using ovn-sbctl.
>>>     -# ovn-controller should again set it back to proper one.
>>>     -ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
>>>     -OVS_WAIT_UNTIL([
>>>     -    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>>     external_ids:iface-types | sed -e 's/\"//g')
>>>     -    echo "chassis_iface_types = ${chassis_iface_types}"
>>>     -    test "${expected_iface_types}" = "${chassis_iface_types}"
>>>     -])
>>>     -
>>>     -# Change the value of external_ids:system-id and make sure it's
>>>     mirrored
>>>     -# in the Chassis record in the OVN_Southbound database.
>>>     -sysid=${sysid}-foo
>>>     -ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
>>>     -OVS_WAIT_UNTIL([
>>>     -    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
>>>     -    test "${sysid}" = "${chassis_id}"
>>>     -])
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP_SBOX([hv])
>>>     -OVN_CLEANUP_VSWITCH([main])
>>>     -as ovn-sb
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# Checks that ovn-controller correctly maintains the mapping from
>>>     the Encap
>>>     -# table in the Southbound database to OVS in the face of changes
>>>     on both sides
>>>     -AT_SETUP([ovn-controller - change Encap properties])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_init_db ovn-sb
>>>     -
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0 \
>>>     -    -- add-br br-eth1 \
>>>     -    -- add-br br-eth2
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -check_tunnel_property () {
>>>     -    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
>>>     -}
>>>     -
>>>     -# Start off with a remote chassis supporting STT
>>>     -ovn-sbctl chassis-add fakechassis stt 192.168.0.2
>>>     -OVS_WAIT_UNTIL([check_tunnel_property type stt])
>>>     -
>>>     -# See if we switch to Geneve as the first choice when it is 
>>> available
>>>     -# With multi-VTEP support we support tunnels with different IPs
>>>     to the
>>>     -# same chassis, and hence use the IP to annotate the tunnel
>>>     (along with
>>>     -# the chassis-id in ovn-chassis-id); if we supply a different 
>>> IP here
>>>     -# we won't be able to co-relate this to the tunnel port that was
>>>     created
>>>     -# in the previous step and, as a result, will end up creating
>>>     another tunnel,
>>>     -# ie. we can't just lookup using "ovn-fakech-0". So, need to use
>>>     the same IP
>>>     -# as above, i.e 192.168.0.2, here.
>>>     -encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap --
>>>     --id=@encap create encap type=geneve ip="192.168.0.2")
>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>     -
>>>     -# Check that changes within an encap row are propagated
>>>     -ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
>>>     -OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip
>>>     "\"192.168.0.2\""])
>>>     -
>>>     -# Change the type on the OVS side and check than OVN fixes it
>>>     -ovs-vsctl set interface ovn-fakech-0 type=vxlan
>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>     -
>>>     -# Delete the port entirely and it should be resurrected
>>>     -ovs-vsctl del-port ovn-fakech-0
>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP_SBOX([hv])
>>>     -OVN_CLEANUP_VSWITCH([main])
>>>     -as ovn-sb
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# Check ovn-controller connection status to Southbound database
>>>     -AT_SETUP([ovn-controller - check sbdb connection])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_init_db ovn-sb
>>>     -
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0 \
>>>     -    -- add-br br-eth1 \
>>>     -    -- add-br br-eth2
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -check_sbdb_connection () {
>>>     -    test "$(ovs-appctl -t ovn-controller connection-status)" = 
>>> "$1"
>>>     -}
>>>     -
>>>     -OVS_WAIT_UNTIL([check_sbdb_connection connected])
>>>     -
>>>     -ovs-vsctl set open .
>>>     external_ids:ovn-remote=tcp:192.168.0.10:6642
>>>     <http://192.168.0.10:6642>
>>>     -OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
>>>     -
>>>     -# reset the remote for clean-up
>>>     -ovs-vsctl set open .
>>>     external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP_SBOX([hv])
>>>     -OVN_CLEANUP_VSWITCH([main])
>>>     -as ovn-sb
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn-macros.at <http://ovn-macros.at>
>>>     b/tests/ovn-macros.at <http://ovn-macros.at>
>>>     deleted file mode 100644
>>>     index 7dba42c..0000000
>>>     --- a/tests/ovn-macros.at <http://ovn-macros.at>
>>>     +++ /dev/null
>>>     @@ -1,180 +0,0 @@
>>>     -# OVN_CLEANUP_VSWITCH(sim)
>>>     -#
>>>     -# Gracefully terminate vswitch daemons in the
>>>     -# specified sandbox.
>>>     -m4_define([OVN_CLEANUP_VSWITCH],[
>>>     -    as $1
>>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>     -    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -])
>>>     -
>>>     -# OVN_CLEANUP_SBOX(sbox)
>>>     -#
>>>     -# Gracefully terminate OVN daemons in the specified
>>>     -# sandbox instance. The sandbox name "vtep" is treated
>>>     -# as a special case, and is assumed to have ovn-controller-vtep
>>>     -# and ovs-vtep daemons running instead of ovn-controller.
>>>     -m4_define([OVN_CLEANUP_SBOX],[
>>>     -    as $1
>>>     -    if test "$1" = "vtep"; then
>>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>>     -        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>>     -    else
>>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -    fi
>>>     -    OVN_CLEANUP_VSWITCH([$1])
>>>     -])
>>>     -
>>>     -# OVN_CLEANUP(sim [, sim ...])
>>>     -#
>>>     -# Gracefully terminate all OVN daemons, including those in the
>>>     -# specified sandbox instances.
>>>     -m4_define([OVN_CLEANUP],[
>>>     -    m4_foreach([sbox], [$@], [
>>>     -        OVN_CLEANUP_SBOX([sbox])
>>>     -    ])
>>>     -    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 northd-backup
>>>     -    OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>     -
>>>     -    OVN_CLEANUP_VSWITCH([main])
>>>     -])
>>>     -
>>>     -m4_divert_push([PREPARE_TESTS])
>>>     -
>>>     -# ovn_init_db DATABASE
>>>     -#
>>>     -# Creates and initializes the given DATABASE (one of "ovn-sb" or
>>>     "ovn-nb"),
>>>     -# starts its ovsdb-server instance, and sets the appropriate
>>>     environment
>>>     -# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or
>>>     ovn-nbctl uses the
>>>     -# database by default.
>>>     -#
>>>     -# Usually invoked from ovn_start.
>>>     -ovn_init_db () {
>>>     -    echo "creating $1 database"
>>>     -    local d=$ovs_base/$1
>>>     -    mkdir "$d" || return 1
>>>     -    : > "$d"/.$1.db.~lock~
>>>     -    as $1 ovsdb-tool create "$d"/$1.db
>>>     "$abs_top_srcdir"/ovn/$1.ovsschema
>>>     -    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock
>>>     "$d"/$1.db
>>>     -    local var=`echo $1_db | tr a-z- A-Z_`
>>>     -    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
>>>     -}
>>>     -
>>>     -# ovn_start
>>>     -#
>>>     -# Creates and initializes ovn-sb and ovn-nb databases and starts
>>>     their
>>>     -# ovsdb-server instance, sets appropriate environment variables
>>>     so that
>>>     -# ovn-sbctl and ovn-nbctl use them by default, and starts
>>>     ovn-northd running
>>>     -# against them.
>>>     -ovn_start () {
>>>     -    ovn_init_db ovn-sb; ovn-sbctl init
>>>     -    ovn_init_db ovn-nb; ovn-nbctl init
>>>     -
>>>     -    echo "starting ovn-northd"
>>>     -    mkdir "$ovs_base"/northd
>>>     -    as northd start_daemon ovn-northd -v \
>>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -
>>>     -    echo "starting backup ovn-northd"
>>>     -    mkdir "$ovs_base"/northd-backup
>>>     -    as northd-backup start_daemon ovn-northd -v \
>>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -}
>>>     -
>>>     -# Interconnection networks.
>>>     -#
>>>     -# When multiple sandboxed Open vSwitch instances exist, one will
>>>     inevitably
>>>     -# want to connect them together.  These commands allow for that.
>>>     Conceptually,
>>>     -# an interconnection network is a switch for which these
>>>     functions make it easy
>>>     -# to plug into other switches in other sandboxed Open vSwitch
>>>     instances.
>>>     -# Interconnection networks are implemented as bridges in a switch
>>>     named "main",
>>>     -# so to use interconnection networks please avoid working with
>>>     that switch
>>>     -# directly.
>>>     -
>>>     -# net_add NETWORK
>>>     -#
>>>     -# Creates a new interconnection network named NETWORK.
>>>     -net_add () {
>>>     -    test -d "$ovs_base"/main || sim_add main || return 1
>>>     -    as main ovs-vsctl add-br "$1"
>>>     -}
>>>     -
>>>     -# net_attach NETWORK BRIDGE
>>>     -#
>>>     -# Adds a new port to BRIDGE in the default sandbox (as set with
>>>     as()) and plugs
>>>     -# it into the NETWORK interconnection network.  NETWORK must
>>>     already have been
>>>     -# created by a previous invocation of net_add.  The default
>>>     sandbox must not be
>>>     -# "main".
>>>     -net_attach () {
>>>     -    local net=$1 bridge=$2
>>>     -
>>>     -    local port=${sandbox}_$bridge
>>>     -    as main ovs-vsctl \
>>>     -        -- add-port $net $port \
>>>     -        -- set Interface $port
>>>     options:pstream="punix:$ovs_base/main/$port.sock"
>>>     options:rxq_pcap="$ovs_base/main/$port-rx.pcap"
>>>     options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
>>>     -        || return 1
>>>     -
>>>     -    ovs-vsctl \
>>>     -        -- set Interface $bridge
>>>     options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap"
>>>     options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
>>>     -        -- add-port $bridge ${bridge}_$net \
>>>     -        -- set Interface ${bridge}_$net
>>>     options:stream="unix:$ovs_base/main/$port.sock"
>>> options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap"
>>> options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
>>>     -        || return 1
>>>     -}
>>>     -
>>>     -# ovn_attach NETWORK BRIDGE IP [MASKLEN]
>>>     -#
>>>     -# First, this command attaches BRIDGE to interconnection network
>>>     NETWORK, just
>>>     -# like "net_attach NETWORK BRIDGE".  Second, it configures
>>>     (simulated) IP
>>>     -# address IP (with network mask length MASKLEN, which defaults to
>>>     24) on
>>>     -# BRIDGE.  Finally, it configures the Open vSwitch database to
>>>     work with OVN
>>>     -# and starts ovn-controller.
>>>     -ovn_attach() {
>>>     -    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
>>>     -    net_attach $net $bridge || return 1
>>>     -
>>>     -    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g`
>>>     -    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
>>>     -    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen
>>>     >/dev/null || return 1
>>>     -    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null ||
>>>     return 1
>>>     -    ovs-vsctl \
>>>     -        -- set Open_vSwitch . external-ids:system-id=$sandbox \
>>>     -        -- set Open_vSwitch .
>>>     external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>>>     -        -- set Open_vSwitch .
>>>     external-ids:ovn-encap-type=geneve,vxlan \
>>>     -        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
>>>     -        -- add-br br-int \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true \
>>>     -        || return 1
>>>     -    start_daemon ovn-controller || return 1
>>>     -}
>>>     -
>>>     -# OVN_POPULATE_ARP
>>>     -#
>>>     -# This pre-populates the ARP tables of all of the OVN instances
>>>     that have been
>>>     -# started with ovn_attach().  That means that packets sent from
>>>     one hypervisor
>>>     -# to another never get dropped or delayed by ARP resolution,
>>>     which makes
>>>     -# testing easier.
>>>     -ovn_populate_arp__() {
>>>     -    for e1 in $arp_table; do
>>>     -        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4
>>>     -        for e2 in $arp_table; do
>>>     -            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
>>>     -            if test $sb1,$br1 != $sb2,$br2; then
>>>     -                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac ||
>>>     return 1
>>>     -            fi
>>>     -        done
>>>     -    done
>>>     -}
>>>     -m4_divert_pop([PREPARE_TESTS])
>>>     -
>>>     -m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0],
>>>     [ignore])])
>>>     diff --git a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>     b/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>     deleted file mode 100644
>>>     index d99d3af..0000000
>>>     --- a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>     +++ /dev/null
>>>     @@ -1,1660 +0,0 @@
>>>     -AT_BANNER([ovn-nbctl])
>>>     -
>>>     -OVS_START_SHELL_HELPERS
>>>     -# OVN_NBCTL_TEST_START
>>>     -m4_define([OVN_NBCTL_TEST_START],
>>>     -  [AT_KEYWORDS([ovn])
>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>     -   ovn_nbctl_test_start $1])
>>>     -ovn_nbctl_test_start() {
>>>     -   dnl Create ovn-nb database.
>>>     -   AT_CHECK([ovsdb-tool create ovn-nb.db
>>>     $abs_top_srcdir/ovn/ovn-nb.ovsschema])
>>>     -
>>>     -   dnl Start ovsdb-server.
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>>     --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db],
>>>     [0], [], [stderr])
>>>     -   on_exit "kill `cat ovsdb-server.pid`"
>>>     -   AS_CASE([$1],
>>>     -     [daemon],
>>>     -       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach
>>>     --no-chdir --log-file -vsocket_util:off)
>>>     -        on_exit "kill `cat ovn-nbctl.pid`"],
>>>     -     [direct], [],
>>>     -     [*], [AT_FAIL_IF(:)])
>>>     -   AT_CHECK([ovn-nbctl init])
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d
>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>     -}
>>>     -
>>>     -# OVN_NBCTL_TEST_STOP
>>>     -m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
>>>     -ovn_nbctl_test_stop() {
>>>     -   AT_CHECK([check_logs "$1"])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -}
>>>     -OVS_END_SHELL_HELPERS
>>>     -
>>>     -# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
>>>     -m4_define([OVN_NBCTL_TEST],
>>>     -   [OVS_START_SHELL_HELPERS
>>>     -    $1() {
>>>     -      $3
>>>     -    }
>>>     -    OVS_END_SHELL_HELPERS
>>>     -
>>>     -    AT_SETUP([ovn-nbctl - $2 - direct])
>>>     -    OVN_NBCTL_TEST_START direct
>>>     -    $1
>>>     -    OVN_NBCTL_TEST_STOP
>>>     -    AT_CLEANUP
>>>     -
>>>     -    AT_SETUP([ovn-nbctl - $2 - daemon])
>>>     -    OVN_NBCTL_TEST_START daemon
>>>     -    $1
>>>     -    OVN_NBCTL_TEST_STOP
>>>     -    AT_CLEANUP])
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch 
>>> commands], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>     -<0> (ls0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>     -<0> (ls0)
>>>     -<1> (ls1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-del ls0])
>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>     -<0> (ls1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl show ls0])
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>>     -  [switch <0> (ls0)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
>>>     -  [ovn-nbctl: ls0: a switch with this name already exists
>>>     -])
>>>  ��  -AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>>     -  [switch <0> (ls0)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], 
>>> [1], [],
>>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>>     together
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
>>>     -  [ovn-nbctl: Multiple logical switches named 'ls0'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
>>>     -  [ovn-nbctl: ls2: switch name not found
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add])
>>>     -AT_CHECK([ovn-nbctl ls-add])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
>>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
>>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port
>>>     commands], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
>>>     -  [ovn-nbctl: lp0: a port with this name already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>     -<0> (lp0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>     -<0> (lp0)
>>>     -<1> (lp1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
>>>     -  [ovn-nbctl: lp1: a port with this name already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
>>>     -  [ovn-nbctl: lp1: port already exists but in switch ls0
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
>>>     -  [ovn-nbctl: lp1: port already exists but has no parent
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-del lp1])
>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>     -<0> (lp0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
>>>     -  [ovn-nbctl: lp2: port already exists with different parent lp3
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
>>>     -  [ovn-nbctl: lp2: port already exists with different 
>>> tag_request 5
>>>     -])
>>>     -AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
>>>     -  [ovn-nbctl: lp2: port already exists but has no tag_request
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
>>>     -<0> (ls0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
>>>     -  [ovn-nbctl: lp1: port name not found
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 
>>> unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>     -00:11:22:33:44:55
>>>     -unknown
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff
>>>     00:11:22:33:44:55])
>>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>>     -00:11:22:33:44:55
>>>     -aa:bb:cc:dd:ee:ff
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
>>>     -ovn_nbctl_test_acl() {
>>>     -   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp 
>>> drop])
>>>     -   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info
>>>     acl-add $1 to-lport 500 udp drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
>>>     -   dnl Add duplicated ACL
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1],
>>>     [], [stderr])
>>>     -   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>>     -   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip
>>>     drop])
>>>     -
>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>     -from-lport   600 (udp) drop log()
>>>     -from-lport   400 (tcp) drop
>>>     -from-lport   200 (ip) drop
>>>     -  to-lport   500 (udp) drop log(name=test,severity=info)
>>>     -  to-lport   300 (tcp) drop
>>>     -  to-lport   100 (ip) drop
>>>     -])
>>>     -
>>>     -   dnl Delete in one direction.
>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>     -from-lport   600 (udp) drop log()
>>>     -from-lport   400 (tcp) drop
>>>     -from-lport   200 (ip) drop
>>>     -])
>>>     -
>>>     -   dnl Delete all ACLs.
>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>     -])
>>>     -
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>>     -
>>>     -   dnl Delete a single flow.
>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>     -from-lport   600 (udp) drop
>>>     -from-lport   200 (ip) drop
>>>     -])
>>>     -}
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -ovn_nbctl_test_acl ls0
>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>     -ovn_nbctl_test_acl ls1 --type=switch
>>>     -AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
>>>     -ovn_nbctl_test_acl pg0 --type=port-group
>>>     -
>>>     -dnl Test when port group doesn't exist
>>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip
>>>     drop], [1], [], [dnl
>>>     -ovn-nbctl: pg1: port group name not found
>>>     -])
>>>     -
>>>     -dnl Test when same name exists in logical switches and portgroups
>>>     -AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [],
>>>     [stderr])
>>>     -AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip
>>>     drop], [0], [ignore])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100
>>>     burst=1000])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0
>>>     rate=300 burst=3000])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301
>>>     burst=30000])
>>>     -
>>>     -dnl Add duplicated qos
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302
>>>     burst=30002], [1], [], [stderr])
>>>     -AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4
>>>     dscp=11 rate=302 burst=30002])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>     -from-lport   600 (tcp) dscp=63
>>>     -from-lport   500 (udp) rate=100 burst=1000
>>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>>     -  to-lport   300 (tcp) dscp=48
>>>     -  to-lport   200 (ip) rate=101
>>>     -  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
>>>     -])
>>>     -
>>>     -dnl Delete in one direction.
>>>     -AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>     -from-lport   600 (tcp) dscp=63
>>>     -from-lport   500 (udp) rate=100 burst=1000
>>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>>     -])
>>>     -
>>>     -dnl Delete all qos_rules.
>>>     -AT_CHECK([ovn-nbctl qos-del ls0])
>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102
>>>     rate=301 dscp=19])
>>>     -
>>>     -dnl Delete a single flow.
>>>     -AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>     -from-lport   600 (ip) rate=1000101
>>>     -from-lport   200 (ip) rate=301 burst=1000102 dscp=19
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>>     rate=100010111111], [1], [],
>>>     -[ovn-nbctl: 100010111111: rate must be in the range 1...4294967295
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>>     burst=100010111112 rate=100010], [1], [],
>>>     -[ovn-nbctl: 100010111112: burst must be in the range 
>>> 1...4294967295
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], 
>>> [1], [],
>>>     -[ovn-nbctl: -1: dscp must be in the range 0...63
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], 
>>> [1], [],
>>>     -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=",
>>>     and "burst="
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123],
>>>     [1], [],
>>>     -[ovn-nbctl: Either "rate" and/or "dscp" must be specified
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
>>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
>>>     -AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
>>>     -AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
>>>     -AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
>>>     -
>>>     -dnl Add duplicate meter name
>>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [],
>>>     [stderr])
>>>     -AT_CHECK([grep 'already exists' stderr], [0], [ignore])
>>>     -
>>>     -dnl Add reserved meter name
>>>     -AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [],
>>>     [stderr])
>>>     -AT_CHECK([grep 'reserved' stderr], [0], [ignore])
>>>     -
>>>     -dnl Add meter with invalid rates
>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps],
>>>     [1], [],
>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>     -])
>>>     -
>>>     -dnl Add meter with invalid rates
>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], 
>>> [1], [],
>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>     -])
>>>     -
>>>     -dnl Add meter with invalid burst
>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps],
>>>     [1], [],
>>>     -[ovn-nbctl: unit must be "kbps" or "pktps"
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>     -meter1: bands:
>>>     -  drop: 10 kbps
>>>     -meter2: bands:
>>>     -  drop: 3 kbps, 2 kb burst
>>>     -meter3: bands:
>>>     -  drop: 100 kbps, 200 kb burst
>>>     -meter4: bands:
>>>     -  drop: 10 pktps, 30 packet burst
>>>     -])
>>>     -
>>>     -dnl Delete a single meter.
>>>     -AT_CHECK([ovn-nbctl meter-del meter2])
>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>     -meter1: bands:
>>>     -  drop: 10 kbps
>>>     -meter3: bands:
>>>     -  drop: 100 kbps, 200 kb burst
>>>     -meter4: bands:
>>>     -  drop: 10 pktps, 30 packet burst
>>>     -])
>>>     -
>>>     -dnl Delete all meters.
>>>     -AT_CHECK([ovn-nbctl meter-del])
>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2],
>>>     [1], [],
>>>     -[ovn-nbctl: snatt: type must be one of "dnat", "snat" and
>>>     "dnat_and_snat".
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2],
>>>     [1], [],
>>>     -[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], 
>>> [1], [],
>>>     -[ovn-nbctl: 30.0.0: should be an IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24
>>>     <http://30.0.0.2/24> 192.168.1.2], [1], [],
>>>     -[ovn-nbctl: 30.0.0.2/24 <http://30.0.0.2/24>: should be an IPv4
>>>     address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80
>>>     <http://30.0.0.2:80> 192.168.1.2], [1], [],
>>>     -[ovn-nbctl: 30.0.0.2:80 <http://30.0.0.2:80>: should be an IPv4
>>>     address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a],
>>>     [1], [],
>>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], 
>>> [1], [],
>>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80
>>>     <http://192.168.1.2:80>], [1], [],
>>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>>     IPv4 address or network.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a
>>>     <http://192.168.1.2/a>], [1], [],
>>>     -[ovn-nbctl: 192.168.1.2/a <http://192.168.1.2/a>: should be an
>>>     IPv4 address or network.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a],
>>>     [1], [],
>>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], 
>>> [1], [],
>>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80
>>>     <http://192.168.1.2:80>], [1], [],
>>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>>     IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24
>>>     <http://192.168.1.2/24>], [1], [],
>>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>>     IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>     192.168.1.2/24 <http://192.168.1.2/24>], [1], [],
>>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>>     IPv4 address.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>     192.168.1.2 lp0], [1], [],
>>>     -[ovn-nbctl: lr-nat-add with logical_port must also specify
>>>     external_mac.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
>>>     00:00:00:01:02:03], [1], [],
>>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>>     type is "dnat_and_snat".
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
>>>     00:00:00:01:02:03], [1], [],
>>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>>     type is "dnat_and_snat".
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>     192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
>>>     -[ovn-nbctl: lp0: port name not found
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>     192.168.1.2 lp0 00:00:00:01:02], [1], [],
>>>     -[ovn-nbctl: invalid mac address 00:00:00:01:02.
>>>     -])
>>>     -
>>>     -dnl Add snat and dnat
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>>     <http://192.168.1.0/24>])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>     192.168.1.2])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>     192.168.1.3 lp0 00:00:00:01:02:03])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>        LOGICAL_PORT
>>>     -dnat             30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>      00:00:00:01:02:03    lp0
>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>>     <http://192.168.1.0/24>], [1], [],
>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>>     NAT with this external_ip and logical_ip already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24
>>>     <http://192.168.1.10/24>], [1], [],
>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>>     NAT with this external_ip and logical_ip already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1
>>>     192.168.1.0/24 <http://192.168.1.0/24>])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24
>>>     <http://192.168.1.0/24>], [1], [],
>>>     -[ovn-nbctl: a NAT with this type (snat) and logical_ip
>>>     (192.168.1.0/24 <http://192.168.1.0/24>) already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2],
>>>     [1], [],
>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>>     with this external_ip and logical_ip already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1
>>>     192.168.1.2])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3],
>>>     [1], [],
>>>     -[ovn-nbctl: a NAT with this type (dnat) and external_ip
>>>     (30.0.0.1) already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>     192.168.1.2], [1], [],
>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>>     with this external_ip and logical_ip already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>     30.0.0.1 192.168.1.2])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>     192.168.1.3], [1], [],
>>>     -[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
>>>     (30.0.0.1) already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>     30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>        LOGICAL_PORT
>>>     -dnat             30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>      00:00:00:04:05:06    lp0
>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>     30.0.0.2 192.168.1.3])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>        LOGICAL_PORT
>>>     -dnat             30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>     -])
>>>     -
>>>     -dnl Deletes the NATs
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], 
>>> [1], [],
>>>     -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and
>>>     external_ip (30.0.0.3)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
>>>     -[ovn-nbctl: no matching NAT with the type (dnat) and external_ip
>>>     (30.0.0.2)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24
>>>     <http://192.168.10.0/24>], [1], [],
>>>     -[ovn-nbctl: no matching NAT with the type (snat) and logical_ip
>>>     (192.168.10.0/24 <http://192.168.10.0/24>)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat
>>>     192.168.10.0/24 <http://192.168.10.0/24>])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>        LOGICAL_PORT
>>>     -dnat             30.0.0.1           192.168.1.2
>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>        LOGICAL_PORT
>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
>>>     -dnl Add two LBs.
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>     -[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP
>>>     address and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>     -[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP
>>>     address and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80
>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20 tcp], [1], [],
>>>     -[ovn-nbctl: 192.168.10.20 <http://192.168.10.20>: should be an IP
>>>     address and a port number with : as a separator.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>], [1], [],
>>>     -[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address
>>>     and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>], [1], [],
>>>     -[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and
>>>     a port number with : as a separator).
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>     192.168.10.10,192.168.10.20:80 <http://192.168.10.20:80>], [1], [],
>>>     -[ovn-nbctl: 192.168.10.20:80 <http://192.168.10.20:80>: should be
>>>     an IP address.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>     192.168.10.10:a80], [1], [],
>>>     -[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>     192.168.10.10:], [1], [],
>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>:: should be an
>>>     IP address.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>     192.168.10.1a], [1], [],
>>>     -[ovn-nbctl: 192.168.10.1a: should be an IP address.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 <http://30.0.0.10>:
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], 
>>> [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900
>>>     <http://192.168.10.10:900> tcp], [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -dnl Add ips to lb
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,,])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,192.168.10.20:80
>>>     <http://192.168.10.20:80>,,,,])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>
>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -])
>>>     -
>>>     -dnl Update the VIP of the lb1.
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080> udp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     -])
>>>     -
>>>     -dnl Config lb1 with another VIP.
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 <http://30.0.0.20:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80> udp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     - udp 30.0.0.20:80 <http://30.0.0.20:80> 192.168.10.10:80
>>>     <http://192.168.10.10:80>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80 
>>> <http://30.0.0.20:80>])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     -])
>>>     -
>>>     -dnl Add LBs whose vip is just an IP address.
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
>>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     -<2>    lb2                 tcp/udp    30.0.0.30  192.168.10.10
>>>     -<3>    lb3                 tcp/udp    30.0.0.30  192.168.10.10
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
>>>     -AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>            IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080>
>>>     -<2>    lb2                 tcp 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>> <http://192.168.10.20:80>
>>>     -<3>    lb2                 tcp 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>> <http://192.168.10.20:80>
>>>     -])
>>>     -
>>>     -dnl If there are multiple load balancers with the same name, use
>>>     a UUID to update/delete.
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>     <http://30.0.0.10:80> 192.168.10.10:8080
>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080> udp])
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:8080
>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080> udp])
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090
>>>     <http://30.0.0.10:9090> 192.168.10.10:8080
>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>     <http://192.168.10.20:8080> udp])
>>>     -AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80 
>>> <http://30.0.0.10:80>])
>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>            IPs
>>>     -<0>    lb2                 tcp 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>> <http://192.168.10.20:80>
>>>     -<1>    lb2                 tcp 30.0.0.10:8080
>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>> <http://192.168.10.20:80>
>>>     -])
>>>     -
>>>     -dnl Add load balancer to logical switch.
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80> udp])
>>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10
>>>     192.168.10.10,192.168.10.20])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>>      192.168.10.10,192.168.10.20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>>      192.168.10.10,192.168.10.20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>>     -
>>>     -dnl Remove all load balancers from logical switch.
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>     -
>>>     -dnl Add load balancer to logical router.
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>>      192.168.10.10,192.168.10.20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>          IPs
>>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>     <http://192.168.10.20:80>
>>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>>      192.168.10.10,192.168.10.20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>>     -
>>>     -dnl Remove all load balancers from logical router.
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>     -
>>>     -dnl Remove load balancers after adding them to a logical
>>>     router/switch.
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
>>>     -dnl A bunch of commands that should fail
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>     -[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP
>>>     address and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>     -[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP
>>>     address and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>>     -[ovn-nbctl: fd0f::20: should be an IP address and a port number
>>>     with : as a separator.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff
>>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>>     -[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP
>>>     address and a port number with : as a separator).
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
>>>     -[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>     fd0f::10,[[fd0f::20]]:80], [1], [],
>>>     -[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>     [[fd0f::10]]:a80], [1], [],
>>>     -[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>     [[fd0f::10]]:], [1], [],
>>>     -[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>     fd0f::1001a], [1], [],
>>>     -[ovn-nbctl: fd0f::1001a: should be an IP address.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp],
>>>     [1], [],
>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>>     family is different from VIP ae0f::10.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>>     family is different from VIP ae0f::10.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80
>>>     <http://192.168.10.10:80>], [1], [],
>>>     -[ovn-nbctl: 192.168.10.10:80 <http://192.168.10.10:80>: IP
>>>     address family is different from VIP [[ae0f::10]]:80.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
>>>     -[ovn-nbctl: ae0f::10: IP address family is different from VIP
>>>     30.0.0.10.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>     [[ae0f::10]]:80], [1], [],
>>>     -[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from
>>>     VIP 30.0.0.10:80 <http://30.0.0.10:80>.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
>>>     -AT_CHECK([ovn-nbctl lb-add lb0
>>>     ae0f:0000:0000:0000:0000:0000:0000:0010 fd0f::20],
>>>     -[1], [], [ovn-nbctl: lb0: a load balancer with this vip
>>>     (ae0f::10) already exists
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>     -
>>>     -dnl Add ips to lb
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>     ,,,[[fd0f::10]]:80,,,,,])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>     ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80 [[fd0f::10]]:80
>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>     -
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -])
>>>     -
>>>     -dnl Update the VIP of the lb1.
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     -])
>>>     -
>>>     -dnl Config lb1 with another VIP.
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 
>>> udp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     - udp        [[ae0f::20]]:80    [[fd0f::10]]:80
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     -])
>>>     -
>>>     -dnl Add LBs whose vip is just an IP address.
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
>>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     -<2>    lb2                 tcp/udp    ae0f::30  fd0f::10
>>>     -<3>    lb3                 tcp/udp    ae0f::30  fd0f::10
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
>>>     -AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>             IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>     -<2>    lb2                 tcp [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<3>    lb2                 tcp [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -])
>>>     -
>>>     -dnl If there are multiple load balancers with the same name, use
>>>     a UUID to update/delete.
>>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080
>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090
>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>     -AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>             IPs
>>>     -<0>    lb2                 tcp [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb2                 tcp [[ae0f::10]]:8080
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -])
>>>     -
>>>     -dnl Add load balancer to logical switch.
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
>>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>>     -
>>>     -dnl Remove all load balancers from logical switch.
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>     -
>>>     -dnl Add load balancer to logical router.
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>     -UUID                                    LB PROTO      VIP
>>>           IPs
>>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>>     -
>>>     -dnl Remove all load balancers from logical router.
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router
>>>     commands], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>     -<0> (lr0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>     -<0> (lr0)
>>>     -<1> (lr1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>     -<0> (lr1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl show lr0])
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>>     -  [router <0> (lr0)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
>>>     -  [ovn-nbctl: lr0: a router with this name already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>>     -  [router <0> (lr0)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], 
>>> [1], [],
>>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>>     together
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
>>>     -  [ovn-nbctl: Multiple logical routers named 'lr0'.  Use a UUID.
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
>>>     -  [ovn-nbctl: lr2: router name not found
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-add])
>>>     -AT_CHECK([ovn-nbctl lr-add])
>>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
>>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
>>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port
>>>     commands], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02
>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04
>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>     -
>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
>>>     -router <0> (lr0)
>>>     -    port lrp0
>>>     -        mac: "00:00:00:01:02:03"
>>>     -        networks: [["192.168.1.1/24 <http://192.168.1.1/24>"]]
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp0: a port with this name already exists
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>])
>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>     -<0> (lrp0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24> peer=lrp1-peer])
>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>     -<0> (lrp0)
>>>     -<1> (lrp1)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp1: a port with this name already exists
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp1: port already exists but in router lr0
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:04:05:06 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp1: port already exists with mac 00:00:00:01:02:03
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>     -  [ovn-nbctl: lrp1: port already exists with mismatching peer
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24>
>>>     peer=lrp1-peer], [1], [],
>>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>     peer=lrp1-peer])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-del lrp1])
>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>     -<0> (lrp0)
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>     10.0.0.1/24 <http://10.0.0.1/24> peer=lrp1-peer])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>     172.16.0.1/24 <http://172.16.0.1/24> peer=lrp1-peer], [1], [],
>>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24> 192.168.1.1/24
>>>     <http://192.168.1.1/24> peer=lrp1-peer])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port
>>>     gateway chassis], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], 
>>> [],
>>>     -[ovn-nbctl: lp0: port name not found
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
>>>     -[ovn-nbctl: lp0: port name not found
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], 
>>> [],
>>>     -[ovn-nbctl: lp0: port name not found
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], 
>>> [1], [],
>>>     -[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis1     0
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis1    10
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis1    20
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis1    20
>>>     -lrp0-chassis2     5
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis2     5
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>     -lrp0-chassis2    10
>>>     -lrp0-chassis3     5
>>>     -lrp0-chassis1     1
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port
>>>     enable and disable], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
>>>     -  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -
>>>     -dnl Check IPv4 routes
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>>     192.168.0.1])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24
>>>     <http://10.0.1.0/24> 11.0.1.1 lp0])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>>     <http://10.0.0.1/24> 11.0.0.2])
>>>     -
>>>     -dnl Add overlapping route with 10.0.0.1/24 <http://10.0.0.1/24>
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>     <http://10.0.0.111/24> 11.0.0.1], [1], [],
>>>     -  [ovn-nbctl: duplicate prefix: 10.0.0.0/24 <http://10.0.0.0/24>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1],
>>>     [1], [],
>>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a
>>>     <http://10.0.0.111/24a> 11.0.0.1], [1], [],
>>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
>>>     <http://10.0.0.111/24a>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>     <http://10.0.0.111/24> 11.0.0.1a], [1], [],
>>>     -  [ovn-nbctl: bad next hop argument: 11.0.0.1a
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>     <http://10.0.0.111/24> 11.0.0.1/24 <http://11.0.0.1/24>], [1], [],
>>>     -  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
>>>     <http://11.0.0.1/24>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>     2001:0db8:0:f103::1/64], [1], [],
>>>     -  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>>     <http://10.0.0.111/24> 11.0.0.1])
>>>     -AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24
>>>     <http://9.16.1.0/24> 11.0.0.1])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv4 Routes
>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip
>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>     - 9.16.1.0/24 <http://9.16.1.0/24> 11.0.0.1 src-ip
>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>>     <http://10.0.0.111/24> 11.0.0.1 lp1])
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv4 Routes
>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip lp1
>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>     - 9.16.1.0/24 <http://9.16.1.0/24> 11.0.0.1 src-ip
>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>     -])
>>>     -
>>>     -dnl Delete non-existent prefix
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24
>>>     <http://10.0.2.1/24>], [1], [],
>>>     -  [ovn-nbctl: no matching prefix: 10.0.2.0/24 <http://10.0.2.0/24>
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24
>>>     <http://10.0.2.1/24>])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24
>>>     <http://10.0.1.1/24>])
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24
>>>     <http://9.16.1.0/24>])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv4 Routes
>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip lp1
>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -])
>>>     -
>>>     -dnl Check IPv6 routes
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>>     2001:0db8:0:f101::1])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>>     2001:0db8:0:f102::1 lp0])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>     2001:0db8:0:f103::1])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv6 Routes
>>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv6 Routes
>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -])
>>>     -
>>>     -dnl Check IPv4 and IPv6 routes
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>>     192.168.0.1])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24
>>>     <http://10.0.1.1/24> 11.0.1.1 lp0])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>>     <http://10.0.0.1/24> 11.0.0.1])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>>     2001:0db8:0:f101::1])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>>     2001:0db8:0:f102::1 lp0])
>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>     2001:0db8:0:f103::1])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>     -IPv4 Routes
>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip
>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>     -
>>>     -IPv6 Routes
>>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>     -
>>>     -dnl Add policies with allow and drop actions
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>>     <http://1.1.1.0/24>" drop])
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24
>>>     <http://1.1.2.0/24>" allow])
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24
>>>     <http://2.1.1.0/24>" allow])
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24
>>>     <http://2.1.2.0/24>" drop])
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64"
>>>     drop])
>>>     -
>>>     -dnl Add duplicated policy
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>>     <http://1.1.1.0/24>" drop], [1], [],
>>>     -  [ovn-nbctl: Same routing policy already existed on the logical
>>>     router lr0.
>>>     -])
>>>     -
>>>     -dnl Add duplicated policy
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24
>>>     <http://1.1.1.0/24>" deny], [1], [],
>>>     -  [ovn-nbctl: deny: action must be one of "allow", "drop", and
>>>     "reroute"
>>>     -])
>>>     -
>>>     -dnl Delete by priority and match string
>>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24
>>>     <http://1.1.1.0/24>"])
>>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>>     -Routing Policies
>>>     -       101                              ip4.src == 2.1.1.0/24
>>>     <http://2.1.1.0/24>           allow
>>>     -       101                              ip4.src == 2.1.2.0/24
>>>     <http://2.1.2.0/24>            drop
>>>     -       101                               ip6.src == 2002::/64
>>>             drop
>>>     -       100                              ip4.src == 1.1.2.0/24
>>>     <http://1.1.2.0/24>           allow
>>>     -])
>>>     -
>>>     -dnl Delete all policies for given priority
>>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
>>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>>     -Routing Policies
>>>     -       100                              ip4.src == 1.1.2.0/24
>>>     <http://1.1.2.0/24>           allow
>>>     -])
>>>     -
>>>     -dnl Add policy with reroute action
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24
>>>     <http://3.1.2.0/24>" reroute 3.3.3.3])
>>>     -
>>>     -dnl Add policy with invalid reroute ip
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24
>>>     <http://3.1.2.0/24>" reroute 3.3.3.x], [1], [],
>>>     -  [ovn-nbctl: bad next hop argument: 3.3.3.x
>>>     -])
>>>     -
>>>     -dnl Add policy with reroute action
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64"
>>>     reroute 2002::5])
>>>     -
>>>     -dnl Add policy with invalid reroute ip
>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64"
>>>     reroute 2002::x], [1], [],
>>>     -  [ovn-nbctl: bad next hop argument: 2002::x
>>>     -])
>>>     -
>>>     -])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>     -
>>>     -dnl switchport type defaults to empty
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -
>>>     -])
>>>     -
>>>     -dnl The following are the valid entries for
>>>     -dnl switchport type
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -l2gateway
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -router
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -localnet
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -localport
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -vtep
>>>     -])
>>>     -
>>>     -dnl All of these are valid southbound port types but
>>>     -dnl should be rejected for northbound logical switch
>>>     -dnl ports.
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
>>>     -ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized.
>>>     Not setting type.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
>>>     -ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not
>>>     setting type.
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], [], 
>>> [dnl
>>>     -ovn-nbctl: Logical switch port type 'chassisredirect' is
>>>     unrecognized. Not setting type.
>>>     -])
>>>     -
>>>     -dnl switch port type should still be "vtep" since previous
>>>     -dnl commands failed.
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -vtep
>>>     -])
>>>     -
>>>     -dnl Attempt a nonsense type
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
>>>     -ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not
>>>     setting type.
>>>     -])
>>>     -
>>>     -dnl Empty string should work too
>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>     -
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
>>>     -AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection
>>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
>>>     -AT_CHECK([ovn-nbctl list connection | grep inactivity_probe],
>>>     [0], [dnl
>>>     -inactivity_probe    : 30000
>>>     -inactivity_probe    : 30000
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
>>>     -dnl Check that dry run has no permanent effect.
>>>     -AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt],
>>>     [0], [dnl
>>>     -<0> (ls0)
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>     -])
>>>     -
>>>     -dnl Check that dry-run mode is not sticky.
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>     -<0> (ls0)
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
>>>     -AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
>>>     -
>>>     -dnl Expect one line for one command.
>>>     -AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
>>>     -<0> (ls0)\n<1> (ls1)
>>>     -])
>>>     -
>>>     -dnl Expect lines for two commands.
>>>     -AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt],
>>>     [0], [dnl
>>>     -<0> (ls0)\n<1> (ls1)
>>>     -<0> (ls0)\n<1> (ls1)
>>>     -])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error
>>>     paths], [
>>>     -dnl FIXME: Duplicate options are allowed when passed with global
>>>     options.
>>>     -dnl        For example: ovn-nbctl --if-exists --if-exists list
>>>     Logical_Switch
>>>     -
>>>     -dnl Duplicate option
>>>     -AT_CHECK([ovn-nbctl -- --if-exists --if-exists list
>>>     Logical_Switch], [1], [], [stderr])
>>>     -AT_CHECK([grep 'option specified multiple times' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -dnl Missing command
>>>     -AT_CHECK([ovn-nbctl], [1], [], [stderr])
>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --], [1], [], [stderr])
>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>     -
>>>     -dnl Unknown command
>>>     -AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
>>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
>>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>>     -
>>>     -dnl Unknown option
>>>     -AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], [stderr])
>>>     -AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], 
>>> [stderr])
>>>     -AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
>>>     -
>>>     -dnl Missing option argument
>>>     -AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
>>>     -AT_CHECK([grep 'option .* requires an argument' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [],
>>>     [stderr])
>>>     -AT_CHECK([grep 'missing argument to .* option' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -dnl Unexpected option argument
>>>     -AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1],
>>>     [], [stderr])
>>>     -AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .*
>>>     requires an argument' stderr], [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1],
>>>     [], [stderr])
>>>     -AT_CHECK([grep 'option on .* does not accept an argument'
>>>     stderr], [0], [ignore])
>>>     -
>>>     -dnl Not enough arguments
>>>     -AT_CHECK([ovn-nbctl list], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>>     [0], [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>>     [0], [ignore])
>>>     -
>>>     -dnl Too many arguments
>>>     -AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>     [ignore])
>>>     -
>>>     -AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>     [ignore])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
>>>     -dnl Check that port group can be looked up by name
>>>     -AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
>>>     -pg0
>>>     -])])
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
>>>     -dnl This test addresses a specific issue seen when running
>>>     ovn-nbctl in
>>>     -dnl daemon mode. All we have to do is ensure that each time we
>>>     list database
>>>     -dnl information, there is not an extra newline at the beginning
>>>     of the output.
>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>>     [dnl
>>>     -name                : sw1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>>     [dnl
>>>     -name                : sw1
>>>     -])])
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
>>>     -dnl This test addresses a specific issue seen when running
>>>     ovn-nbctl in
>>>     -dnl daemon mode. We need to ensure that table formatting options
>>>     are honored
>>>     -dnl when listing database information.
>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch
>>>     sw1], [0], [dnl
>>>     -sw1
>>>     -])])
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group
>>>     commands], [
>>>     -AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], 
>>> [0],
>>>     -[pg1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
>>>     -SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>>     sw1-p1)
>>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
>>>     -SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>>     sw1-p2)
>>>     -
>>>     -AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1],
>>>     [0],[dnl
>>>     -pg1
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>>     port_group pg1], [0], [dnl
>>>     -$SW1P1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
>>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>>     port_group pg1], [0], [dnl
>>>     -$SW1P2
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>>     -])
>>>     -
>>>     -AT_SETUP([ovn-nbctl - daemon retry connection])
>>>     -OVN_NBCTL_TEST_START daemon
>>>     -AT_CHECK([kill `cat ovsdb-server.pid`])
>>>     -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
>>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>>     [stderr])
>>>     -AT_CHECK([ovn-nbctl show], [0], [ignore])
>>>     -OVN_NBCTL_TEST_STOP /Terminated/d
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn-northd.at <http://ovn-northd.at>
>>>     b/tests/ovn-northd.at <http://ovn-northd.at>
>>>     deleted file mode 100644
>>>     index 62e58fd..0000000
>>>     --- a/tests/ovn-northd.at <http://ovn-northd.at>
>>>     +++ /dev/null
>>>     @@ -1,900 +0,0 @@
>>>     -AT_BANNER([OVN northd])
>>>     -AT_SETUP([ovn -- check   from NBDB to SBDB])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>     -
>>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl --wait=sb \
>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>     -                                     chassis_name=gw1 \
>>>     -                                     priority=20 -- \
>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>     -                                     chassis_name=gw2 \
>>>     -                                     priority=10 -- \
>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>     Gateway_Chassis name="alice_gw1"`
>>>     -
>>>     -# With the new ha_chassis_group table added, there should be no
>>>     rows in
>>>     -# gateway_chassis table in SB DB.
>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# There should be one ha_chassis_group with the name "alice"
>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="alice"`
>>>     -
>>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>>     -
>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>     ha_chassis_group name=alice`
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>     port_binding \
>>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# There should be one ha_chassis_group with the name "alice"
>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="alice"`
>>>     -
>>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>>     -
>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>     ha_chassis_group name=alice`
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>     port_binding \
>>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>> ha_chassis_group`
>>>     -# Trim the spaces.
>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>     -
>>>     -ha_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list="$ha_ch_list $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>     -
>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>     -
>>>     -# Delete chassis - gw2 in SB DB.
>>>     -# ovn-northd should not recreate ha_chassis rows
>>>     -# repeatedly when gw2 is deleted.
>>>     -ovn-sbctl chassis-del gw2
>>>     -
>>>     -ha_ch_list_1=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>>     -
>>>     -ha_ch_list_2=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>>     -
>>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>>     -
>>>     -# Add back the gw2 chassis
>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>     -
>>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>>     -gw_ch=`ovn-sbctl --bare --columns gateway_chassis find 
>>> port_binding \
>>>     -logical_port="cr-alice"`
>>>     -AT_CHECK([test "$gw_ch" = ""])
>>>     -
>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>> ha_chassis_group`
>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>     -# Trim the spaces.
>>>     -echo "ha ch in grp = $ha_ch"
>>>     -
>>>     -ha_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list="$ha_ch_list $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>     -
>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>     -
>>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port alice
>>>     gateway_chassis=${nb_gwc1_uuid}
>>>     -
>>>     -# There should be only 1 row in ha_chassis SB DB table.
>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>     -l], [0], [1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# There should be only 1 row in ha_chassis SB DB table.
>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>     -l], [0], [1
>>>     -])
>>>     -
>>>     -# delete all the gateway_chassis on NBDB for alice port
>>>     -
>>>     -ovn-nbctl --wait=sb clear Logical_Router_Port alice 
>>> gateway_chassis
>>>     -
>>>     -# expect that the ha_chassis doesn't exist anymore
>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# expect that the ha_chassis doesn't exist anymore
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to
>>>     SBDB backwards compatibility])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>     -
>>>     -ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03
>>>     172.16.1.1/24 <http://172.16.1.1/24> \
>>>     -    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
>>>     -
>>>     -
>>>     -# It should be converted to ha_chassis_group entries in SBDB, and
>>>     -# still redirect-chassis is kept for backwards compatibility
>>>     -
>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>     -l], [0], [1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group
>>>     | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# There should be one ha_chassis_group with the name "bob_gw1"
>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="bob_gw1"`
>>>     -
>>>     -AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
>>>     -
>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>     ha_chassis_group name=bob_gw1`
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>     port_binding \
>>>     -logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb remove Logical_Router_Port bob options
>>>     redirect-chassis
>>>     -
>>>     -# expect that the ha_chassis/ha_chassis_group doesn't exist 
>>> anymore
>>>     -
>>>     -AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check up state of VIF LSP])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add S1
>>>     -ovn-nbctl --wait=sb lsp-add S1 S1-vm1
>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
>>>     -
>>>     -ovn-sbctl chassis-add hv1 geneve 127.0.0.1
>>>     -ovn-sbctl lsp-bind S1-vm1 hv1
>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check up state of router LSP linked to a
>>>     distributed LR])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl ls-add S1
>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check up state of router LSP linked to a gateway
>>>     LR])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl ls-add S1
>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>     -
>>>     -ovn-sbctl lsp-bind S1-R1 gw1
>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check up state of router LSP linked to an LRP
>>>     with set Gateway Chassis])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
>>>     -
>>>     -ovn-nbctl ls-add S1
>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>     -ovn-nbctl lsp-set-addresses S1-R1 router
>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl lr-add ro
>>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>>>     -ovn-nbctl ls-add sw
>>>     -ovn-nbctl lsp-add sw sw-ro
>>>     -ovn-nbctl lsp-set-type sw-ro router
>>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:send_periodic=true
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:address_mode=slaac
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:mtu=1280
>>>     -
>>>     -uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding
>>>     logical_port=ro-sw)
>>>     -
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_send_periodic],
>>>     -[0], ["true"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_address_mode],
>>>     -[0], [slaac
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[0], ["600"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[0], ["200"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
>>>     -[0], ["1280"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_src_eth],
>>>     -[0], ["00:00:00:00:00:01"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_src_addr],
>>>     -[0], ["fe80::200:ff:fe00:1"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_prefixes],
>>>     -[0], ["aef0::/64"
>>>     -])
>>>     -
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:max_interval=300
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:min_interval=600
>>>     -
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[0], ["300"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[0], ["225"
>>>     -])
>>>     -
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:max_interval=300
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:min_interval=250
>>>     -
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[0], ["300"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[0], ["225"
>>>     -])
>>>     -
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:max_interval=0
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:min_interval=0
>>>     -
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[0], ["4"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[0], ["3"
>>>     -])
>>>     -
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:max_interval=3600
>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:min_interval=2400
>>>     -
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[0], ["1800"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[0], ["1350"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb set Logical_Router_port ro-sw
>>>     ipv6_ra_configs:send_periodic=false
>>>     -
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_send_periodic],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in
>>>     Port_Binding record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_max_interval],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in
>>>     Port_Binding record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_min_interval],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in
>>>     Port_Binding record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_mtu],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record
>>>     "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_address_mode],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in
>>>     Port_Binding record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_src_eth],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding
>>>     record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_src_addr],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding
>>>     record "${uuid}" column options
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>     options:ipv6_ra_prefixes],
>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding
>>>     record "${uuid}" column options
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- test unixctl])
>>>     -ovn_init_db ovn-sb; ovn-sbctl init
>>>     -ovn_init_db ovn-nb; ovn-nbctl init
>>>     -
>>>     -# test unixctl option
>>>     -mkdir "$ovs_base"/northd
>>>     -as northd start_daemon ovn-northd
>>>     --unixctl="$ovs_base"/northd/ovn-northd.ctl
>>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -ovn-nbctl ls-add sw
>>>     -ovn-nbctl --wait=sb lsp-add sw p1
>>>     -# northd created with unixctl option successfully created
>>>     port_binding entry
>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>     logical_port="p1" | wc -l], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
>>>     -
>>>     -# ovs-appctl exit with unixctl option
>>> -OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl],
>>>     ["$ovs_base"/northd/ovn-northd.pid])
>>>     -
>>>     -# Check no port_binding entry for new port as ovn-northd is not
>>>     running
>>>     -ovn-nbctl lsp-add sw p2
>>>     -ovn-nbctl --timeout=10 --wait=sb sync
>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>     logical_port="p2" | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# test default unixctl path
>>>     -as northd start_daemon ovn-northd
>>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -ovn-nbctl --wait=sb lsp-add sw p3
>>>     -# northd created with default unixctl path successfully created
>>>     port_binding entry
>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>     logical_port="p3" | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -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])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to
>>>     SBDB])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>     -
>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>> rows
>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>     -# a logical router port or logical port of type external.
>>>     -AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group
>>>     name="hagrp1" \
>>>     -| wc -l], [0], [0
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>>     -
>>>     -# There should be no HA_Chassis rows in SB DB.
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>>     $3}' \
>>>     -| grep -v '-' | wc -l ], [0], [0
>>>     -])
>>>     -
>>>     -# Add chassis ch1.
>>>     -ovn-sbctl chassis-add ch1 geneve 127.0.0.2
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc
>>>     -l`])
>>>     -
>>>     -# There should be no HA_Chassis rows
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>>     $3}' \
>>>     -| grep -v '-' | wc -l ], [0], [0
>>>     -])
>>>     -
>>>     -# Create a logical router port and attach ha chassis group.
>>>     -ovn-nbctl lr-add lr0
>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13
>>>     172.168.0.100/24 <http://172.168.0.100/24>
>>>     -
>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>     ha_chassis_group name=hagrp1`
>>>     -ovn-nbctl set logical_router_port lr0-public
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Make sure that ovn-northd doesn't recreate the ha_chassis
>>>     -# records if the chassis record is missing in SB DB.
>>>     -
>>>     -ha_ch_list_1=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>>     -
>>>     -ha_ch_list_2=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>>     -
>>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>>     -
>>>     -# 2 HA chassis should be created with 'chassis' column empty 
>>> because
>>>     -# we have not added hv1 and hv2 chassis to the SB DB.
>>>     -AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis |
>>>     awk '{print $3}' \
>>>     -| grep -v '-' | wc -l`])
>>>     -
>>>     -# We should have 1 ha chassis with 'chassis' column set for hv1
>>>     -AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | awk '{print $3}' \
>>>     -| grep '-' | wc -l`])
>>>     -
>>>     -# Create another logical router port and associate to the same
>>>     ha_chasis_group
>>>     -ovn-nbctl lr-add lr1
>>>     -ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14
>>>     182.168.0.100/24 <http://182.168.0.100/24>
>>>     -
>>>     -ovn-nbctl set logical_router_port lr1-public
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -# We should still have 1 HA chassis group and 3 HA chassis in 
>>> SB DB.
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Change the priority of ch1 - ha chassis in NB DB. It should get
>>>     -# reflected in SB DB.
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority 
>>> find \
>>>     -ha_chassis | grep 100 | wc -l`])
>>>     -
>>>     -# Delete ch1 HA chassis in NB DB.
>>>     -ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
>>>     -
>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>     chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Add back the ha chassis
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
>>>     -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep
>>>     chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Delete lr0-public. We should still have 1 HA chassis group and
>>>     -# 3 HA chassis in SB DB.
>>>     -ovn-nbctl --wait=sb lrp-del lr0-public
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Delete lr1-public. There should be no HA chassis group in SB DB.
>>>     -ovn-nbctl --wait=sb lrp-del lr1-public
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>>     -l`])
>>>     -
>>>     -# Add lr0-public again
>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 
>>> 172.168.0.100/24
>>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> set
>>>     logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Create a Gateway chassis. ovn-northd should ignore this.
>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
>>>     -
>>>     -# There should be only 1 HA chassis group in SB DB with the
>>>     -# name hagrp1.
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Now delete HA chassis group. ovn-northd should create HA
>>>     chassis group
>>>     -# with the Gateway chassis name
>>>     -ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
>>>     -ovn-nbctl ha-chassis-group-del hagrp1
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>>     -find ha_chassis | wc -l`])
>>>     -
>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>     -
>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>     chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Test if 'ref_chassis' column is properly set or not in
>>>     -# SB DB ha_chassis_group.
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>>     -
>>>     -ovn-sbctl chassis-add ch2 geneve 127.0.0.3
>>>     -ovn-sbctl chassis-add ch3 geneve 127.0.0.4
>>>     -ovn-sbctl chassis-add comp1 geneve 127.0.0.5
>>>     -ovn-sbctl chassis-add comp2 geneve 127.0.0.6
>>>     -
>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
>>>     <http://10.0.0.1/24>
>>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>>     -
>>>     -ovn-sbctl lsp-bind sw0-p1 comp1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
>>>     -
>>>     -comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="comp1"`
>>>     -comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="comp2"`
>>>     -ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="comp1"`
>>>     -
>>>     -echo "comp1_ch_uuid = $comp1_ch_uuid"
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp1_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# unbind sw0-p1
>>>     -ovn-sbctl lsp-unbind sw0-p1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "" = "$ref_ch_list"])
>>>     -
>>>     -# Bind sw0-p1 in comp2
>>>     -ovn-sbctl lsp-bind sw0-p1 comp2
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>>     -ovn-nbctl lr-add lr1
>>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add sw1 sw1-lr1
>>>     -ovn-nbctl lsp-set-type sw1-lr1 router
>>>     -ovn-nbctl lsp-set-addresses sw1-lr1 router
>>>     -ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
>>>     -
>>>     -# Bind sw1-p1 in comp1.
>>>     -ovn-sbctl lsp-bind sw1-p1 comp1
>>>     -# Wait until sw1-p1 is up
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
>>>     -
>>>     -# sw1-p1 is not connected to lr0. So comp1 should not be in
>>>     'ref_chassis'
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Now attach sw0 to lr1
>>>     -ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
>>>     <http://10.0.0.10/24>
>>>     -ovn-nbctl lsp-add sw0 sw0-lr1
>>>     -ovn-nbctl lsp-set-type sw0-lr1 router
>>>     -ovn-nbctl lsp-set-addresses sw0-lr1 router
>>>     -ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
>>>     -
>>>     -# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is
>>>     indirectly
>>>     -# connected to lr0
>>>     -exp_ref_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>     -do
>>>     -    if test $i = $comp1_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    elif test $i = $comp2_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    fi
>>>     -done
>>>     -
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# Unind sw1-p1. comp2 should not be in the ref_chassis.
>>>     -ovn-sbctl lsp-unbind sw1-p1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Create sw2 and attach it to lr2
>>>     -ovn-nbctl ls-add sw2
>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>     -ovn-nbctl lr-add lr2
>>>     -ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
>>>     <http://30.0.0.1/24>
>>>     -ovn-nbctl lsp-add sw2 sw2-lr2
>>>     -ovn-nbctl lsp-set-type sw2-lr2 router
>>>     -ovn-nbctl lsp-set-addresses sw2-lr2 router
>>>     -ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
>>>     -
>>>     -# Bind sw2-p1 to comp1
>>>     -ovn-sbctl lsp-bind sw2-p1 comp1
>>>     -# Wait until sw2-p1 is up
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
>>>     -
>>>     -# sw2-p1 is not connected to lr0. So comp1 should not be in
>>>     'ref_chassis'
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected
>>>     to lr0.
>>>     -ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
>>>     <http://20.0.0.10/24>
>>>     -ovn-nbctl lsp-add sw1 sw1-lr2
>>>     -ovn-nbctl lsp-set-type sw1-lr2 router
>>>     -ovn-nbctl lsp-set-addresses sw1-lr2 router
>>>     -ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
>>>     -
>>>     -# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2)
>>>     should be in
>>>     -# 'ref_chassis'
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# Create sw0-p2 and bind it to comp1
>>>     -ovn-nbctl lsp-add sw0 sw0-p2
>>>     -ovn-sbctl lsp-bind sw0-p2 comp1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# unbind sw0-p2
>>>     -ovn-sbctl lsp-unbind sw0-p2
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# Delete lr1-sw0. comp1 should be deleted from ref_chassis as
>>>     there is no link
>>>     -# from sw1 and sw2 to lr0.
>>>     -ovn-nbctl lrp-del lr1-sw0
>>>     -
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Set redirect-chassis option to lr0-public. It should be ignored.
>>>     -ovn-nbctl set logical_router_port lr0-public
>>>     options:redirect-chassis=ch1
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>     -
>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>     chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Delete the gateway chassis. HA chassis group should be created
>>>     in SB DB
>>>     -# for the redirect-chassis option.
>>>     -ovn-nbctl clear logical_router_port lr0-public gateway_chassis
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group | wc -l`])
>>>     -
>>>     -ovn-sbctl list ha_chassis_group
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="lr0-public_ch1" | wc -l`])
>>>     -
>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep 
>>> chassis |
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Clear the redirect-chassis option.
>>>     -ovn-nbctl clear logical_router_port lr0-public options
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>>> -l`])
>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>     -
>>>     -# Delete old sw0.
>>>     -ovn-nbctl ls-del sw0
>>>     -
>>>     -# Create external logical ports and associate ha_chassis_group
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl lsp-add sw0 sw0-pext1
>>>     -ovn-nbctl lsp-add sw0 sw0-pext2
>>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>>     -
>>>     -ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 10.0.0.3"
>>>     -ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 10.0.0.4"
>>>     -ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
>>>     -
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>     -
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>>     -
>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>> rows
>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>     -# a logical router port or logical port of type external.
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>>> -l`])
>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>     -
>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find 
>>> ha_chassis_group \
>>>     -name=hagrp1`
>>>     -
>>>     -# The type of the lsp - sw0-pext1 is still not set to external.
>>>     -# So ha_chassis_group should be ignored.
>>>     -ovn-nbctl set logical_switch_port sw0-pext1
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>>     -l`])
>>>     -
>>>     -# Set the type of sw0-pext1 to external
>>>     -ovn-nbctl lsp-set-type sw0-pext1 external
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>>     ha_chassis_group \
>>>     -name=hagrp1`
>>>     -
>>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>>     -
>>>     -# Set the type of sw0-pext2 to external and associate
>>>     ha_chassis_group
>>>     -ovn-nbctl lsp-set-type sw0-pext2 external
>>>     -ovn-nbctl set logical_switch_port sw0-pext2
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
>>>     -grep -v chassis-name | wc -l`])
>>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare
>>>     --columns \
>>>     -ha_chassis_group find port_binding logical_port=sw0-pext2`])
>>>     -
>>>     -# sw0-p1 is a normal port. So ha_chassis_group should not be set
>>>     -# in port_binding.
>>>     -ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
>>>     -ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding \
>>>     -logical_port=sw0-p1) = x], [0], [])
>>>     -
>>>     -# Clear ha_chassis_group for sw0-pext1
>>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1
>>>     ha_chassis_group
>>>     -
>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding \
>>>     -logical_port=sw0-pext1) = x], [0], [])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>     -
>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -# Clear ha_chassis_group for sw0-pext2
>>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2
>>>     ha_chassis_group
>>>     -
>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding \
>>>     -logical_port=sw0-pext2) = x], [0], [])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc 
>>> -l`])
>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>     -
>>>     -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])
>>>     -
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn-performance.at <http://ovn-performance.at>
>>>     b/tests/ovn-performance.at <http://ovn-performance.at>
>>>     deleted file mode 100644
>>>     index a8a15f8..0000000
>>>     --- a/tests/ovn-performance.at <http://ovn-performance.at>
>>>     +++ /dev/null
>>>     @@ -1,424 +0,0 @@
>>>     -#
>>>     -# Tests targeting performance of OVN components.
>>>     -#
>>>     -
>>>     -m4_divert_push([PREPARE_TESTS])
>>>     -
>>>     -# vec_cmp VALUE_VEC OP-VALUE_VEC
>>>     -#
>>>     -# Compares each value from VALUE_VEC to the operator-value pair
>>>     from the
>>>     -# OP-VALUE_VEC.
>>>     -#
>>>     -# VALUE_VEC must be a list of values separated by a character
>>>     from $IFS.
>>>     -# OP-VALUE_VEC must be a list of operator-value expressions
>>>     separated by a
>>>     -# character from $IFS.  Operator-value expressions cannot contain
>>>     any characters
>>>     -# from $IFS like spaces. '=' is treated as an equality operator
>>>     ('==') for
>>>     -# conciseness.
>>>     -#
>>>     -# Returns the result of each comparison as a list of boolean
>>>     values (0 or 1)
>>>     -# separated by a new-line character.
>>>     -vec_cmp() {
>>>     -    local a b i j
>>>     -
>>>     -    i=0
>>>     -    for a in $1; do
>>>     -        j=0
>>>     -        for b in $2; do
>>>     -            if test $i -eq $j; then
>>>     -                # Replace assignment '=' with equality comparison
>>>     '=='
>>>     -                case "$b" in
>>>     -                =[[0-9]]*) b="=$b" ;;
>>>     -                esac
>>>     -
>>>     -                echo $(($a $b))
>>>     -                break
>>>     -            fi
>>>     -            j=$((j + 1))
>>>     -        done
>>>     -        i=$((i + 1))
>>>     -    done
>>>     -}
>>>     -
>>>     -# vec_sub VEC_A VEC_B
>>>     -#
>>>     -# Subtracts two vectors:
>>>     -#
>>>     -#     VEC_A = [a1, a2, ...]
>>>     -#     VEC_B = [b1, b2, ...]
>>>     -#     OUT = [(a1 - b1), (a2 - b2), ...]
>>>     -#
>>>     -# VEC_A and VEC_B must be lists of values separated by a
>>>     character from $IFS.
>>>     -vec_sub() {
>>>     -    local a b i j
>>>     -
>>>     -    i=0
>>>     -    for a in $1; do
>>>     -        j=0
>>>     -        for b in $2; do
>>>     -            if test $i -eq $j; then
>>>     -                echo $((a - b))
>>>     -                break
>>>     -            fi
>>>     -            j=$((j + 1))
>>>     -        done
>>>     -        i=$((i + 1))
>>>     -    done
>>>     -}
>>>     -
>>>     -# vec_fold VEC OP
>>>     -#
>>>     -# Reduces a vector to a single value by applying the binary
>>>     operator OP (i.e.,
>>>     -# one that requires two arguments) cumulatively to all vector
>>>     elements from left
>>>     -# to right:
>>>     -#
>>>     -#     VEC = [e1, e2, e3 ...]
>>>     -#     OUT = (...((e1 OP e2) OP e3) OP ...)
>>>     -#
>>>     -# VEC must be a list of values separated by a character from $IFS.
>>>     -vec_fold() {
>>>     -    local first op prod
>>>     -
>>>     -    first=1
>>>     -    op=$2
>>>     -    for a in $1; do
>>>     -        if test $first -eq 1; then
>>>     -            prod=$a
>>>     -            first=0
>>>     -        else
>>>     -            prod=$((prod $op a))
>>>     -        fi
>>>     -    done
>>>     -    echo $prod
>>>     -}
>>>     -
>>>     -# read_counters SANDBOXES TARGET COUNTER
>>>     -#
>>>     -# Prints out the coverage COUNTER for the TARGET in each of the
>>>     SANDBOXES.
>>>     -#
>>>     -# SANDBOXES must be a list of strings separated by a character
>>>     from $IFS.
>>>     -read_counters() {
>>>     -    local sims="$1" target="$2" counter="$3"
>>>     -
>>>     -    for sim in $sims; do
>>>     -        as $sim ovs-appctl -t "$target" coverage/read-counter
>>>     "$counter" || return 1
>>>     -    done
>>>     -}
>>>     -
>>>     -# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
>>>     -#
>>>     -# Runs the COMMAND and reports the COUNTER change registered
>>>     during the command
>>>     -# run for the given TARGET in each of the SANDBOXES.
>>>     -counter_delta_() {
>>>     -    local sims="$1" target="$2" counter="$3" cmd="$4"
>>>     -    local before after
>>>     -
>>>     -    before=$(read_counters "$sims" "$target" "$counter") || 
>>> return 1
>>>     -    eval "$cmd" >/dev/null || return 1
>>>     -    after=$(read_counters "$sims" "$target" "$counter") || 
>>> return 1
>>>     -
>>>     -    vec_sub "$after" "$before"
>>>     -}
>>>     -
>>>     -# counter_delta SANDBOXES TARGET COUNTER COMMAND
>>>     -#
>>>     -# Same as counter_delta_ but also prints the COUNTER values
>>>     together with the
>>>     -# COMMAND to standard error.
>>>     -counter_delta() {
>>>     -    local cmd="$4"
>>>     -    local v
>>>     -
>>>     -    v=$(counter_delta_ "$@") || return 1
>>>     -
>>>     -    # Dump the counters and the command for troubleshooting
>>>     -    echo "$v" | tr '\n' '\t' >&2
>>>     -    echo "$cmd" >&2
>>>     -
>>>     -    echo "$v"
>>>     -}
>>>     -
>>>     -# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
>>>     -#
>>>     -# Check if COUNTER change in the TARGET app in each of the
>>>     SANDBOXES after
>>>     -# running the COMMAND meets the conditions listed as
>>>     operator-value pairs in
>>>     -# CONDS.
>>>     -vec_cmp_counter_delta() {
>>>     -    local v
>>>     -
>>>     -    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
>>>     -    v=$(vec_cmp "$v" "$4") || return 1
>>>     -    v=$(vec_fold "$v" "&&") || return 1
>>>     -
>>>     -    echo "$v"
>>>     -}
>>>     -
>>>     -# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
>>>     -#
>>>     -# Check if COUNTER change in the TARGET app in each of the
>>>     SANDBOXES after
>>>     -# running the COMMAND meets the COND condition given as a
>>>     operator-value pair.
>>>     -cmp_counter_delta() {
>>>     -    local conds=""
>>>     -
>>>     -    # Use the same condition for each sandbox
>>>     -    for _ in $1; do
>>>     -        conds="$conds $4"
>>>     -    done
>>>     -
>>>     -    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
>>>     -}
>>>     -
>>>     -m4_divert_pop([PREPARE_TESTS])
>>>     -
>>>     -# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
>>>     -#
>>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>>     in all of
>>>     -# the SANDBOXES did not change.
>>>     -m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
>>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
>>>     -    rc=$?
>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>     -])
>>>     -
>>>     -# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER COMMAND
>>>     -#
>>>     -# Runs the COMMAND and checks if the COUNTER value for the 
>>> TARGET in
>>>     -# all of the SANDBOXES has changed.
>>>     -m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
>>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
>>>     -    rc=$?
>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>     -])
>>>     -
>>>     -# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
>>>     -#
>>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>>     in all of the
>>>     -# SANDBOXES satisfies the conditions listed in CONDS.
>>>     -m4_define([CHECK_COUNTER_DELTA_COND],[
>>>     -    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
>>>     -    rc=$?
>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>     -])
>>>     -
>>>     -# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
>>>     -#
>>>     -# Checks if the COUNTER value has changed for any of the
>>>     ovn-controller
>>>     -# processes in the SANDBOXES when the COMMAND was run.
>>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT],[
>>>     -    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2],
>>>     [$3])
>>>     -])
>>>     -
>>>     -# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
>>>     -#
>>>     -# Checks if the COUNTER value has not changed for any of the
>>>     ovn-controller
>>>     -# processes in the SANDBOXES when the COMMAND was run.
>>>     -m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
>>>     -    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], 
>>> [$3])
>>>     -])
>>>     -
>>>     -# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
>>>     -#
>>>     -# Checks if the change of the COUNTER value, when the COMMAND was
>>>     run, of the
>>>     -# ovn-controller process in each of the SANDBOXES meets the
>>>     conditions in
>>>     -# CONDS. CONDS must be a list of operator-value pairs, for
>>>     example "[>0 =0]",
>>>     -# following the same order as SANDBOXES.
>>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
>>>     -    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3],
>>>     [$4])
>>>     -])
>>>     -
>>>     -AT_SETUP([ovn -- ovn-controller incremental processing])
>>>     -# Check which operations the trigger full logical flow processing.
>>>     -#
>>>     -# Create and destroy logical routers, switches, ports, address
>>>     sets and ACLs
>>>     -# while counting calls to lflow_run() in ovn-controller.
>>>     -
>>>     -ovn_start
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -done
>>>     -
>>>     -# Add router lr1
>>>     -OVN_CONTROLLER_EXPECT_HIT(
>>>     -    [hv1 hv2], [lflow_run],
>>>     -    [ovn-nbctl --wait=hv lr-add lr1]
>>>     -)
>>>     -
>>>     -for i in 1 2; do
>>>     -    ls=ls$i
>>>     -    lsp=$ls-lr1
>>>     -    lrp=lr1-$ls
>>>     -
>>>     -    # Add switch $ls
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv ls-add $ls]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config
>>>     subnet=10.0.$i.0/24]
>>>     -    )
>>>     -
>>>     -    # Add router port to $ls
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01
>>>     10.0.$i.1/24]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-set-options $lsp 
>>> router-port=$lrp]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
>>>     -    )
>>>     -done
>>>     -
>>>     -get_lsp_uuid () {
>>>     -    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
>>>     -}
>>>     -
>>>     -pg_ports=
>>>     -
>>>     -for i in 1 2; do
>>>     -    j=$((i%2 + 1))
>>>     -    as=as$i
>>>     -    ls=ls$i
>>>     -    lp=lp$i
>>>     -    vif=vif$i
>>>     -
>>>     -    # Add port $lp
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lp]
>>>     -    )
>>>     -
>>>     -    pg_ports="$pg_port `get_lsp_uuid $lp`"
>>>     -
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl wait-until Logical_Switch_Port $lp
>>>     dynamic_addresses!=[[]] &&
>>>     -         ovn-nbctl --wait=hv sync]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl get Logical_Switch_Port $lp 
>>> dynamic_addresses &&
>>>     -         ovn-nbctl --wait=hv sync]
>>>     -    )
>>>     -
>>>     -    # Add address set $as
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv create Address_Set name="$as"]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv add Address_Set "$as" addresses
>>>     "10.0.$i.10"]
>>>     -    )
>>>     -
>>>     -    # Add ACLs for port $lp
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport
>>>     == \"$lp\" && ip4.src == \$$as' allow]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport
>>>     == \"$lp\"' drop]
>>>     -    )
>>>     -
>>>     -    # Bind port $lp and wait for it to come up
>>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>>     -        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface
>>>     $vif external-ids:iface-id=$lp &&
>>>     -         ovn-nbctl wait-until Logical_Switch_Port $lp 'up=true' &&
>>>     -         ovn-nbctl --wait=hv sync]
>>>     -    )
>>>     -done
>>>     -
>>>     -for i in 1 2; do
>>>     -    j=$((i%2 + 1))
>>>     -    as=as$i
>>>     -    ls=ls$i
>>>     -    lp=lp$i
>>>     -
>>>     -    # Delete ACLs for port $lp
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport
>>>     == \"$lp\" && ip4.src == \$$as']
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport
>>>     == \"$lp\"']
>>>     -    )
>>>     -
>>>     -    # Delete address set $as
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses
>>>     "10.0.$i.10"]
>>>     -    )
>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
>>>     -    )
>>>     -done
>>>     -
>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -    [hv1 hv2], [lflow_run],
>>>     -    [ovn-nbctl --wait=hv create Port_Group name=pg1
>>>     ports=\"$pg_ports\"]
>>>     -)
>>>     -
>>>     -# Add ACLs for port group pg1
>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -    [hv1 hv2], [lflow_run],
>>>     -    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport ==
>>>     @pg1 && ip4.src == $pg1_ip4' allow]
>>>     -)
>>>     -
>>>     -for i in 1 2; do
>>>     -    j=$((i%2 + 1))
>>>     -    lp=lp$i
>>>     -
>>>     -    # Delete port $lp
>>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>>     -        [ovn-nbctl --wait=hv lsp-del $lp]
>>>     -    )
>>>     -done
>>>     -
>>>     -# Delete port group pg1
>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>     -    [hv1 hv2], [lflow_run],
>>>     -    [ovn-nbctl --wait=hv destroy Port_Group pg1]
>>>     -)
>>>     -
>>>     -for i in 1 2; do
>>>     -    ls=ls$i
>>>     -
>>>     -    # Delete switch $ls
>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>     -        [hv1 hv2], [lflow_run],
>>>     -        [ovn-nbctl --wait=hv ls-del $ls]
>>>     -    )
>>>     -done
>>>     -
>>>     -# Delete router lr1
>>>     -OVN_CONTROLLER_EXPECT_HIT(
>>>     -    [hv1 hv2], [lflow_run],
>>>     -    [ovn-nbctl --wait=hv lr-del lr1]
>>>     -)
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>     b/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>     deleted file mode 100644
>>>     index 650e357..0000000
>>>     --- a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>     +++ /dev/null
>>>     @@ -1,150 +0,0 @@
>>>     -AT_BANNER([ovn-sbctl])
>>>     -
>>>     -# OVN_SBCTL_TEST_START
>>>     -m4_define([OVN_SBCTL_TEST_START],
>>>     -  [dnl Create databases (ovn-nb, ovn-sb).
>>>     -   AT_KEYWORDS([ovn])
>>>     -   for daemon in ovn-nb ovn-sb; do
>>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>>     -   done
>>>     -
>>>     -   dnl Start ovsdb-servers.
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>     --pidfile=ovnnb_db.pid --unixctl=$OVS_RUNDIR/ovnnb_db.ctl
>>>     --log-file=ovsdb_nb.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock
>>>     ovn-nb.db ], [0], [], [stderr])
>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>     --pidfile=ovnsb_db.pid --unixctl=$OVS_RUNDIR/ovnsb_db.ctl
>>>     --log-file=ovsdb_sb.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock
>>>     ovn-sb.db], [0], [], [stderr])
>>>     -   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d
>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>     -
>>>     -   dnl Start ovn-northd.
>>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file
>>>     --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock
>>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>>     -   on_exit "kill `cat ovn-northd.pid`"
>>>     -   AT_CHECK([[sed < stderr '
>>>     -/vlog|INFO|opened log file/d']])
>>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>>     -])
>>>     -
>>>     -# OVN_SBCTL_TEST_STOP
>>>     -m4_define([OVN_SBCTL_TEST_STOP],
>>>     -  [AT_CHECK([check_logs "$1"])
>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl],
>>>     [$OVS_RUNDIR/ovnnb_db.pid])
>>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl],
>>>     [$OVS_RUNDIR/ovnsb_db.pid])])
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -AT_SETUP([ovn-sbctl - chassis commands])
>>>     -OVN_SBCTL_TEST_START
>>>     -ovn_init_db ovn-sb
>>>     -
>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>     ip,type list encap | sort],
>>>     -         [0], [dnl
>>>     -1.2.3.4,geneve
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>     ip,type list encap | sort],
>>>     -         [0], [dnl
>>>     -1.2.3.4,geneve
>>>     -1.2.3.5,geneve
>>>     -1.2.3.5,stt
>>>     -1.2.3.5,vxlan
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-sbctl chassis-del ch0])
>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>     ip,type list encap | sort],
>>>     -         [0], [dnl
>>>     -1.2.3.5,geneve
>>>     -1.2.3.5,stt
>>>     -1.2.3.5,vxlan
>>>     -])
>>>     -
>>>     -OVN_SBCTL_TEST_STOP
>>>     -as ovn-sb
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -AT_CLEANUP
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -AT_SETUP([ovn-sbctl])
>>>     -OVN_SBCTL_TEST_START
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add br-test])
>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
>>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>     -
>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>     -Chassis ch0
>>>     -    Encap stt
>>>     -        ip: "1.2.3.5"
>>>     -        options: {csum="true"}
>>>     -    Port_Binding vif0
>>>     -])
>>>     -
>>>     -# adds another 'vif1'
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>>     -
>>>     -AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
>>>     -Chassis ch0
>>>     -    Encap stt
>>>     -        ip: "1.2.3.5"
>>>     -        options: {csum="true"}
>>>     -    Port_Binding vif
>>>     -    Port_Binding vif
>>>     -])
>>>     -
>>>     -# deletes 'vif1'
>>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>>     -
>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>     -Chassis ch0
>>>     -    Encap stt
>>>     -        ip: "1.2.3.5"
>>>     -        options: {csum="true"}
>>>     -    Port_Binding vif0
>>>     -])
>>>     -
>>>     -uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':'
>>>     -f2 | tr -d ' ')
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis
>>>     list Port_Binding], [0], [dnl
>>>     -logical_port        : vif0
>>>     -mac                 : [["f0:ab:cd:ef:01:02"]]
>>>     -chassis             : ${uuid}
>>>     -])
>>>     -
>>>     -# test the passing down of logical port type and options.
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0
>>>     vtep_logical_switch=l0])
>>>     -
>>>     -AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0
>>>     options!={}])
>>>     -AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list
>>>     Port_Binding vtep0], [0], [dnl
>>>     -logical_port        : vtep0
>>>     -mac                 : [[]]
>>>     -type                : vtep
>>>     -options             : {vtep_logical_switch=l0,
>>>     vtep_physical_switch=p0}
>>>     -])
>>>     -
>>>     -OVN_SBCTL_TEST_STOP
>>>     -AT_CLEANUP
>>>     -
>>>     -dnl
>>> ---------------------------------------------------------------------
>>>     -
>>>     -AT_SETUP([ovn-sbctl - connection])
>>>     -OVN_SBCTL_TEST_START
>>>     -
>>>     -AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection
>>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
>>>     -AT_CHECK([ovn-sbctl list connection | grep inactivity_probe],
>>>     [0], [dnl
>>>     -inactivity_probe    : 30000
>>>     -inactivity_probe    : 30000
>>>     -])
>>>     -
>>>     -OVN_SBCTL_TEST_STOP
>>>     -AT_CLEANUP
>>>     diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at
>>>     <http://ovn.at>
>>>     deleted file mode 100644
>>>     index cb380d2..0000000
>>>     --- a/tests/ovn.at <http://ovn.at>
>>>     +++ /dev/null
>>>     @@ -1,14702 +0,0 @@
>>>     -# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
>>>     -#
>>>     -# This compares packets read from PCAP, in pcap format, to 
>>> those read
>>>     -# from EXPECTED, which is a text file containing packets as hex
>>>     -# strings, one per line.  If PCAP contains fewer packets than
>>>     -# EXPECTED, it waits up to 10 seconds for more packets to appear.
>>>     -#
>>>     -# The implementation is an m4 macro that is mostly implemented in
>>>     -# terms of a shell function.  This reduces the size of the 
>>> generated
>>>     -# testsuite file since the shell function is only emitted once 
>>> even
>>>     -# when this macro is invoked many times.
>>>     -m4_divert_text([PREPARE_TESTS],
>>>     -  [ovn_check_packets__ () {
>>>     -     echo
>>>     -     echo "checking packets in $1 against $2:"
>>>     -     rcv_pcap=$1
>>>     -     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
>>>     -     exp_text=$2
>>>     -     exp_n=`wc -l < "$exp_text"`
>>>     -     OVS_WAIT_UNTIL(
>>>     -       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $rcv_pcap > $rcv_text
>>>     -        rcv_n=`wc -l < "$rcv_text"`
>>>     -        echo "rcv_n=$rcv_n exp_n=$exp_n"
>>>     -        test $rcv_n -ge $exp_n])
>>>     -     sort $exp_text > expout
>>>     -   }
>>>     -])
>>>     -m4_define([OVN_CHECK_PACKETS],
>>>     -  [ovn_check_packets__ "$1" "$2"
>>>     -   AT_CHECK([sort $rcv_text], [0], [expout])])
>>>     -
>>>     -AT_BANNER([OVN components])
>>>     -
>>>     -AT_SETUP([ovn -- lexer])
>>>     -dnl For lines without =>, input and expected output are identical.
>>>     -dnl For lines with =>, input precedes => and expected output
>>>     follows =>.
>>>     -AT_DATA([test-cases.txt], [dnl
>>>     -foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
>>>     -"abc\u0020def" => "abc def"
>>>     -" => error("Input ends inside quoted string.")dnl "
>>>     -
>>>     -$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
>>>     -$1 => error("`$' must be followed by a valid identifier.") 1
>>>     -
>>>     -a/*b*/c => a c
>>>     -a//b c => a
>>>     -a/**/b => a b
>>>     -a/*/b => a error("`/*' without matching `*/'.")
>>>     -a/*/**/b => a b
>>>     -a/b => a error("`/' is only valid as part of `//' or `/*'.") b
>>>     -
>>>     -0 1 12345 18446744073709551615
>>>     -18446744073709551616 => error("Decimal constants must be less
>>>     than 2**64.")
>>>     -9999999999999999999999 => error("Decimal constants must be less
>>>     than 2**64.")
>>>     -01 => error("Decimal constants must not have leading zeros.")
>>>     -
>>>     -0/0
>>>     -0/1
>>>     -1/0 => error("Value contains unmasked 1-bits.")
>>>     -1/1
>>>     -128/384
>>>     -1/3
>>>     -1/ => error("Integer constant expected.")
>>>     -
>>>     -1/0x123 => error("Value and mask have incompatible formats.")
>>>     -
>>>     -0x1234
>>>     -0x01234 => 0x1234
>>>     -0x0 => 0
>>>     -0x000 => 0
>>>     -0xfedcba9876543210
>>>     -0XFEDCBA9876543210 => 0xfedcba9876543210
>>>     -0xfedcba9876543210fedcba9876543210
>>>     -0x0000fedcba9876543210fedcba9876543210 =>
>>>     0xfedcba9876543210fedcba9876543210
>>>     -0x => error("Hex digits expected following 0x.")
>>>     -0X => error("Hex digits expected following 0X.")
>>>     -0x0/0x0 => 0/0
>>>     -0x0/0x1 => 0/0x1
>>>     -0x1/0x0 => error("Value contains unmasked 1-bits.")
>>>     -0xffff/0x1ffff
>>>     -0x. => error("Invalid syntax in hexadecimal constant.")
>>>     -
>>>     -192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
>>>     -256.1.2.3 => error("Invalid numeric constant.")
>>>     -192.168.0.0/16 <http://192.168.0.0/16>
>>>     -192.168.0.0/255.255.0.0 <http://192.168.0.0/255.255.0.0> =>
>>>     192.168.0.0/16 <http://192.168.0.0/16>
>>>     -192.168.0.0/255.255.255.0 <http://192.168.0.0/255.255.255.0> =>
>>>     192.168.0.0/24 <http://192.168.0.0/24>
>>>     -192.168.0.0/255.255.0.255 <http://192.168.0.0/255.255.0.255>
>>>     -192.168.0.0/255.0.0.0 <http://192.168.0.0/255.0.0.0> =>
>>>     error("Value contains unmasked 1-bits.")
>>>     -192.168.0.0/32 <http://192.168.0.0/32>
>>>     -192.168.0.0/255.255.255.255 <http://192.168.0.0/255.255.255.255>
>>>     => 192.168.0.0/32 <http://192.168.0.0/32>
>>>     -1.2.3.4:5 <http://1.2.3.4:5> => 1.2.3.4 : 5
>>>     -
>>>     -::
>>>     -::1
>>>     -ff00::1234 => ff00::1234
>>>     -2001:db8:85a3::8a2e:370:7334
>>>     -2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
>>>     -2001:0db8:85a3:0000:0000:8a2e:0370:7334 =>
>>>     2001:db8:85a3::8a2e:370:7334
>>>     -::ffff:192.0.2.128
>>>     -::ffff:c000:0280 => ::ffff:192.0.2.128
>>>     -::1/::1
>>>     -::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
>>>     -::1/128
>>>     -ff00::/8
>>>     -ff00::/ff00:: => ff00::/8
>>>     -
>>>     -01:23:45:67:ab:cd
>>>     -01:23:45:67:AB:CD => 01:23:45:67:ab:cd
>>>     -fe:dc:ba:98:76:54
>>>     -FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
>>>     -01:00:00:00:00:00/01:00:00:00:00:00
>>>     -ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>>     -fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>>     -ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains
>>>     unmasked 1-bits.")
>>>     -fe:x => error("Invalid numeric constant.")
>>>     -00:01:02:03:04:x => error("Invalid numeric constant.")
>>>     -
>>>     -# Test that operators are tokenized as expected, even without
>>>     white space.
>>> -(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= >
>>>     >= ! && || .. , ; = <-> -- :
>>>     -& => error("`&' is only valid as part of `&&'.")
>>>     -| => error("`|' is only valid as part of `||'.")
>>>     -- => error("`-' is only valid as part of `--'.")
>>>     -
>>>     -^ => error("Invalid character `^' in input.")
>>>     -])
>>>     -AT_CAPTURE_FILE([input.txt])
>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>     -sed 's/.* => //' test-cases.txt > expout
>>>     -AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
>>>     -AT_CLEANUP
>>>     -
>>>     -dnl The OVN expression parser needs to know what fields overlap
>>>     with one
>>>     -dnl another.  This test therefore verifies that all the smaller
>>>     registers
>>>     -dnl are defined as terms of subfields of the larger ones.
>>>     -dnl
>>>     -dnl When we add or remove registers this test needs to be
>>>     updated, of course.
>>>     -AT_SETUP([ovn -- registers])
>>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
>>>     -[[reg0 = xxreg0[96..127]
>>>     -reg1 = xxreg0[64..95]
>>>     -reg2 = xxreg0[32..63]
>>>     -reg3 = xxreg0[0..31]
>>>     -reg4 = xxreg1[96..127]
>>>     -reg5 = xxreg1[64..95]
>>>     -reg6 = xxreg1[32..63]
>>>     -reg7 = xxreg1[0..31]
>>>     -reg8 = xreg4[32..63]
>>>     -reg9 = xreg4[0..31]
>>>     -xreg0 = xxreg0[64..127]
>>>     -xreg1 = xxreg0[0..63]
>>>     -xreg2 = xxreg1[64..127]
>>>     -xreg3 = xxreg1[0..63]
>>>     -xreg4 = OXM_OF_PKT_REG4
>>>     -xxreg0 = NXM_NX_XXREG0
>>>     -xxreg1 = NXM_NX_XXREG1
>>>     -]])
>>>     -AT_CLEANUP
>>>     -
>>>     -dnl Check that the OVN conntrack field definitions are correct.
>>>     -AT_SETUP([ovn -- conntrack fields])
>>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
>>>     -[[ct.dnat = ct_state[7]
>>>     -ct.est = ct_state[1]
>>>     -ct.inv = ct_state[4]
>>>     -ct.new = ct_state[0]
>>>     -ct.rel = ct_state[2]
>>>     -ct.rpl = ct_state[3]
>>>     -ct.snat = ct_state[6]
>>>     -ct.trk = ct_state[5]
>>>     -ct_label = NXM_NX_CT_LABEL
>>>     -ct_label.blocked = ct_label[0]
>>>     -ct_mark = NXM_NX_CT_MARK
>>>     -ct_state = NXM_NX_CT_STATE
>>>     -]])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- composition])
>>>     -AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- expression parser])
>>>     -dnl For lines without =>, input and expected output are identical.
>>>     -dnl For lines with =>, input precedes => and expected output
>>>     follows =>.
>>>     -AT_DATA([test-cases.txt], [[
>>>     -eth.type == 0x800
>>>     -eth.type==0x800 => eth.type == 0x800
>>>     -eth.type[0..15] == 0x800 => eth.type == 0x800
>>>     -
>>>     -vlan.present
>>>     -vlan.present == 1 => vlan.present
>>>     -!(vlan.present == 0) => vlan.present
>>>     -!(vlan.present != 1) => vlan.present
>>>     -!vlan.present
>>>     -vlan.present == 0 => !vlan.present
>>>     -vlan.present != 1 => !vlan.present
>>>     -!(vlan.present == 1) => !vlan.present
>>>     -!(vlan.present != 0) => !vlan.present
>>>     -
>>>     -eth.dst[0]
>>>     -eth.dst[0] == 1 => eth.dst[0]
>>>     -eth.dst[0] != 0 => eth.dst[0]
>>>     -!(eth.dst[0] == 0) => eth.dst[0]
>>>     -!(eth.dst[0] != 1) => eth.dst[0]
>>>     -
>>>     -!eth.dst[0]
>>>     -eth.dst[0] == 0 => !eth.dst[0]
>>>     -eth.dst[0] != 1 => !eth.dst[0]
>>>     -!(eth.dst[0] == 1) => !eth.dst[0]
>>>     -!(eth.dst[0] != 0) => !eth.dst[0]
>>>     -
>>>     -vlan.tci[12..15] == 0x3
>>>     -vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
>>>     -vlan.tci[12..15] != 0x3
>>>     -vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
>>>     -
>>>     -!vlan.pcp => vlan.pcp == 0
>>>     -!(vlan.pcp) => vlan.pcp == 0
>>>     -vlan.pcp == 0x4
>>>     -vlan.pcp != 0x4
>>>     -vlan.pcp > 0x4
>>>     -vlan.pcp >= 0x4
>>>     -vlan.pcp < 0x4
>>>     -vlan.pcp <= 0x4
>>>     -!(vlan.pcp != 0x4) => vlan.pcp == 0x4
>>>     -!(vlan.pcp == 0x4) => vlan.pcp != 0x4
>>>     -!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
>>>     -!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
>>>     -!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
>>>     -!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
>>>     -0x4 == vlan.pcp => vlan.pcp == 0x4
>>>     -0x4 != vlan.pcp => vlan.pcp != 0x4
>>>     -0x4 < vlan.pcp => vlan.pcp > 0x4
>>>     -0x4 <= vlan.pcp => vlan.pcp >= 0x4
>>>     -0x4 > vlan.pcp => vlan.pcp < 0x4
>>>     -0x4 >= vlan.pcp => vlan.pcp <= 0x4
>>>     -!(0x4 != vlan.pcp) => vlan.pcp == 0x4
>>>     -!(0x4 == vlan.pcp) => vlan.pcp != 0x4
>>>     -!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
>>>     -!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
>>>     -!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
>>>     -!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
>>>     -
>>>     -1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
>>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>>     -1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
>>>     -1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
>>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>>     -4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
>>>     -4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
>>>     -4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
>>>     -4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
>>>     -!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
>>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>>     -!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
>>>     -!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
>>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>>     -!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
>>>     -!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
>>>     -!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
>>>     -!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
>>>     -
>>>     -vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 ||
>>>     vlan.pcp == 0x3 || vlan.pcp == 0x4
>>>     -vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp ==
>>>     4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 ||
>>>     vlan.pcp == 0x4
>>>     -
>>>     -vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 &&
>>>     vlan.pcp != 0x3 && vlan.pcp != 0x4
>>>     -vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp ==
>>>     4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 &&
>>>     vlan.pcp == 0x4
>>>     -
>>>     -vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 ||
>>>     vlan.pcp != 0x4)
>>>     -vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3)
>>>     && vlan.pcp == 0x4
>>>     -vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>     == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3)
>>>     || vlan.pcp != 0x4)
>>>     -
>>>     -ip4.src == {10.0.0.0/8 <http://10.0.0.0/8>, 192.168.0.0/16
>>>     <http://192.168.0.0/16>, 172.16.20.0/24 <http://172.16.20.0/24>,
>>>     8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 ||
>>>     ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
>>>     -ip6.src == ::1 => ip6.src == 0x1
>>>     -
>>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304
>>>     -ip4.src == ::1.2.3.4/::ffff:ffff <http://1.2.3.4/::ffff:ffff> =>
>>>     ip4.src == 0x1020304
>>>     -ip6.src == ::1 => ip6.src == 0x1
>>>     -
>>>     -1
>>>     -0
>>>     -!1 => 0
>>>     -!0 => 1
>>>     -
>>>     -inport == "eth0"
>>>     -!(inport != "eth0") => inport == "eth0"
>>>     -
>>> -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>>
>>>     => 0
>>>     -
>>>     -ip4.src == "eth0" => Integer field ip4.src is not compatible with
>>>     string constant.
>>>     -inport == 1 => String field inport is not compatible with integer
>>>     constant.
>>>     -ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational
>>>     operator.
>>>     -
>>>     -ip4.src > {1, 2, 3} => Only == and != operators may be used with
>>>     value sets.
>>>     -eth.type > 0x800 => Only == and != operators may be used with
>>>     nominal field eth.type.
>>>     -vlan.present > 0 => Only == and != operators may be used with
>>>     Boolean field vlan.present.
>>>     -
>>>     -inport != "eth0" => Nominal field inport may only be tested for
>>>     equality (taking enclosing `!' operators into account).
>>>     -!(inport == "eth0") => Nominal field inport may only be tested
>>>     for equality (taking enclosing `!' operators into account).
>>>     -eth.type != 0x800 => Nominal field eth.type may only be tested
>>>     for equality (taking enclosing `!' operators into account).
>>>     -!(eth.type == 0x800) => Nominal field eth.type may only be tested
>>>     for equality (taking enclosing `!' operators into account).
>>>     -inport = "eth0" => Syntax error at `=' expecting relational 
>>> operator.
>>>     -
>>>     -123 == 123 => Syntax error at `123' expecting field name.
>>>     -
>>>     -$name => Syntax error at `$name' expecting address set name.
>>>     -@name => Syntax error at `@name' expecting port group name.
>>>     -
>>>     -123 == xyzzy => Syntax error at `xyzzy' expecting field name.
>>>     -xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
>>>     -
>>>     -inport[1] == 1 => Cannot select subfield of string field inport.
>>>     -
>>>     -eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
>>>     -eth.type[::1] == 1 => Syntax error at `::1' expecting small 
>>> integer.
>>>     -eth.type[18446744073709551615] == 1 => Syntax error at
>>>     `18446744073709551615' expecting small integer.
>>>     -
>>>     -eth.type[5!] => Syntax error at `!' expecting `@:>@'.
>>>     -
>>>     -eth.type[5..1] => Invalid bit range 5 to 1.
>>>     -
>>>     -eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field
>>>     eth.type.
>>>     -
>>>     -eth.type[10] == 1 => Cannot select subfield of nominal field
>>>     eth.type.
>>>     -
>>>     -eth.type => Explicit `!= 0' is required for inequality test of
>>>     multibit field against 0.
>>>     -
>>>     -!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test
>>>     of multibit field against 0.
>>>     -
>>>     -123 => Syntax error at end of input expecting relational operator.
>>>     -
>>>     -123 x => Syntax error at `x' expecting relational operator.
>>>     -
>>>     -{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
>>>     -
>>>     -eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
>>>     -
>>>     -(1 x) => Syntax error at `x' expecting `)'.
>>>     -
>>>     -!0x800 != eth.type => Missing parentheses around operand of !.
>>>     -
>>>     -eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => &&
>>>     and || must be parenthesized when used together.
>>>     -
>>>     -eth.dst == {} => Syntax error at `}' expecting constant.
>>>     -
>>>     -eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and !=
>>>     operators may be used with masked constants. Consider using
>>>     subfields instead (e.g. eth.src[0..15] > 0x1111 in place of
>>>     eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
>>>     -
>>>     -ip4.src == ::1 => 128-bit constant is not compatible with 32-bit
>>>     field ip4.src.
>>>     -
>>>     -1 == eth.type == 2 => Range expressions must have the form `x <
>>>     field < y' or `x > field > y', with each `<' optionally replaced
>>>     by `<=' or `>' by `>=').
>>>     -
>>>     -eth.dst[40] x => Syntax error at `x' expecting end of input.
>>>     -
>>>     -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at
>>>     `$unknownset' expecting address set name.
>>>     -eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at
>>>     `badmac' expecting constant.
>>>     -
>>> -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>>
>>>     => Parentheses nested too deeply.
>>>     -
>>>     -ct_label > $set4 => Only == and != operators may be used to
>>>     compare a field against an empty value set.
>>>     -]])
>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>     -sed 's/.* => //' test-cases.txt > expout
>>>     -AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- expression annotation])
>>>     -dnl Input precedes =>, expected output follows =>.
>>>     -dnl Empty lines and lines starting with # are ignored.
>>>     -AT_DATA([test-cases.txt], [[
>>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
>>>     -ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
>>>     -ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 ||
>>>     eth.type == 0x86dd)
>>>     -ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea)
>>>     && (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304
>>>     && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
>>>     -
>>>     -# Nested expressions over a single symbol should be annotated
>>>     with symbol's
>>>     -# prerequisites only once, at the top level.
>>>     -tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1
>>>     || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 &&
>>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -
>>>     -ip => eth.type == 0x800 || eth.type == 0x86dd
>>>     -ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>>     -ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>>     -ip > 0 => Only == and != operators may be used with nominal 
>>> field ip.
>>>     -!ip => Nominal predicate ip may only be tested positively, e.g.
>>>     `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>>     -ip == 0 => Nominal predicate ip may only be tested positively,
>>>     e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>>     -
>>>     -vlan.present => vlan.tci[12]
>>>     -!vlan.present => !vlan.tci[12]
>>>     -
>>>     -!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
>>>     -vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 &&
>>>     vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
>>>     -!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 &&
>>>     xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
>>>     -
>>>     -ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type ==
>>>     0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 
>>> 0x86dd))
>>>     -!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type
>>>     != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>>     0x86dd))
>>>     -ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>>     0x86dd)
>>>     -
>>>     -bad_prereq != 0 => Error parsing expression `xyzzy' encountered
>>>     as prerequisite or predicate of initial expression: Syntax error
>>>     at `xyzzy' expecting field name.
>>>     -self_recurse != 0 => Error parsing expression `self_recurse != 0'
>>>     encountered as prerequisite or predicate of initial expression:
>>>     Recursive expansion of symbol `self_recurse'.
>>>     -mutual_recurse_1 != 0 => Error parsing expression
>>>     `mutual_recurse_2 != 0' encountered as prerequisite or predicate
>>>     of initial expression: Error parsing expression `mutual_recurse_1
>>>     != 0' encountered as prerequisite or predicate of initial
>>>     expression: Recursive expansion of symbol `mutual_recurse_1'.
>>>     -mutual_recurse_2 != 0 => Error parsing expression
>>>     `mutual_recurse_1 != 0' encountered as prerequisite or predicate
>>>     of initial expression: Error parsing expression `mutual_recurse_2
>>>     != 0' encountered as prerequisite or predicate of initial
>>>     expression: Recursive expansion of symbol `mutual_recurse_2'.
>>>     -]])
>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>     -sed 's/.* => //' test-cases.txt > expout
>>>     -AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], 
>>> [expout])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 1-term expression conversion])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
>>>     -  [Tested converting all 1-terminal expressions with 2 numeric
>>>     vars (each 3 bits) in terms of operators == != < <= > >= and 2
>>>     string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2-term expression conversion])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
>>>     -  [Tested converting 578 expressions of 2 terminals with 2
>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>>     and 2 string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 3-term expression conversion])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert
>>>     --bits=2 3], [0],
>>>     -  [Tested converting 67410 expressions of 3 terminals with 2
>>>     numeric vars (each 2 bits) in terms of operators == != < <= > >=
>>>     and 2 string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 3-term numeric expression simplification])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>     --nvars=2 --svars=0 3], [0],
>>>     -  [Tested simplifying 490770 expressions of 3 terminals with 2
>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term string expression simplification])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>     --nvars=0 --svars=4 4], [0],
>>>     -  [Tested simplifying 21978 expressions of 4 terminals with 4
>>>     string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 3-term mixed expression simplification])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>     --nvars=1 --svars=1 3], [0],
>>>     -  [Tested simplifying 127890 expressions of 3 terminals with 1
>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>>     and 1 string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- simplification special cases])
>>>     -simplify() {
>>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>>     -}
>>>     -AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
>>>     -])
>>>     -AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
>>>     -])
>>>     -AT_CHECK([simplify 'tcp.dst >= 0'], [0],
>>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -])
>>>     -AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
>>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -])
>>>     -AT_CHECK([simplify 'tcp.dst > 0'], [0],
>>>     -    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] ||
>>>     tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8]
>>>     || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] ||
>>>     tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 &&
>>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -]])
>>>     -AT_CHECK([simplify 'tcp.dst < 65535'], [0],
>>>     -    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3]
>>>     || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] ||
>>>     !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] ||
>>>     !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) &&
>>>     ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>     -]])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- is_chassis_resident simplification])
>>>     -simplify() {
>>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>>     -}
>>>     -AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
>>>     -])
>>>     -AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
>>>     -])
>>>     -AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
>>>     -])
>>>     -AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term numeric expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=3 --svars=0 --bits=1 4], [0],
>>>     -  [Tested normalizing 1874026 expressions of 4 terminals with 3
>>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term string expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=0 --svars=3 --bits=1 4], [0],
>>>     -  [Tested normalizing 11242 expressions of 4 terminals with 3
>>>     string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term mixed expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=1 --bits=1 --svars=2 4], [0],
>>>     -  [Tested normalizing 175978 expressions of 4 terminals with 1
>>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=
>>>     and 2 string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 5-term numeric expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
>>>     -  [Tested normalizing 1317600 expressions of 5 terminals with 3
>>>     numeric vars (each 1 bits) in terms of operators ==.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 5-term string expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
>>>     -  [Tested normalizing 368550 expressions of 5 terminals with 3
>>>     string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 5-term mixed expression normalization])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>     --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
>>>     -  [Tested normalizing 216000 expressions of 5 terminals with 1
>>>     numeric vars (each 1 bits) in terms of operators == and 1 string 
>>> vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term numeric expressions to flows])
>>>     -AT_KEYWORDS([expression])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2
>>>     --svars=0 --bits=2 --relops='==' 4], [0],
>>>     -  [Tested converting to flows 175978 expressions of 4 terminals
>>>     with 2 numeric vars (each 2 bits) in terms of operators ==.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term string expressions to flows])
>>>     -AT_KEYWORDS([expression])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0
>>>     --svars=4 4], [0],
>>>     -  [Tested converting to flows 21978 expressions of 4 terminals
>>>     with 4 string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4-term mixed expressions to flows])
>>>     -AT_KEYWORDS([expression])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1
>>>     --bits=2 --svars=1 --relops='==' 4], [0],
>>>     -  [Tested converting to flows 48312 expressions of 4 terminals
>>>     with 1 numeric vars (each 2 bits) in terms of operators == and 1
>>>     string vars.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 3-term numeric expressions to flows])
>>>     -AT_KEYWORDS([expression])
>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3
>>>     --svars=0 --bits=3 --relops='==' 3], [0],
>>>     -  [Tested converting to flows 41328 expressions of 3 terminals
>>>     with 3 numeric vars (each 3 bits) in terms of operators ==.
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- converting expressions to flows -- string 
>>> fields])
>>>     -AT_KEYWORDS([expression])
>>>     -expr_to_flow () {
>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>     -}
>>>     -AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
>>>     -ip,reg14=0x5
>>>     -ipv6,reg14=0x5
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
>>>     -ip,reg14=0x6
>>>     -ipv6,reg14=0x6
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2",
>>>     "LOCAL"}'], [0],
>>>     -[reg14=0x5
>>>     -reg14=0x6
>>>     -reg14=0xfffe
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} &&
>>>     ip'], [0], [dnl
>>>     -ip,reg14=0x5
>>>     -ip,reg14=0x6
>>>     -ipv6,reg14=0x5
>>>     -ipv6,reg14=0x6
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'],
>>>     [0], [dnl
>>>     -(no flows)
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- converting expressions to flows -- address sets])
>>>     -AT_KEYWORDS([expression])
>>>     -expr_to_flow () {
>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>     -}
>>>     -AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2,
>>>     10.0.0.3}'], [0], [dnl
>>>     -ip,nw_src=10.0.0.1
>>>     -ip,nw_src=10.0.0.2
>>>     -ip,nw_src=10.0.0.3
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
>>>     -ip,nw_src=10.0.0.1
>>>     -ip,nw_src=10.0.0.2
>>>     -ip,nw_src=10.0.0.3
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
>>>     -ip,nw_src=1.2.3.4
>>>     -ip,nw_src=10.0.0.1
>>>     -ip,nw_src=10.0.0.2
>>>     -ip,nw_src=10.0.0.3
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20
>>>     <http://1.2.0.0/20>, 5.5.5.0/24 <http://5.5.5.0/24>, $set1}'],
>>>     [0], [dnl
>>>     -ip,nw_src=1.2.0.0/20 <http://1.2.0.0/20>
>>>     -ip,nw_src=10.0.0.1
>>>     -ip,nw_src=10.0.0.2
>>>     -ip,nw_src=10.0.0.3
>>>     -ip,nw_src=5.5.5.0/24 <http://5.5.5.0/24>
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
>>>     -ipv6,ipv6_src=::1
>>>     -ipv6,ipv6_src=::2
>>>     -ipv6,ipv6_src=::3
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
>>>     -ipv6,ipv6_src=::1
>>>     -ipv6,ipv6_src=::2
>>>     -ipv6,ipv6_src=::3
>>>     -ipv6,ipv6_src=::4
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01,
>>>     00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
>>>     -dl_src=00:00:00:00:00:01
>>>     -dl_src=00:00:00:00:00:02
>>>     -dl_src=00:00:00:00:00:03
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
>>>     -dl_src=00:00:00:00:00:01
>>>     -dl_src=00:00:00:00:00:02
>>>     -dl_src=00:00:00:00:00:03
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3,
>>>     ba:be:be:ef:de:ad, $set3}'], [0], [dnl
>>>     -dl_src=00:00:00:00:00:01
>>>     -dl_src=00:00:00:00:00:02
>>>     -dl_src=00:00:00:00:00:03
>>>     -dl_src=ba:be:be:ef:de:ad
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
>>>     -(no flows)
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
>>>     -ip,nw_src=1.2.3.4
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src ==
>>>     {$set4}'], [0], [dnl
>>>     -ip,nw_src=1.2.3.4
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
>>>     -
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8 <http://1.0.0.0/8>,
>>>     $set4}'], [0], [dnl
>>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 <http://1.0.0.0/8>
>>>     && ip4.src != {$set4}'], [0], [dnl
>>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- converting expressions to flows -- port groups])
>>>     -AT_KEYWORDS([expression])
>>>     -expr_to_flow () {
>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>     -}
>>>     -AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
>>>     -reg15=0x11
>>>     -reg15=0x12
>>>     -reg15=0x13
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
>>>     -(no flows)
>>>     -])
>>>     -AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], 
>>> [dnl
>>>     -reg15=0x11
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- converting expressions to flows -- conjunction])
>>>     -AT_KEYWORDS([conjunction])
>>>     -expr_to_flow () {
>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>     -}
>>>     -
>>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>     -conj_id=1,ip
>>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>>     -ip,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/2)
>>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>>     -])
>>>     -
>>>     -lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>     -ct_state=+est+trk,ct_label=0x1/0x1,ip
>>>     -ct_state=+est+trk,ct_label=0x1/0x1,ipv6
>>>     -ct_state=-est+trk,ip
>>>     -ct_state=-est+trk,ipv6
>>>     -])
>>>     -
>>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>     -ip4.dst == {20.0.0.1, 20.0.0.2}"
>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>     -conj_id=1,ip
>>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>>     -])
>>>     -
>>>     -lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
>>>     -tcp.dst >= 1000 && tcp.dst <= 1010"
>>>     -
>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>     -conj_id=1,tcp
>>>     -tcp,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/3)
>>>     -tcp,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/3)
>>>     -tcp,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/3)
>>>     -tcp,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/3)
>>>     -tcp,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/3)
>>>     -tcp,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/3)
>>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
>>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
>>>     -tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
>>>     -tcp,tp_dst=1000: conjunction(1, 2/3)
>>>     -tcp,tp_dst=1001: conjunction(1, 2/3)
>>>     -tcp,tp_dst=1010: conjunction(1, 2/3)
>>>     -])
>>>     -
>>>     -lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
>>>     -((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 
>>> && \
>>>     -tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
>>>     -|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
>>>     -
>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>     -conj_id=1,tcp
>>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
>>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
>>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
>>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
>>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
>>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
>>>     -tcp,nw_dst=20.0.0.4 <http://20.0.0.4>: conjunction(1, 0/4)
>>>     -tcp,nw_dst=20.0.0.7 <http://20.0.0.7>: conjunction(1, 0/4)
>>>     -tcp,nw_dst=20.0.0.8 <http://20.0.0.8>: conjunction(1, 0/4)
>>>     -tcp,nw_src=10.0.0.4 <http://10.0.0.4>: conjunction(1, 1/4)
>>>     -tcp,nw_src=10.0.0.5 <http://10.0.0.5>: conjunction(1, 1/4)
>>>     -tcp,nw_src=10.0.0.6 <http://10.0.0.6>: conjunction(1, 1/4)
>>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
>>>     -tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
>>>     -tcp,tp_dst=1000: conjunction(1, 2/4)
>>>     -tcp,tp_dst=1001: conjunction(1, 2/4)
>>>     -tcp,tp_dst=2000: conjunction(1, 2/4)
>>>     -tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
>>>     -tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
>>>     -tcp,tp_src=1000: conjunction(1, 3/4)
>>>     -tcp,tp_src=1001: conjunction(1, 3/4)
>>>     -tcp,tp_src=2000: conjunction(1, 3/4)
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- action parsing])
>>>     -dnl Unindented text is input (a set of OVN logical actions).
>>>     -dnl Indented text is expected output.
>>>     -AT_DATA([test-cases.txt],
>>>     -[[# drop
>>>     -drop;
>>>     -    encodes as drop
>>>     -drop; next;
>>>     -    Syntax error at `next' expecting end of input.
>>>     -next; drop;
>>>     -    Syntax error at `drop' expecting action.
>>>     -
>>>     -# output
>>>     -output;
>>>     -    encodes as resubmit(,64)
>>>     -
>>>     -# next
>>>     -next;
>>>     -    encodes as resubmit(,19)
>>>     -next(11);
>>>     -    formats as next;
>>>     -    encodes as resubmit(,19)
>>>     -next(0);
>>>     -    encodes as resubmit(,8)
>>>     -next(23);
>>>     -    encodes as resubmit(,31)
>>>     -
>>>     -next();
>>>     -    Syntax error at `)' expecting "pipeline" or "table".
>>>     -next(10;
>>>     -    Syntax error at `;' expecting `)'.
>>>     -next(24);
>>>     -    "next" action cannot advance beyond table 23.
>>>     -
>>>     -next(table=11);
>>>     -    formats as next;
>>>     -    encodes as resubmit(,19)
>>>     -next(pipeline=ingress);
>>>     -    formats as next;
>>>     -    encodes as resubmit(,19)
>>>     -next(table=11, pipeline=ingress);
>>>     -    formats as next;
>>>     -    encodes as resubmit(,19)
>>>     -next(pipeline=ingress, table=11);
>>>     -    formats as next;
>>>     -    encodes as resubmit(,19)
>>>     -
>>>     -next(pipeline=egress);
>>>     -    "next" action cannot advance from ingress to egress pipeline
>>>     (use "output" action instead)
>>>     -
>>>     -next(table=10);
>>>     -    formats as next(10);
>>>     -    encodes as resubmit(,18)
>>>     -
>>>     -# Loading a constant value.
>>>     -tcp.dst=80;
>>>     -    formats as tcp.dst = 80;
>>>     -    encodes as set_field:80->tcp_dst
>>>     -    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type
>>>     == 0x86dd)
>>>     -eth.dst[40] = 1;
>>>     -    encodes as 
>>> set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
>>>     -vlan.pcp = 2;
>>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>>     -    has prereqs vlan.tci[12]
>>>     -vlan.tci[13..15] = 2;
>>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>>     -inport = "";
>>>     -    encodes as set_field:0->reg14
>>>     -ip.ttl=4;
>>>     -    formats as ip.ttl = 4;
>>>     -    encodes as set_field:4->nw_ttl
>>>     -    has prereqs eth.type == 0x800 || eth.type == 0x86dd
>>>     -outport="eth0"; next; outport="LOCAL"; next;
>>>     -    formats as outport = "eth0"; next; outport = "LOCAL"; next;
>>>     -    encodes as
>>> set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
>>>     -
>>>     -inport[1] = 1;
>>>     -    Cannot select subfield of string field inport.
>>>     -ip.proto[1] = 1;
>>>     -    Cannot select subfield of nominal field ip.proto.
>>>     -eth.dst[40] == 1;
>>>     -    Syntax error at `==' expecting `=' or `<->'.
>>>     -ip = 1;
>>>     -    Predicate symbol ip used where lvalue required.
>>>     -ip.proto = 6;
>>>     -    Field ip.proto is not modifiable.
>>>     -inport = {"a", "b"};
>>>     -    Syntax error at `{' expecting constant.
>>>     -inport = {};
>>>     -    Syntax error at `{' expecting constant.
>>>     -bad_prereq = 123;
>>>     -    Error parsing expression `xyzzy' encountered as prerequisite
>>>     or predicate of initial expression: Syntax error at `xyzzy'
>>>     expecting field name.
>>>     -self_recurse = 123;
>>>     -    Error parsing expression `self_recurse != 0' encountered as
>>>     prerequisite or predicate of initial expression: Error parsing
>>>     expression `self_recurse != 0' encountered as prerequisite or
>>>     predicate of initial expression: Recursive expansion of symbol
>>>     `self_recurse'.
>>>     -vlan.present = 0;
>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>     -
>>>     -# Moving one field into another.
>>>     -reg0=reg1;
>>>     -    formats as reg0 = reg1;
>>>     -    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
>>>     -vlan.pcp = reg0[0..2];
>>>     -    encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
>>>     -    has prereqs vlan.tci[12]
>>>     -reg0[10] = vlan.pcp[1];
>>>     -    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
>>>     -    has prereqs vlan.tci[12]
>>>     -outport = inport;
>>>     -    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
>>>     -
>>>     -reg0[0] = vlan.present;
>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>     -reg0 = reg1[0..10];
>>>     -    Can't assign 11-bit value to 32-bit destination.
>>>     -inport = reg0;
>>>     -    Can't assign integer field (reg0) to string field (inport).
>>>     -inport = big_string;
>>>     -    String fields inport and big_string are incompatible for
>>>     assignment.
>>>     -ip.proto = reg0[0..7];
>>>     -    Field ip.proto is not modifiable.
>>>     -
>>>     -# Exchanging fields.
>>>     -reg0 <-> reg1;
>>>     -    encodes as
>>> push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127] 
>>>
>>>     -vlan.pcp <-> reg0[0..2];
>>>     -    encodes as
>>> push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15] 
>>>
>>>     -    has prereqs vlan.tci[12]
>>>     -reg0[10] <-> vlan.pcp[1];
>>>     -    encodes as
>>> push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106] 
>>>
>>>     -    has prereqs vlan.tci[12]
>>>     -outport <-> inport;
>>>     -    encodes as
>>> push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[] 
>>>
>>>     -
>>>     -reg0[0] <-> vlan.present;
>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>     -reg0 <-> reg1[0..10];
>>>     -    Can't exchange 32-bit field with 11-bit field.
>>>     -inport <-> reg0;
>>>     -    Can't exchange string field (inport) with integer field 
>>> (reg0).
>>>     -inport <-> big_string;
>>>     -    String fields inport and big_string are incompatible for
>>>     exchange.
>>>     -ip.proto <-> reg0[0..7];
>>>     -    Field ip.proto is not modifiable.
>>>     -reg0[0..7] <-> ip.proto;
>>>     -    Field ip.proto is not modifiable.
>>>     -
>>>     -# TTL decrement.
>>>     -ip.ttl--;
>>>     -    encodes as dec_ttl
>>>     -    has prereqs ip
>>>     -ip.ttl
>>>     -    Syntax error at end of input expecting `--'.
>>>     -
>>>     -# load balancing.
>>>     -ct_lb;
>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>>     -    has prereqs ip
>>>     -ct_lb();
>>>     -    formats as ct_lb;
>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>>     -    has prereqs ip
>>>     -ct_lb(192.168.1.2:80 <http://192.168.1.2:80>, 192.168.1.3:80
>>>     <http://192.168.1.3:80>);
>>>     -    encodes as group:1
>>>     -    has prereqs ip
>>>     -ct_lb(192.168.1.2, 192.168.1.3, );
>>>     -    formats as ct_lb(192.168.1.2, 192.168.1.3);
>>>     -    encodes as group:2
>>>     -    has prereqs ip
>>>     -ct_lb(fd0f::2, fd0f::3, );
>>>     -    formats as ct_lb(fd0f::2, fd0f::3);
>>>     -    encodes as group:3
>>>     -    has prereqs ip
>>>     -
>>>     -ct_lb(192.168.1.2:);
>>>     -    Syntax error at `)' expecting port number.
>>>     -ct_lb(192.168.1.2:123456 <http://192.168.1.2:123456>);
>>>     -    Syntax error at `123456' expecting port number.
>>>     -ct_lb(foo);
>>>     -    Syntax error at `foo' expecting IP address.
>>>     -ct_lb([192.168.1.2]);
>>>     -    Syntax error at `192.168.1.2' expecting IPv6 address.
>>>     -
>>>     -# ct_next
>>>     -ct_next;
>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
>>>     -    has prereqs ip
>>>     -
>>>     -# ct_commit
>>>     -ct_commit;
>>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>>     -    has prereqs ip
>>>     -ct_commit();
>>>     -    formats as ct_commit;
>>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>>     -    has prereqs ip
>>>     -ct_commit(ct_mark=1);
>>>     -    formats as ct_commit(ct_mark=0x1);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
>>>     -    has prereqs ip
>>>     -ct_commit(ct_mark=1/1);
>>>     -    formats as ct_commit(ct_mark=0x1/0x1);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
>>>     -    has prereqs ip
>>>     -ct_commit(ct_label=1);
>>>     -    formats as ct_commit(ct_label=0x1);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
>>>     -    has prereqs ip
>>>     -ct_commit(ct_label=1/1);
>>>     -    formats as ct_commit(ct_label=0x1/0x1);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
>>>     -    has prereqs ip
>>>     -ct_commit(ct_mark=1, ct_label=2);
>>>     -    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label)) 
>>>
>>>     -    has prereqs ip
>>>     -
>>>     -ct_commit(ct_label=0x01020304050607080910111213141516);
>>>     -    formats as 
>>> ct_commit(ct_label=0x1020304050607080910111213141516);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label)) 
>>>
>>>     -    has prereqs ip
>>> -ct_commit(ct_label=0x181716151413121110090807060504030201);
>>>     -    formats as
>>>     ct_commit(ct_label=0x16151413121110090807060504030201);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label)) 
>>>
>>>     -    has prereqs ip
>>> -ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000); 
>>>
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label)) 
>>>
>>>     -    has prereqs ip
>>>     -ct_commit(ct_label=18446744073709551615);
>>>     -    formats as ct_commit(ct_label=0xffffffffffffffff);
>>>     -    encodes as
>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label)) 
>>>
>>>     -    has prereqs ip
>>>     -ct_commit(ct_label=18446744073709551616);
>>>     -    Decimal constants must be less than 2**64.
>>>     -
>>>     -# ct_dnat
>>>     -ct_dnat;
>>>     -    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
>>>     -    has prereqs ip
>>>     -ct_dnat(192.168.1.2);
>>>     -    encodes as
>>> ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
>>>     -    has prereqs ip
>>>     -
>>>     -ct_dnat(192.168.1.2, 192.168.1.3);
>>>     -    Syntax error at `,' expecting `)'.
>>>     -ct_dnat(foo);
>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>     -ct_dnat(foo, bar);
>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>     -ct_dnat();
>>>     -    Syntax error at `)' expecting IPv4 address.
>>>     -
>>>     -# ct_snat
>>>     -ct_snat;
>>>     -    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
>>>     -    has prereqs ip
>>>     -ct_snat(192.168.1.2);
>>>     -    encodes as
>>> ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
>>>     -    has prereqs ip
>>>     -
>>>     -ct_snat(192.168.1.2, 192.168.1.3);
>>>     -    Syntax error at `,' expecting `)'.
>>>     -ct_snat(foo);
>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>     -ct_snat(foo, bar);
>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>     -ct_snat();
>>>     -    Syntax error at `)' expecting IPv4 address.
>>>     -
>>>     -# ct_clear
>>>     -ct_clear;
>>>     -    encodes as ct_clear
>>>     -
>>>     -# clone
>>>     -clone { ip4.dst = 255.255.255.255; output; }; next;
>>>     -    encodes as
>>> clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
>>>     -    has prereqs eth.type == 0x800
>>>     -
>>>     -# arp
>>>     -arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip4
>>>     -arp { };
>>>     -    formats as arp { drop; };
>>>     -    encodes as controller(userdata=00.00.00.00.00.00.00.00)
>>>     -    has prereqs ip4
>>>     -
>>>     -# get_arp
>>>     -get_arp(outport, ip4.dst);
>>>     -    encodes as
>>> push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[] 
>>>
>>>     -    has prereqs eth.type == 0x800
>>>     -get_arp(inport, reg0);
>>>     -    encodes as
>>> push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] 
>>>
>>>     -
>>>     -get_arp;
>>>     -    Syntax error at `;' expecting `('.
>>>     -get_arp();
>>>     -    Syntax error at `)' expecting field name.
>>>     -get_arp(inport);
>>>     -    Syntax error at `)' expecting `,'.
>>>     -get_arp(inport ip4.dst);
>>>     -    Syntax error at `ip4.dst' expecting `,'.
>>>     -get_arp(inport, ip4.dst;
>>>     -    Syntax error at `;' expecting `)'.
>>>     -get_arp(inport, eth.dst);
>>>     -    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is
>>>     required.
>>>     -get_arp(inport, outport);
>>>     -    Cannot use string field outport where numeric field is 
>>> required.
>>>     -get_arp(reg0, ip4.dst);
>>>     -    Cannot use numeric field reg0 where string field is required.
>>>     -
>>>     -# put_arp
>>>     -put_arp(inport, arp.spa, arp.sha);
>>>     -    encodes as
>>> push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[] 
>>>
>>>     -    has prereqs eth.type == 0x806 && eth.type == 0x806
>>>     -
>>>     -# put_dhcp_opts
>>>     -reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>>     -    encodes as
>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) 
>>>
>>>     -reg2[5] =
>>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org 
>>>
>>> <http://ovn.org>",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot"); 
>>>
>>>     -    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router
>>>     = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name =
>>>     "ovn.org <http://ovn.org>", wpad = "https://example.org",
>>>     bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix =
>>>     "/tftpboot");
>>>     -    encodes as
>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause) 
>>>
>>>     -reg0[15] =
>>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1 
>>>
>>> <http://30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1>},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5}); 
>>>
>>>     -    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4,
>>>     router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400,
>>>     ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8,
>>>     7.7.7.7}, classless_static_route = {30.0.0.0/24
>>>     <http://30.0.0.0/24>, 10.0.0.4, 40.0.0.0/16 <http://40.0.0.0/16>,
>>>     10.0.0.6, 0.0.0.0/0 <http://0.0.0.0/0>, 10.0.0.1}, ethernet_encap
>>>     = 1, router_discovery = 0, tftp_server_address = {10.0.0.4,
>>>     10.0.0.5});
>>>     -    encodes as
>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause) 
>>>
>>>     -
>>>     -reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>>     -    Cannot use 2-bit field reg1[0..1] where 1-bit field is 
>>> required.
>>>     -reg1[0] = put_dhcp_opts();
>>>     -    put_dhcp_opts requires offerip to be specified.
>>>     -reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
>>>     -    Syntax error at `x' expecting DHCPv4 option name.
>>>     -reg1[0] = put_dhcp_opts(router = 10.0.0.1);
>>>     -    put_dhcp_opts requires offerip to be specified.
>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
>>>     -    Syntax error at `"hi"'.
>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
>>>     -    Syntax error at `xyzzy' expecting DHCPv4 option name.
>>>     -reg1[0] = put_dhcp_opts(offerip="xyzzy");
>>>     -    DHCPv4 option offerip requires numeric value.
>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>>>     -    DHCPv4 option domain_name requires string value.
>>>     -
>>>     -# nd_ns
>>>     -nd_ns { nd.target = xxreg0; output; };
>>>     -    encodes as
>>> controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>
>>>     -    has prereqs ip6
>>>     -
>>>     -nd_ns { };
>>>     -    formats as nd_ns { drop; };
>>>     -    encodes as controller(userdata=00.00.00.09.00.00.00.00)
>>>     -    has prereqs ip6
>>>     -
>>>     -# nd_na
>>>     -nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc;
>>>     outport = inport; inport = ""; /* Allow sending out inport. */
>>>     output; };
>>>     -    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>>     12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>>     -    encodes as
>>> controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>
>>>     -    has prereqs nd_ns
>>>     -# nd_na_router
>>>     -nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>>     12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending
>>>     out inport. */ output; };
>>>     -    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll
>>>     = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>>     -    encodes as
>>> controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>
>>>     -    has prereqs nd_ns
>>>     -
>>>     -# get_nd
>>>     -get_nd(outport, ip6.dst);
>>>     -    encodes as
>>> push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[] 
>>>
>>>     -    has prereqs eth.type == 0x86dd
>>>     -get_nd(inport, xxreg0);
>>>     -    encodes as
>>> push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[] 
>>>
>>>     -get_nd;
>>>     -    Syntax error at `;' expecting `('.
>>>     -get_nd();
>>>     -    Syntax error at `)' expecting field name.
>>>     -get_nd(inport);
>>>     -    Syntax error at `)' expecting `,'.
>>>     -get_nd(inport ip6.dst);
>>>     -    Syntax error at `ip6.dst' expecting `,'.
>>>     -get_nd(inport, ip6.dst;
>>>     -    Syntax error at `;' expecting `)'.
>>>     -get_nd(inport, eth.dst);
>>>     -    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is
>>>     required.
>>>     -get_nd(inport, outport);
>>>     -    Cannot use string field outport where numeric field is 
>>> required.
>>>     -get_nd(xxreg0, ip6.dst);
>>>     -    Cannot use numeric field xxreg0 where string field is 
>>> required.
>>>     -
>>>     -# put_nd
>>>     -put_nd(inport, nd.target, nd.sll);
>>>     -    encodes as
>>> push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[] 
>>>
>>>     -    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) &&
>>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>>     eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd &&
>>>     ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>>     ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>>     icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a &&
>>>     (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 &&
>>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>>     eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 ||
>>>     eth.type == 0x86dd)
>>>     -
>>>     -# put_dhcpv6_opts
>>>     -reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
>>>     00:00:00:00:10:02);
>>>     -    encodes as
>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause) 
>>>
>>>     -reg1[0] = put_dhcpv6_opts();
>>>     -    encodes as
>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>>
>>>     -reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
>>>     -    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1,
>>>     ae70::2});
>>>     -    encodes as
>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>>
>>>     -reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc,
>>>     dns_server={ae70::1,ae89::2});
>>>     -    formats as reg1[0] = put_dhcpv6_opts(server_id =
>>>     12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
>>>     -    encodes as
>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>>
>>>     -reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org
>>>     <http://ovn.org>");
>>>     -    encodes as
>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause) 
>>>
>>>     -reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
>>>     -    Syntax error at `x' expecting DHCPv6 option name.
>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
>>>     -    Syntax error at `"hi"'.
>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
>>>     -    Syntax error at `xyzzy' expecting DHCPv6 option name.
>>>     -reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
>>>     -    DHCPv6 option ia_addr requires numeric value.
>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
>>>     -    DHCPv6 option domain_search requires string value.
>>>     -
>>>     -# set_queue
>>>     -set_queue(0);
>>>     -    encodes as set_queue:0
>>>     -set_queue(61440);
>>>     -    encodes as set_queue:61440
>>>     -set_queue(65535);
>>>     -    Queue ID 65535 for set_queue is not in valid range 0 to 61440.
>>>     -
>>>     -# dns_lookup
>>>     -reg1[0] = dns_lookup();
>>>     -    encodes as
>>> controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>>
>>>     -    has prereqs udp
>>>     -reg1[0] = dns_lookup("foo");
>>>     -    dns_lookup doesn't take any parameters
>>>     -
>>>     -# set_meter
>>>     -set_meter(0);
>>>     -    Rate 0 for set_meter is not in valid.
>>>     -set_meter(1);
>>>     -    encodes as meter:1
>>>     -set_meter(100, 1000);
>>>     -    encodes as meter:2
>>>     -set_meter(100, 1000, );
>>>     -    Syntax error at `,' expecting `)'.
>>>     -set_meter(4294967295, 4294967295);
>>>     -    encodes as meter:3
>>>     -
>>>     -# log
>>>     -log(verdict=allow, severity=warning);
>>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
>>>     -log(name="test1", verdict=drop, severity=info);
>>>     -    encodes as
>>> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
>>>     -log(verdict=drop, severity=info, meter="meter1");
>>>     -    encodes as
>>> controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
>>>     -log(name="test1", verdict=drop, severity=info, meter="meter1");
>>>     -    encodes as
>>> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4) 
>>>
>>>     -log(verdict=drop);
>>>     -    formats as log(verdict=drop, severity=info);
>>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
>>>     -log(verdict=bad_verdict, severity=info);
>>>     -    Syntax error at `bad_verdict' unknown verdict.
>>>     -log(verdict=drop, severity=bad_severity);
>>>     -    Syntax error at `bad_severity' unknown severity.
>>>     -log(severity=notice);
>>>     -    Syntax error at `;' expecting verdict.
>>>     -
>>>     -# put_nd_ra_opts
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>     = aef0::/64, slla = ae:01:02:03:04:05);
>>>     -    encodes as
>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause) 
>>>
>>>     -    has prereqs ip6
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla =
>>>     ae:01:02:03:04:10, mtu = 1450);
>>>     -    encodes as
>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause) 
>>>
>>>     -    has prereqs ip6
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>>     ae:01:02:03:04:06, prefix = aef0::/64);
>>>     -    encodes as
>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause) 
>>>
>>>     -    has prereqs ip6
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>     = aef0::/64);
>>>     -    slla option not present
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>>     ae:01:02:03:04:10);
>>>     -    encodes as
>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>>
>>>     -    has prereqs ip6
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>>     ae:01:02:03:04:10);
>>>     -    encodes as
>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>>
>>>     -    has prereqs ip6
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla =
>>>     ae:01:02:03:04:10);
>>>     -    prefix option needs to be set when address mode is
>>>     slaac/dhcpv6_stateless.
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>>     ae:01:02:03:04:10);
>>>     -    prefix option needs to be set when address mode is
>>>     slaac/dhcpv6_stateless.
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix =
>>>     aef0::/64, slla = ae:01:02:03:04:10);
>>>     -    Syntax error at `dhcpv6_stateless' expecting constant.
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>     = aef0::, slla = ae:01:02:03:04:10);
>>>     -    Invalid value for "prefix" option
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla =
>>>     ae:01:02:03:04:10);
>>>     -    Invalid value for "addr_mode" option
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla
>>>     = ae:01:02:03:04:10);
>>>     -    IPv6 ND RA option mtu requires numeric value.
>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4,
>>>     slla = ae:01:02:03:04:10);
>>>     -    Invalid value for "mtu" option
>>>     -
>>>     -# icmp4
>>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip4
>>>     -
>>>     -icmp4 { };
>>>     -    formats as icmp4 { drop; };
>>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>>     -    has prereqs ip4
>>>     -
>>>     -# icmp4 with icmp4.frag_mtu
>>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>>     output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip4
>>>     -
>>>     -# icmp4_error
>>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip4
>>>     -
>>>     -icmp4_error { };
>>>     -    formats as icmp4_error { drop; };
>>>     -    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
>>>     -    has prereqs ip4
>>>     -
>>>     -# icmp4_error with icmp4.frag_mtu
>>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>>     output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip4
>>>     -
>>>     -icmp4.frag_mtu = 1500;
>>>     -    encodes as
>>>     controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
>>>     -
>>>     -# icmp6
>>>     -icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs ip6
>>>     -
>>>     -icmp6 { };
>>>     -    formats as icmp6 { drop; };
>>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>>     -    has prereqs ip6
>>>     -
>>>     -# tcp_reset
>>>     -tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>     -    encodes as
>>> controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>
>>>     -    has prereqs tcp
>>>     -
>>>     -tcp_reset { };
>>>     -    formats as tcp_reset { drop; };
>>>     -    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
>>>     -    has prereqs tcp
>>>     -
>>>     -# trigger_event
>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer =
>>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>>     -    encodes as
>>> controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63) 
>>>
>>>     -
>>>     -# Testing invalid vip results in extra error messages from
>>>     socket-util.c
>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>     <http://10.0.0.1:80>", protocol = "sctp", load_balancer =
>>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>>     -    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer = "bacon");
>>>     -    Load balancer 'bacon' is not a UUID
>>>     -
>>>     -# IGMP
>>>     -igmp;
>>>     -    encodes as controller(userdata=00.00.00.10.00.00.00.00)
>>>     -
>>>     -# Contradictionary prerequisites (allowed but not useful):
>>>     -ip4.src = ip6.src[0..31];
>>>     -    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
>>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>>     -ip4.src <-> ip6.src[0..31];
>>>     -    encodes as
>>> push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[] 
>>>
>>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>>     -
>>>     -# check_pkt_larger
>>>     -reg0[0] = check_pkt_larger(1500);
>>>     -    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
>>>     -
>>>     -reg0 = check_pkt_larger(1500);
>>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>>     required.
>>>     -
>>>     -reg0 = check_pkt_larger(foo);
>>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>>     required.
>>>     -
>>>     -reg0[0] = check_pkt_larger(foo);
>>>     -    Syntax error at `foo' expecting `;'.
>>>     -
>>>     -# Miscellaneous negative tests.
>>>     -;
>>>     -    Syntax error at `;'.
>>>     -xyzzy;
>>>     -    Syntax error at `xyzzy' expecting action.
>>>     -next; 123;
>>>     -    Syntax error at `123'.
>>>     -next; xyzzy;
>>>     -    Syntax error at `xyzzy' expecting action.
>>>     -next
>>>     -    Syntax error at end of input expecting `;'.
>>>     -]])
>>>     -sed '/^[[      ]]/d' test-cases.txt > input.txt
>>>     -cp test-cases.txt expout
>>>     -AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], 
>>> [expout])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_BANNER([OVN end-to-end tests])
>>>     -
>>>     -# 3 hypervisors, one logical switch, 3 logical ports per 
>>> hypervisor
>>>     -AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
>>>     -AT_KEYWORDS([ovnarp])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Create hypervisors hv[123].
>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>     -# Add all of the vifs to a single logical switch lsw0.
>>>     -# Turn on port security on all the vifs except vif[123]1.
>>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2 3; do
>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>     -        if test $j = 1; then
>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>>     -        else
>>>     -            if test $j = 3; then
>>>     -                ip_addrs="192.168.0.$i$j
>>>     fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
>>>     -            else
>>>     -                ip_addrs="192.168.0.$i$j"
>>>     -            fi
>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>     "f0:00:00:00:00:$i$j $ip_addrs"
>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>     f0:00:00:00:00:$i$j
>>>     -        fi
>>>     -    done
>>>     -done
>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>>     inport == "lp11"' drop
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>>     outport == "lp33"' drop
>>>     -ovn-nbctl create Address_Set name=set1
>>> addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\" 
>>>
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>>     eth.src == $set1 && outport == "lp33"' drop
>>>     -
>>>     -get_lsp_uuid () {
>>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>>     -}
>>>     -
>>>     -ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid
>>>     lp22`,`get_lsp_uuid lp33`
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 &&
>>>     outport == @pg1' drop
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Make sure there is no attempt to adding duplicated flows by
>>>     ovn-controller
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv${1%?}
>>>     -}
>>>     -
>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>     for vif11.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>     -    local
>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -    hv=`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>     -
>>>     -    if test X$reply_ha = X; then
>>>     -        # Expect to receive the broadcast ARP on the other
>>>     logical switch ports
>>>     -        # if no reply is expected.
>>>     -        local i j
>>>     -        for i in 1 2 3; do
>>>     -            for j in 1 2 3; do
>>>     -                if test $i$j != $inport; then
>>>     -                    echo $request >> $i$j.expected
>>>     -                fi
>>>     -            done
>>>     -        done
>>>     -    else
>>>     -        # Expect to receive the reply, if any.
>>>     -        local
>>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>
>>>     -        echo $reply >> $inport.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send packets between all pairs of source and destination ports:
>>>     -#
>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>> switch port
>>>     -#    (except that packets destined to their input ports are 
>>> dropped).
>>>     -#
>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>     ports
>>>     -#    except the input port.
>>>     -#
>>>     -# 3. When port security is turned on, the switch drops packets
>>>     from the wrong
>>>     -#    MAC address.
>>>     -#
>>>     -# 4. The switch drops all packets with a VLAN tag.
>>>     -#
>>>     -# 5. The switch drops all packets with a multicast source
>>>     address.  (This only
>>>     -#    affects behavior when port security is turned off, since
>>>     otherwise port
>>>     -#    security would drop the packet anyway.)
>>>     -#
>>>     -# 6. The switch delivers packets with an unknown destination to
>>>     logical
>>>     -#    switch ports with "unknown" among their MAC addresses (and 
>>> port
>>>     -#    security disabled).
>>>     -#
>>>     -# 7. The switch drops unicast packets that violate an ACL.
>>>     -#
>>>     -# 8. The switch drops multicast and broadcast packets that
>>>     violate an ACL.
>>>     -#
>>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>>     except for
>>>     -#    requests from a port for the port's own IP.
>>>     -#
>>>     -# 10. No response to ARP requests for unknown IPs.
>>>     -
>>>     -for is in 1 2 3; do
>>>     -    for js in 1 2 3; do
>>>     -        s=$is$js
>>>     -        bcast=
>>>     -        unknown=
>>>     -        bacl2=
>>>     -        bacl3=
>>>     -        for id in 1 2 3; do
>>>     -            for jd in 1 2 3; do
>>>     -                d=$id$jd
>>>     -
>>>     -                if test $d != $s; then unicast=$d; else 
>>> unicast=; fi
>>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>>     $unicast     #1
>>>     -
>>>     -                if test $d != $s && test $js = 1; then
>>>     -                    impersonate=$d
>>>     -                else
>>>     -                    impersonate=
>>>     -                fi
>>>     -                test_packet $s f000000000$d f00000000055 55$d
>>>     $impersonate #3
>>>     -
>>>     -                if test $d != $s && test $s != 11; then acl2=$d;
>>>     else acl2=; fi
>>>     -                if test $d != $s && test $d != 33; then acl3=$d;
>>>     else acl3=; fi
>>>     -                if test $d = $s || (test $js = 1 && test $d =
>>>     33); then
>>>     -                    # Source of 11, 21, or 31 and dest of 33
>>>     should be dropped
>>>     -                    # due to the 4th ACL that uses 
>>> address_set(set1).
>>>     -                    acl4=
>>>     -                else
>>>     -                    acl4=$d
>>>     -                fi
>>>     -                if test $d = $s || test $d = 22 || test $d = 
>>> 33; then
>>>     -                    # dest of 22 and 33 should be dropped
>>>     -                    # due to the 5th ACL that uses 
>>> port_group(pg1).
>>>     -                    acl5=
>>>     -                else
>>>     -                    acl5=$d
>>>     -                fi
>>>     -                test_packet $s f000000000$d f000000000$s 1234
>>>         #7, acl1
>>>     -                test_packet $s f000000000$d f000000000$s 1235
>>>     $acl2  #7, acl2
>>>     -                test_packet $s f000000000$d f000000000$s 1236
>>>     $acl3  #7, acl3
>>>     -                test_packet $s f000000000$d f000000000$s 1237
>>>     $acl4  #7, acl4
>>>     -                test_packet $s f000000000$d f000000000$s 1238
>>>     $acl5  #7, acl5
>>>     -
>>>     -                test_packet $s f000000000$d f00000000055
>>>     810000091234      #4
>>>     -                test_packet $s f000000000$d 0100000000$s $s$d
>>>               #5
>>>     -
>>>     -                if test $d != $s && test $jd = 1; then
>>>     -                    unknown="$unknown $d"
>>>     -                fi
>>>     -                bcast="$bcast $unicast"
>>>     -                bacl2="$bacl2 $acl2"
>>>     -                bacl3="$bacl3 $acl3"
>>>     -
>>>     -                sip=`ip_to_hex 192 168 0 $is$js`
>>>     -                tip=`ip_to_hex 192 168 0 $id$jd`
>>>     -                tip_unknown=`ip_to_hex 11 11 11 11`
>>>     -                if test $d != $s; then
>>>     -                    reply_ha=f000000000$d
>>>     -                else
>>>     -                    reply_ha=
>>>     -                fi
>>>     -                test_arp $s f000000000$s $sip $tip $reply_ha
>>>              #9
>>>     -                test_arp $s f000000000$s $sip $tip_unknown
>>>              #10
>>>     -
>>>     -                if test $jd = 3; then
>>>     -                    # lsp[123]3 has an additional ip
>>>     192.169.0.[123]3.
>>>     -                    tip=`ip_to_hex 192 169 0 $id$jd`
>>>     -                    test_arp $s f000000000$s $sip $tip $reply_ha
>>>              #9
>>>     -                fi
>>>     -            done
>>>     -        done
>>>     -
>>>     -        # Broadcast and multicast.
>>>     -        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast
>>>              #2
>>>     -        test_packet $s 010000000000 f000000000$s ${s}ff $bcast
>>>              #2
>>>     -        if test $js = 1; then
>>>     -            bcast_impersonate=$bcast
>>>     -        else
>>>     -            bcast_impersonate=
>>>     -        fi
>>>     -        test_packet $s 010000000000 f00000000044 44ff
>>>     $bcast_impersonate   #3
>>>     -
>>>     -        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown
>>>              #6
>>>     -
>>>     -        test_packet $s ffffffffffff f000000000$s 1234
>>>     #8, acl1
>>>     -        test_packet $s ffffffffffff f000000000$s 1235 $bacl2
>>>        #8, acl2
>>>     -        test_packet $s ffffffffffff f000000000$s 1236 $bacl3
>>>        #8, acl3
>>>     -        test_packet $s 010000000000 f000000000$s 1234
>>>     #8, acl1
>>>     -        test_packet $s 010000000000 f000000000$s 1235 $bacl2
>>>        #8, acl2
>>>     -        test_packet $s 010000000000 f000000000$s 1236 $bacl3
>>>        #8, acl3
>>>     -    done
>>>     -done
>>>     -
>>>     -# set address for lp13 with invalid characters.
>>>     -# lp13 should be configured with only 192.168.0.13.
>>>     -ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13
>>>     invalid 192.169.0.13"
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 11`
>>>     -tip=`ip_to_hex 192 168 0 13`
>>>     -test_arp 11 f00000000011  $sip $tip f00000000013
>>>     -
>>>     -tip=`ip_to_hex 192 169 0 13`
>>>     -#arp request for 192.169.0.13 should be flooded
>>>     -test_arp 11 f00000000011  $sip $tip
>>>     -
>>>     -# dump information and flows with counters
>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv3 dump ------"
>>>     -as hv3 ovs-vsctl show
>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# 2 hypervisors, one logical switch, 2 logical ports per 
>>> hypervisor
>>>     -# logical ports bound to chassis encap-ip.
>>>     -AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
>>>     -AT_KEYWORDS([ovnarp])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Create hypervisors hv[12].
>>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2; do
>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>     -        ip_addrs="192.168.0.$i$j"
>>>     -        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
>>>     $ip_addrs"
>>>     -        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j
>>>     f0:00:00:00:00:$i$j
>>>     -    done
>>>     -done
>>>     -
>>>     -get_lsp_uuid () {
>>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>>     -}
>>>     -
>>>     -# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just
>>>     do it
>>>     -# explictly
>>>     -
>>>     -# For Chassis hv1
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp11], [0], [dnl
>>>     -encap               : [[]]
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp12], [0], [dnl
>>>     -encap               : [[]]
>>>     -])
>>>     -
>>>     -# For Chassis hv2
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp21], [0], [dnl
>>>     -encap               : [[]]
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp22], [0], [dnl
>>>     -encap               : [[]]
>>>     -])
>>>     -
>>>     -# Bind the ports to the encap-ip
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        as hv$i
>>>     -        ovs-vsctl set Interface vif$i$j
>>>     external-ids:encap-ip=192.168.0.$i
>>>     -    done
>>>     -done
>>>     -
>>>     -sleep 1
>>>     -
>>>     -# dump port bindings; since we have vxlan and geneve tunnels, we
>>>     expect the
>>>     -# ports to be bound to geneve tunnels.
>>>     -
>>>     -# For Chassis 1
>>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>>     encap chassis_name=hv1 type=geneve ip=192.168.0.1`
>>>     -
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp11], [0], [dnl
>>>     -encap               : ${encap_rec}
>>>     -])
>>>     -
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp12], [0], [dnl
>>>     -encap               : ${encap_rec}
>>>     -])
>>>     -
>>>     -# For Chassis 2
>>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>>     encap chassis_name=hv2 type=geneve ip=192.168.0.2`
>>>     -
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp21], [0], [dnl
>>>     -encap               : ${encap_rec}
>>>     -])
>>>     -
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>     lp22], [0], [dnl
>>>     -encap               : ${encap_rec}
>>>     -])
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Make sure there is no attempt to adding duplicated flows by
>>>     ovn-controller
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv${1%?}
>>>     -}
>>>     -
>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>     for vif11.
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send packets between all pairs of source and destination ports:
>>>     -#
>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>> switch port
>>>     -#    (except that packets destined to their input ports are 
>>> dropped).
>>>     -
>>>     -for is in 1 2; do
>>>     -    for js in 1 2; do
>>>     -        s=$is$js
>>>     -        bcast=
>>>     -        unknown=
>>>     -        bacl2=
>>>     -        bacl3=
>>>     -        for id in 1 2 3; do
>>>     -            for jd in 1 2 3; do
>>>     -                d=$id$jd
>>>     -
>>>     -                if test $d != $s; then unicast=$d; else 
>>> unicast=; fi
>>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>>     $unicast     #1
>>>     -            done
>>>     -        done
>>>     -
>>>     -    done
>>>     -done
>>>     -
>>>     -# dump information and flows with counters
>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv3 dump ------"
>>>     -as hv3 ovs-vsctl show
>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Create a logical switch and some logical ports.
>>>     -# Turn on port security on all lports except ls1.
>>>     -# Make ls1 a destination for unknown MACs.
>>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>>     -ovn-nbctl ls-add lsw0
>>>     -ovn-sbctl chassis-add hv0 geneve 127.0.0.1
>>>     -for i in 1 2 3; do
>>>     -    ovn-nbctl lsp-add lsw0 lp$i
>>>     -done
>>>     -ovn-nbctl --wait=sb sync
>>>     -for i in 1 2 3; do
>>>     -    ovn-sbctl lsp-bind lp$i hv0
>>>     -    if test $i = 1; then
>>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>>     192.168.0.$i" unknown
>>>     -    else
>>>     -        if test $i = 3; then
>>>     -           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64
>>>     192.169.0.$i"
>>>     -        else
>>>     -           ip_addrs="192.168.0.$i"
>>>     -        fi
>>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>>     $ip_addrs"
>>>     -        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
>>>     -    fi
>>>     -done
>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>>     inport == "lp1"' drop
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>>     outport == "lp3"' drop
>>>     -ovn-nbctl create Address_Set name=set1
>>>     addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>>     eth.src == $set1 && outport == "lp3"' drop
>>>     -
>>>     -ovn-nbctl --wait=sb sync
>>>     -on_exit 'kill `cat ovn-trace.pid`'
>>>     -ovn-trace --detach --pidfile --no-chdir
>>>     -
>>>     -# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>     for vif11.
>>>     -test_packet() {
>>>     -    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst &&
>>>     eth.src==$eth_src"
>>>     -    while :; do
>>>     -        case $1 in # (
>>>     -            -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; 
>>> # (
>>>     -            -eth) uflow="$uflow && eth.type == 0x$2"; shift;
>>>     shift ;; # (
>>>     -            *) break ;;
>>>     -        esac
>>>     -    done
>>>     -    for outport; do
>>>     -        echo "output(\"lp$outport\");"
>>>     -    done > expout
>>>     -
>>>     -    AT_CAPTURE_FILE([trace])
>>>     -    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" |
>>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>>     -}
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>     -
>>>     -    local request="inport == \"lp$inport\"
>>>     -                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src 
>>> == $sha
>>>     -                   && arp.op == 1 && arp.sha == $sha && arp.spa
>>>     == $spa
>>>     -                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa ==
>>>     $tpa"
>>>     -
>>>     -    if test -z "$reply_ha"; then
>>>     -        reply=
>>>     -        local i
>>>     -        for i in 1 2 3; do
>>>     -            if test $i != $inport; then
>>>     -                reply="${reply}output(\"lp$i\");
>>>     -"
>>>     -            fi
>>>     -        done
>>>     -    else
>>>     -        reply="\
>>>     -eth.dst = $sha;
>>>     -eth.src = $reply_ha;
>>>     -arp.op = 2;
>>>     -arp.tha = $sha;
>>>     -arp.sha = $reply_ha;
>>>     -arp.tpa = $spa;
>>>     -arp.spa = $tpa;
>>>     -output(\"lp$inport\");
>>>     -"
>>>     -    fi
>>>     -
>>>     -    AT_CAPTURE_FILE([trace])
>>>     -    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0
>>>     "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
>>>     -}
>>>     -
>>>     -# Send packets between all pairs of source and destination ports:
>>>     -#
>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>> switch port
>>>     -#    (except that packets destined to their input ports are 
>>> dropped).
>>>     -#
>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>     ports
>>>     -#    except the input port.
>>>     -#
>>>     -# 3. When port security is turned on, the switch drops packets
>>>     from the wrong
>>>     -#    MAC address.
>>>     -#
>>>     -# 4. The switch drops all packets with a VLAN tag.
>>>     -#
>>>     -# 5. The switch drops all packets with a multicast source
>>>     address.  (This only
>>>     -#    affects behavior when port security is turned off, since
>>>     otherwise port
>>>     -#    security would drop the packet anyway.)
>>>     -#
>>>     -# 6. The switch delivers packets with an unknown destination to
>>>     logical
>>>     -#    switch ports with "unknown" among their MAC addresses (and 
>>> port
>>>     -#    security disabled).
>>>     -#
>>>     -# 7. The switch drops unicast packets that violate an ACL.
>>>     -#
>>>     -# 8. The switch drops multicast and broadcast packets that
>>>     violate an ACL.
>>>     -#
>>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>>     except for
>>>     -#    requests from a port for the port's own IP.
>>>     -#
>>>     -# 10. No response to ARP requests for unknown IPs.
>>>     -
>>>     -for s in 1 2 3; do
>>>     -    bcast=
>>>     -    unknown=
>>>     -    bacl2=
>>>     -    bacl3=
>>>     -    for d in 1 2 3; do
>>>     -        echo
>>>     -        echo "lp$s -> lp$d"
>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s
>>>     $unicast      #1
>>>     -
>>>     -        if test $d != $s && test $s = 1; then
>>>     -            impersonate=$d
>>>     -        else
>>>     -            impersonate=
>>>     -        fi
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>>     $impersonate   #3
>>>     -
>>>     -        if test $d != $s && test $s != 1; then acl2=$d; else
>>>     acl2=; fi
>>>     -        if test $d != $s && test $d != 3; then acl3=$d; else
>>>     acl3=; fi
>>>     -        if test $d = $s || ( (test $s = 1 || test $s = 2) && test
>>>     $d = 3); then
>>>     -            # Source of 1 or 2 and dest of 3 should be dropped
>>>     -            # due to the 4th ACL that uses address_set(set1).
>>>     -            acl4=
>>>     -        else
>>>     -            acl4=$d
>>>     -        fi
>>>     -
>>>     -        #7, acl1 to acl4:
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>     1234
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>     1235 $acl2
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>     1236 $acl3
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>     1237 $acl4
>>>     -
>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>>     -vlan          #4
>>>     -        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s
>>>              #5
>>>     -
>>>     -        if test $d != $s && test $d = 1; then
>>>     -            unknown="$unknown $d"
>>>     -        fi
>>>     -        bcast="$bcast $unicast"
>>>     -        bacl2="$bacl2 $acl2"
>>>     -        bacl3="$bacl3 $acl3"
>>>     -
>>>     -        sip=192.168.0.$s
>>>     -        tip=192.168.0.$d
>>>     -        tip_unknown=11.11.11.11
>>>     -        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else
>>>     reply_ha=; fi
>>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>>              #9
>>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown
>>>            #10
>>>     -
>>>     -        if test $d = 3; then
>>>     -            # lp3 has an additional ip 192.169.0.[123]3.
>>>     -            tip=192.169.0.$d
>>>     -            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>>              #9
>>>     -        fi
>>>     -    done
>>>     -
>>>     -    # Broadcast and multicast.
>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast
>>>              #2
>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast
>>>              #2
>>>     -    if test $s = 1; then
>>>     -       bcast_impersonate=$bcast
>>>     -    else
>>>     -       bcast_impersonate=
>>>     -    fi
>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44
>>>     $bcast_impersonate  #3
>>>     -
>>>     -    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown
>>>              #6
>>>     -
>>>     -    #8, acl1 to acl3:
>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235
>>>     $bacl2
>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236
>>>     $bacl3
>>>     -
>>>     -    #8, acl1 to acl3:
>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235
>>>     $bacl2
>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236
>>>     $bacl3
>>>     -done
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# 2 hypervisors, 4 logical ports per HV
>>>     -# 2 locally attached networks (one flat, one vlan tagged over
>>>     same device)
>>>     -# 2 ports per HV on each network
>>>     -AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# In this test cases we create 3 switches, all connected to same
>>>     -# physical network (through br-phys on each HV). Each switch has
>>>     -# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
>>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>>     -# lp23 means VIF 3 on hv2.
>>>     -#
>>>     -# Each switch's VLAN tag and their logical switch ports are:
>>>     -#   - ls1:
>>>     -#       - untagged
>>>     -#       - ports: lp11, lp12, lp21, lp22
>>>     -#
>>>     -#   - ls2:
>>>     -#       - tagged with VLAN 101
>>>     -#       - ports: lp13, lp14, lp23, lp24
>>>     -#   - ls3:
>>>     -#       - untagged
>>>     -#       - ports: lp15, lp25
>>>     -#
>>>     -# Note: a localnet port is created for each switch to connect to
>>>     -# physical network.
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    ls_name=ls$i
>>>     -    ovn-nbctl ls-add $ls_name
>>>     -    ln_port_name=ln$i
>>>     -    if test $i -eq 2; then
>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>>     -    else
>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name
>>>     -    fi
>>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>>     -done
>>>     -
>>>     -# lsp_to_ls LSP
>>>     -#
>>>     -# Prints the name of the logical switch that contains LSP.
>>>     -lsp_to_ls () {
>>>     -    case $1 in dnl (
>>>     -        lp?[[12]]) echo ls1 ;; dnl (
>>>     -        lp?[[34]]) echo ls2 ;; dnl (
>>>     -        lp?5) echo ls3 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2 3 4 5; do
>>>     -        ovs-vsctl add-port br-int vif$i$j -- \
>>>     -            set Interface vif$i$j external-ids:iface-id=lp$i$j \
>>>     - options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>     - options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>     -                                  ofport-request=$i$j
>>>     -
>>>     -        lsp_name=lp$i$j
>>>     -        ls_name=$(lsp_to_ls $lsp_name)
>>>     -
>>>     -        ovn-nbctl lsp-add $ls_name $lsp_name
>>>     -        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
>>>     -        ovn-nbctl lsp-set-port-security $lsp_name 
>>> f0:00:00:00:00:$i$j
>>>     -
>>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` =
>>>     xup])
>>>     -    done
>>>     -done
>>>     -ovn-nbctl --wait=sb sync
>>>     -ovn-sbctl dump-flows
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -# XXX This is now the 3rd copy of these functions in this file ...
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv${1%?}
>>>     -}
>>>     -#
>>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is
>>>     specified as
>>>     -# logical switch port numbers, e.g. 11 for vif11.
>>>     -#
>>>     -# EOUT is the end-to-end output port, that is, where the packet
>>>     will end up
>>>     -# after possibly bouncing through one or more localnet ports.
>>>     LOUT is the
>>>     -# logical output port, which might be a localnet port, as seen by
>>>     ovn-trace
>>>     -# (which doesn't know what localnet ports are connected to and
>>>     therefore can't
>>>     -# figure out the end-to-end answer).
>>>     -for i in 1 2; do
>>>     -    for j in 1 2 3 4 5; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
>>>     -    echo "$@"
>>>     -
>>>     -    # First try tracing the packet.
>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>>     eth.src==$src && eth.type==0x$eth"
>>>     -    if test $lout != drop; then
>>>     -        echo "output(\"$lout\");"
>>>     -    fi > expout
>>>     -    AT_CAPTURE_FILE([trace])
>>>     -    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" |
>>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>>     -
>>>     -    # Then actually send a packet, for an end-to-end test.
>>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>>     -    hv=`vif_to_hv $inport`
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    if test $eout != drop; then
>>>     -        echo $packet >> ${eout#lp}.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -# lp11 and lp21 are on the same network (phys, untagged)
>>>     -# and on different hypervisors
>>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>>     -
>>>     -# lp11 and lp12 are on the same network (phys, untagged)
>>>     -# and on the same hypervisor
>>>     -test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
>>>     -test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
>>>     -
>>>     -# lp13 and lp23 are on the same network (phys, VLAN 101)
>>>     -# and on different hypervisors
>>>     -test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
>>>     -test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
>>>     -
>>>     -# lp13 and lp14 are on the same network (phys, VLAN 101)
>>>     -# and on the same hypervisor
>>>     -test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
>>>     -test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
>>>     -
>>>     -# lp11 and lp15 are on the same network (phys, untagged),
>>>     -# same hypervisor, and on different switches
>>>     -test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
>>>     -test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
>>>     -
>>>     -# lp11 and lp25 are on the same network (phys, untagged),
>>>     -# different hypervisors, and on different switches
>>>     -test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
>>>     -test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
>>>     -
>>>     -# Ports that should not be able to communicate
>>>     -test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
>>>     -test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
>>>     -test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
>>>     -test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
>>>     -test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
>>>     -test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
>>>     -test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
>>>     -test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
>>>     -
>>>     -# Dump a bunch of info helpful for debugging if there's a failure.
>>>     -
>>>     -echo "------ OVN dump ------"
>>>     -ovn-nbctl show
>>>     -ovn-sbctl show
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2; do
>>>     -    for j in 1 2 3 4 5; do
>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
>>>     -AT_KEYWORDS([vtep])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Configure the Northbound database
>>>     -ovn-nbctl ls-add lsw0
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp-vtep
>>>     -ovn-nbctl lsp-set-type lp-vtep vtep
>>>     -ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep
>>>     vtep-logical-switch=lsw0
>>>     -ovn-nbctl lsp-set-addresses lp-vtep unknown
>>>     -
>>>     -# lpr, lr and lrp1 are used for the ARP request handling test 
>>> only.
>>>     -ovn-nbctl lsp-add lsw0 lpr
>>>     -ovn-nbctl lr-add lr
>>>     -ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl set Logical_Switch_Port lpr type=router \
>>>     -                             options:router-port=lrp1 \
>>>     -    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
>>>     -
>>>     -
>>>     -net_add n1               # Network to connect hv1, hv2, and vtep
>>>     -net_add n2               # Network to connect vtep and hv3
>>>     -
>>>     -# Create hypervisor hv1 connected to n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>     -
>>>     -# Create hypervisor hv2 connected to n1
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>>     -
>>>     -
>>>     -# Start the vtep emulator with a leg in both networks
>>>     -sim_add vtep
>>>     -as vtep
>>>     -
>>>     -ovsdb-tool create "$ovs_base"/vtep/vtep.db
>>>     "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
>>>     -ovs-appctl -t ovsdb-server ovsdb-server/add-db
>>>     "$ovs_base"/vtep/vtep.db
>>>     -
>>>     -ovs-vsctl add-br br-phys
>>>     -net_attach n1 br-phys
>>>     -
>>>     -mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
>>>     -arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
>>>     -ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24
>>>     <http://192.168.0.3/24> >/dev/null || return 1
>>>     -ovs-appctl ovs/route/add 192.168.0.3/24 <http://192.168.0.3/24>
>>>     br-phys >/dev/null || return 1
>>>     -
>>>     -ovs-vsctl add-br br-vtep
>>>     -net_attach n2 br-vtep
>>>     -
>>>     -vtep-ctl add-ps br-vtep
>>>     -vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
>>>     -vtep-ctl add-ls lsw0
>>>     -
>>>     -start_daemon ovs-vtep br-vtep
>>>     -start_daemon ovn-controller-vtep
>>>     --vtep-db=unix:"$ovs_base"/vtep/db.sock
>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -
>>>     -OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
>>>     -
>>>     -OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode
>>>     lsw0 |
>>>     -               grep -- source`"])
>>>     -# It takes more time for the update to be processed by ovs-vtep.
>>>     -sleep 1
>>>     -
>>>     -# Add hv3 on the other side of the vtep
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -net_attach n2 br-phys
>>>     -
>>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>>     ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 1
>>>     for vif1.
>>>     -for i in 1 2 3; do
>>>     -    : > $i.expected
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>>     -    hv=hv$inport
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# Send packets between all pairs of source and destination ports:
>>>     -#
>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>> switch port
>>>     -#    (except that packets destined to their input ports are 
>>> dropped).
>>>     -#
>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>     ports
>>>     -#    except the input port.
>>>     -#
>>>     -# 3. The switch delivers packets with an unknown destination to
>>>     logical
>>>     -#    switch ports with "unknown" among their MAC addresses (and 
>>> port
>>>     -#    security disabled).
>>>     -for s in 1 2 3; do
>>>     -    bcast=
>>>     -    unknown=
>>>     -    for d in 1 2 3; do
>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>>     $unicast       #1
>>>     -
>>>     -        # The vtep (vif3) is the only one configured for "unknown"
>>>     -        if test $d != $s && test $d = 3; then
>>>     -            unknown="$unknown $d"
>>>     -        fi
>>>     -        bcast="$bcast $unicast"
>>>     -    done
>>>     -
>>>     -    # Broadcast and multicast.
>>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>>            #2
>>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>>            #2
>>>     -
>>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>>            #3
>>>     -done
>>>     -
>>>     -# ARP request should not be responded to by logical switch router
>>>     -# type arp responder on HV1 and HV2 and should reach directly to
>>>     -# vif1 and vif2
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -sha=f00000000003
>>>     -spa=`ip_to_hex 192 168 1 2`
>>>     -tpa=`ip_to_hex 192 168 1 1`
>>> -request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -as hv3 ovs-appctl netdev-dummy/receive vif3 $request
>>>     -echo $request >> 1.expected
>>>     -echo $request >> 2.expected
>>>     -
>>>     -# dump information with counters
>>>     -echo "------ OVN dump ------"
>>>     -ovn-nbctl show
>>>     -ovn-sbctl show
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv3 dump ------"
>>>     -as hv3 ovs-vsctl show
>>>     -# note: hv3 has no logical port bind, thus it should not have 
>>> br-int
>>>     -AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
>>>     -[ovs-ofctl: br-int is not a bridge or a socket
>>>     -])
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>>     -done
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1],[hv2],[vtep])
>>>     -OVN_CLEANUP_VSWITCH([hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# Similar test to "hardware GW"
>>>     -AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Configure the Northbound database
>>>     -ovn-nbctl ls-add lsw0
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp-gw
>>>     -ovn-nbctl lsp-set-type lp-gw l2gateway
>>>     -ovn-nbctl lsp-set-options lp-gw network_name=physnet1
>>>     l2gateway-chassis=hv_gw
>>>     -ovn-nbctl lsp-set-addresses lp-gw unknown
>>>     -
>>>     -net_add n1               # Network to connect hv1, hv2, and gw
>>>     -net_add n2               # Network to connect gw and hv3
>>>     -
>>>     -# Create hypervisor hv1 connected to n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>     -
>>>     -# Create hypervisor hv2 connected to n1
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>>     -
>>>     -# Create hypervisor hv_gw connected to n1 and n2
>>>     -# connect br-phys bridge to n1; connect hv-gw bridge to n2
>>>     -sim_add hv_gw
>>>     -as hv_gw
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl add-br br-phys2
>>>     -net_attach n2 br-phys2
>>>     -ovs-vsctl set open .
>>>     external_ids:ovn-bridge-mappings="physnet1:br-phys2"
>>>     -
>>>     -# Add hv3 on the other side of the GW
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -net_attach n2 br-phys
>>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>>     ofport-request=1
>>>     -
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
>>>     -for i in 1 2 3; do
>>>     -    : > $i.expected
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>>     -    hv=hv$inport
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# Send packets between all pairs of source and destination ports:
>>>     -#
>>>     -# 1. Unicast packets are delivered to exactly one lport (except
>>>     that packets
>>>     -#    destined to their input ports are dropped).
>>>     -#
>>>     -# 2. Broadcast and multicast are delivered to all lports except
>>>     the input port.
>>>     -#
>>>     -# 3. The lswitch delivers packets with an unknown destination to
>>>     lports with
>>>     -#    "unknown" among their MAC addresses (and port security
>>>     disabled).
>>>     -for s in 1 2 3 ; do
>>>     -    bcast=
>>>     -    unknown=
>>>     -    for d in 1 2 3 ; do
>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>>     $unicast       #1
>>>     -
>>>     -        # The vtep (vif3) is the only one configured for "unknown"
>>>     -        if test $d != $s && test $d = 3; then
>>>     -            unknown="$unknown $d"
>>>     -        fi
>>>     -        bcast="$bcast $unicast"
>>>     -    done
>>>     -
>>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>>            #2
>>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>>            #3
>>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>>            #4
>>>     -done
>>>     -
>>>     -echo "------ ovn-nbctl show ------"
>>>     -ovn-nbctl show
>>>     -echo "------ ovn-sbctl show ------"
>>>     -ovn-sbctl show
>>>     -
>>>     -echo "------ hv1 ------"
>>>     -as hv1 ovs-vsctl show
>>>     -echo "------ hv1 br-int ------"
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -echo "------ hv1 br-phys ------"
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>     -
>>>     -echo "------ hv2 ------"
>>>     -as hv2 ovs-vsctl show
>>>     -echo "------ hv2 br-int ------"
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -echo "------ hv2 br-phys ------"
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>     -
>>>     -echo "------ hv_gw ------"
>>>     -as hv_gw ovs-vsctl show
>>>     -echo "------ hv_gw br-phys ------"
>>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>     -echo "------ hv_gw br-phys2 ------"
>>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
>>>     -
>>>     -echo "------ hv3 ------"
>>>     -as hv3 ovs-vsctl show
>>>     -echo "------ hv3 br-phys ------"
>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>>     -done
>>>     -AT_CLEANUP
>>>     -
>>>     -# 3 hypervisors, 3 logical switches with 3 logical ports each, 1
>>>     logical router
>>>     -AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -#
>>>     -# Three logical switches ls1, ls2, ls3.
>>>     -# One logical router lr0 connected to ls[123],
>>>     -# with nine subnets, three per logical switch:
>>>     -#
>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>> <http://192.168.11.0/24>
>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>> <http://192.168.12.0/24>
>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>> <http://192.168.13.0/24>
>>>     -#    ...
>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>> <http://192.168.33.0/24>
>>>     -#
>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>     first two
>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>     -for i in 1 2 3; do
>>>     -    ovn-nbctl ls-add ls$i
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            # Add "unknown" to MAC addresses for lp?11, so
>>>     packets for
>>>     -            # MAC-IP bindings discovered via ARP later have
>>>     somewhere to go.
>>>     -            if test $j$k = 11; then unknown=unknown; else
>>>     unknown=; fi
>>>     -
>>>     -            ovn-nbctl \
>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>     192.168.$i$j.254/24
>>>     -        ovn-nbctl \
>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>     type=router \
>>>     -                             options:router-port=lrp$i$j \
>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl set Logical_Switch_Port lrp33-attachment \
>>>     -    addresses='"00:00:00:00:ff:33 192.168.33.254"'
>>>     -
>>>     -# Physical network:
>>>     -#
>>>     -# Three hypervisors hv[123].
>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>     lp?13 on hv3.
>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>     on hv3.
>>>     -# lp?3[123] all on hv3.
>>>     -
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    case $1 in dnl (
>>>     -        ?11) echo 1 ;; dnl (
>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its
>>>     logical router
>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>     -vif_to_lrp() {
>>>     -    echo ${1%?}
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its logical
>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>     -vif_to_ls() {
>>>     -    echo ${1%??}
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -done
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            hv=`vif_to_hv $i$j$k`
>>>     -                as hv$hv ovs-vsctl \
>>>     -                -- add-port br-int vif$i$j$k \
>>>     -                -- set Interface vif$i$j$k \
>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>     -                    ofport-request=$i$j$k
>>>     -        done
>>>     -    done
>>>     -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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>>     for vif123.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            : > $i$j$k.expected
>>>     -        done
>>>     -    done
>>>     -done
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    in_ls=`vif_to_ls $inport`
>>>     -    in_lrp=`vif_to_lrp $inport`
>>>     -    for outport; do
>>>     -        out_ls=`vif_to_ls $outport`
>>>     -        if test $in_ls = $out_ls; then
>>>     -            # Ports on the same logical switch receive exactly
>>>     the same packet.
>>>     -            echo $packet
>>>     -        else
>>>     -            # Routing decrements TTL and updates source and 
>>> dest MAC
>>>     -            # (and checksum).
>>>     -            out_lrp=`vif_to_lrp $outport`
>>>     -            echo
>>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -        fi >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>     -    local
>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>     -    as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $request
>>>     -
>>>     -    # Expect to receive the broadcast ARP on the other logical
>>>     switch ports if
>>>     -    # IP address is not configured to the switch patch port.
>>>     -    local i=`vif_to_ls $inport`
>>>     -    local j k
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            # 192.168.33.254 is configured to the switch patch
>>>     port for lrp33,
>>>     -            # so no ARP flooding expected for it.
>>>     -            if test $i$j$k != $inport && test $tpa != `ip_to_hex
>>>     192 168 33 254`; then
>>>     -                echo $request >> $i$j$k.expected
>>>     -            fi
>>>     -        done
>>>     -    done
>>>     -
>>>     -    # Expect to receive the reply, if any.
>>>     -    if test X$reply_ha != X; then
>>>     -        lrp=`vif_to_lrp $inport`
>>>     -        local
>>> reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>
>>>     -        echo $reply >> $inport.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>     -as hv1 ovn-sbctl list port_binding
>>>     -as hv1 ovn-sbctl list datapath_binding
>>>     -as hv1 ovn-sbctl dump-flows
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Send IP packets between all pairs of source and destination 
>>> ports:
>>>     -#
>>>     -# 1. Unicast IP packets are delivered to exactly one logical
>>>     switch port
>>>     -#    (except that packets destined to their input ports are 
>>> dropped).
>>>     -#
>>>     -# 2. Broadcast IP packets are delivered to all logical switch 
>>> ports
>>>     -#    except the input port.
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -for is in 1 2 3; do
>>>     -  for js in 1 2 3; do
>>>     -    for ks in 1 2 3; do
>>>     -      bcast=
>>>     -      s=$is$js$ks
>>>     -      smac=f00000000$s
>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>     -      for id in 1 2 3; do
>>>     -          for jd in 1 2 3; do
>>>     -              for kd in 1 2 3; do
>>>     -                d=$id$jd$kd
>>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>>     -                if test $is = $id; then dmac=f00000000$d; else
>>>     dmac=00000000ff$is$js; fi
>>>     -                if test $d != $s; then unicast=$d; else 
>>> unicast=; fi
>>>     -
>>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>>     -
>>>     -                if test $id = $is && test $d != $s; then
>>>     bcast="$bcast $d"; fi
>>>     -              done
>>>     -          done
>>>     -        done
>>>     -      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
>>>     -      done
>>>     -  done
>>>     -done
>>>     -
>>>     -: > mac_bindings.expected
>>>     -
>>>     -# 3. Send an IP packet from every logical port to every other 
>>> subnet,
>>>     -#    to an IP address that does not have a static IP-MAC binding.
>>>     -#    This should generate a broadcast ARP request for the 
>>> destination
>>>     -#    IP address in the destination subnet.
>>>     -#    Moreover generate an ARP reply for each of the IP addresses
>>>     ARPed
>>>     -for is in 1 2 3; do
>>>     -  for js in 1 2 3; do
>>>     -    for ks in 1 2 3; do
>>>     -      s=$is$js$ks
>>>     -      smac=f00000000$s
>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>     -      for id in 1 2 3; do
>>>     -        for jd in 1 2 3; do
>>>     -          if test $is$js = $id$jd; then
>>>     -            continue
>>>     -          fi
>>>     -
>>>     -          # Send the packet.
>>>     -          dmac=00000000ff$is$js
>>>     -          # Calculate a 4th octet for the destination that is
>>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP 
>>> addresses
>>>     -          # that have static MAC bindings, and fits in the range
>>>     -          # 0-255.
>>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>>     -          test_ip $s $smac $dmac $sip $dip
>>>     -
>>>     -          # Every LP on the destination subnet's lswitch should
>>>     -          # receive the ARP request.
>>>     -          lrmac=00000000ff$id$jd
>>>     -          lrip=`ip_to_hex 192 168 $id$jd 254`
>>>     -
>>> arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip} 
>>>
>>>     -          for jd2 in 1 2 3; do
>>>     -            for kd in 1 2 3; do
>>>     -              echo $arp >> $id$jd2$kd.expected
>>>     -            done
>>>     -          done
>>>     -
>>>     -          hmac=8000000000$o4
>>>     -          rmac=00000000ff$id$jd
>>>     -          echo
>>> ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 
>>>
>>>     >> ${id}11.expected
>>>     -
>>>     -          host_mac=8000000000$o4
>>>     -          lrmac=00000000ff$id$jd
>>>     -
>>>     -
>>> arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip} 
>>>
>>>     -
>>>     -          hv=hv`vif_to_hv ${id}${jd}1`
>>>     -          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1
>>>     $arp_reply
>>>     -
>>>     -          host_ip_pretty=192.168.$id$jd.$o4
>>>     -          host_mac_pretty=80:00:00:00:00:$o4
>>>     -          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >>
>>>     mac_bindings.expected
>>>     -        done
>>>     -      done
>>>     -    done
>>>     -  done
>>>     -done
>>>     -
>>>     -# Test router replies to ARP requests from all source ports:
>>>     -#
>>>     -# 4. Router replies to query for its MAC address from port's own
>>>     IP address.
>>>     -#
>>>     -# 5. Router replies to query for its MAC address from any random
>>>     IP address
>>>     -#    in its subnet.
>>>     -#
>>>     -# 6. No reply to query for IP address other than router IP.
>>>     -#
>>>     -# 7. No reply to query from another subnet.
>>>     -for i in 1 2 3; do
>>>     -  for j in 1 2 3; do
>>>     -    for k in 1 2 3; do
>>>     -      smac=f00000000$i$j$k               # Source MAC
>>>     -      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
>>>     -      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
>>>     -      rmac=00000000ff$i$j                # Router MAC
>>>     -      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in 
>>> subnet
>>>     -      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in
>>>     subnet
>>>     -
>>>     -      test_arp $i$j$k $smac $sip        $rip        $rmac     #4
>>>     -      test_arp $i$j$k $smac $otherip    $rip        $rmac     #5
>>>     -      test_arp $i$j$k $smac $sip        $otherip    #6
>>>     -
>>>     -      # When rip is 192.168.33.254, ARP request from externalip
>>>     won't be
>>>     -      # filtered, because 192.168.33.254 is configured to switch
>>>     peer port
>>>     -      # for lrp33.
>>>     -      lrp33_rsp=
>>>     -      if test $i = 3 && test $j = 3; then
>>>     -        lrp33_rsp=$rmac
>>>     -      fi
>>>     -      test_arp $i$j$k $smac $externalip $rip $lrp33_rsp #7
>>>     -
>>>     -      # MAC binding should be learned from ARP request.
>>>     -      host_mac_pretty=f0:00:00:00:0$i:$j$k
>>>     -
>>>     -      host_ip_pretty=192.168.$i$j.$k
>>>     -      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>>     mac_bindings.expected
>>>     -
>>>     -      # mac_binding is learned and overwritten so only the last
>>>     one remains.
>>>     -      if test $k = 3; then
>>>     -          # lrp33 will not learn from ARP request, because
>>>     192.168.33.254 is
>>>     -          # configured to switch peer port for lrp33.
>>>     -          if test $i != 3 || test $j != 3; then
>>>     -              host_ip_pretty=192.168.$i$j.55
>>>     -              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>>     mac_bindings.expected
>>>     -          fi
>>>     -      fi
>>>     -
>>>     -    done
>>>     -  done
>>>     -done
>>>     -
>>>     -
>>>     -# Allow some time for packet forwarding.
>>>     -# XXX This can be improved.
>>>     -sleep 1
>>>     -
>>>     -# 8. Send an IP packet from every logical port to every other
>>>     subnet.  These
>>>     -#    are the same packets already sent as #3, but now the
>>>     destinations' IP-MAC
>>>     -#    bindings have been discovered via ARP, so instead of
>>>     provoking an ARP
>>>     -#    request, these packets now get routed to their destinations
>>>     (which don't
>>>     -#    have static MAC bindings, so they go to the port we've
>>>     designated as
>>>     -#    accepting "unknown" MACs.)
>>>     -for is in 1 2 3; do
>>>     -  for js in 1 2 3; do
>>>     -    for ks in 1 2 3; do
>>>     -      s=$is$js$ks
>>>     -      smac=f00000000$s
>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>     -      for id in 1 2 3; do
>>>     -        for jd in 1 2 3; do
>>>     -          if test $is$js = $id$jd; then
>>>     -            continue
>>>     -          fi
>>>     -
>>>     -          # Send the packet.
>>>     -          dmac=00000000ff$is$js
>>>     -          # Calculate a 4th octet for the destination that is
>>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP 
>>> addresses
>>>     -          # that have static MAC bindings, and fits in the range
>>>     -          # 0-255.
>>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>>     -          test_ip $s $smac $dmac $sip $dip
>>>     -
>>>     -          # Expect the packet egress.
>>>     -          host_mac=8000000000$o4
>>>     -          outport=${id}11
>>>     -          out_lrp=$id$jd
>>>     -          echo
>>> ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 
>>>
>>>     >> $outport.expected
>>>     -        done
>>>     -      done
>>>     -    done
>>>     -  done
>>>     -done
>>>     -
>>>     -ovn-sbctl -f csv -d bare --no-heading \
>>>     -    -- --columns=logical_port,ip,mac list mac_binding > 
>>> mac_bindings
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>     -                              [$i$j$k.expected])
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -# Check the MAC bindings against those expected.
>>>     -AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort <
>>>     mac_bindings.expected`
>>>     -])
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IP relocation using GARP request])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -#
>>>     -# Two logical switches ls1, ls2.
>>>     -# One logical router lr0 connected to ls[12],
>>>     -# with 2 subnets, 1 per logical switch:
>>>     -#
>>>     -#    lrp1 on ls1 for subnet 192.168.1.1/24 <http://192.168.1.1/24>
>>>     -#    lrp2 on ls2 for subnet 192.168.2.1/24 <http://192.168.2.1/24>
>>>     -#
>>>     -# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
>>>     -# VIFs' fixed IP addresses are 192.168.[12].1[12].
>>>     -#
>>>     -# There is a secondary IP 192.168.1.100 that is unknown in NB and
>>>     learned
>>>     -# through ARP only, and it can move between lp11 and lp12.
>>>     -#
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2 ; do
>>>     -    ovn-nbctl ls-add ls$i
>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
>>>     -    ovn-nbctl \
>>>     -        -- lsp-add ls$i lrp$i-attachment \
>>>     -        -- set Logical_Switch_Port lrp$i-attachment type=router \
>>>     -                         options:router-port=lrp$i \
>>>     -                         addresses=router
>>>     -    for j in 1 2; do
>>>     -        ovn-nbctl \
>>>     -            -- lsp-add ls$i lp$i$j \
>>>     -            -- lsp-set-addresses lp$i$j \
>>>     -               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
>>>     -    done
>>>     -done
>>>     -
>>>     -# Physical network:
>>>     -# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located, e.g. "vif_to_hv 12" yields 2.
>>>     -vif_to_hv() {
>>>     -    echo ${1#?}
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its
>>>     logical router
>>>     -# port, e.g. "vif_to_lrp 12" yields 1.
>>>     -vif_to_lrp() {
>>>     -    echo ${1%?}
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its logical
>>>     -# switch, e.g. "vif_to_ls 12" yields 1.
>>>     -vif_to_ls() {
>>>     -    echo ${1%?}
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -done
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        hv=`vif_to_hv $i$j`
>>>     -            as hv$hv ovs-vsctl \
>>>     -                -- add-port br-int vif$i$j \
>>>     -                -- set Interface vif$i$j \
>>>     -                    external-ids:iface-id=lp$i$j \
>>>     -                    options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
>>>     - options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
>>>     -                    ofport-request=$i$j
>>>     -    done
>>>     -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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 12
>>>     for vif12.
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    in_ls=`vif_to_ls $inport`
>>>     -    in_lrp=`vif_to_lrp $inport`
>>>     -    for outport; do
>>>     -        out_ls=`vif_to_ls $outport`
>>>     -        if test $in_ls = $out_ls; then
>>>     -            # Ports on the same logical switch receive exactly
>>>     the same packet.
>>>     -            echo $packet
>>>     -        else
>>>     -            # Routing decrements TTL and updates source and 
>>> dest MAC
>>>     -            # (and checksum).
>>>     -            out_lrp=`vif_to_lrp $outport`
>>>     -            echo
>>> f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -        fi >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>     -    local
>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>     -
>>>     -    # Expect to receive the broadcast ARP on the other logical
>>>     switch ports if
>>>     -    # IP address is not configured to the switch patch port.
>>>     -    local i=`vif_to_ls $inport`
>>>     -    local j
>>>     -    for j in 1 2; do
>>>     -        if test $i$j != $inport; then
>>>     -            echo $request >> $i$j$k.expected
>>>     -        fi
>>>     -    done
>>>     -
>>>     -    # Expect to receive the reply, if any.
>>>     -    if test X$reply_ha != X; then
>>>     -        lrp=`vif_to_lrp $inport`
>>>     -        local
>>> reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>
>>>     -        echo $reply >> $inport.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# lp11 send GARP request to announce ownership of 192.168.1.100.
>>>     -
>>>     -sha=f00000000011
>>>     -spa=`ip_to_hex 192 168 1 100`
>>>     -tpa=$spa
>>>     -test_arp 11 $sha $spa $tpa
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>     ip="192.168.1.100" | wc -l` -gt 0])
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>>     to lp11.
>>>     -
>>>     -smac=f00000000021
>>>     -dmac=00000000ff02
>>>     -sip=`ip_to_hex 192 168 2 11`
>>>     -dip=`ip_to_hex 192 168 1 100`
>>>     -test_ip 21 $smac $dmac $sip $dip 11
>>>     -
>>>     -# lp12 send GARP request to announce ownership of 192.168.1.100.
>>>     -
>>>     -sha=f00000000012
>>>     -test_arp 12 $sha $spa $tpa
>>>     -OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" |
>>>     grep f0:00:00:00:00:12])
>>>     -ovn-nbctl --wait=hv sync
>>>     -# give to the hv the time to send queued ip packets
>>>     -sleep 1
>>>     -
>>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>>     to lp12.
>>>     -
>>>     -test_ip 21 $smac $dmac $sip $dip 12
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2; do
>>>     -    for j in 1 2; do
>>>     -        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
>>>     -                          [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# 3 hypervisors, one logical switch, 3 logical ports per 
>>> hypervisor
>>>     -AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Create hypervisors hv[123].
>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>     -# Add all of the vifs to a single logical switch lsw0.
>>>     -# Turn off port security on vifs vif[123]1
>>>     -# Turn on l2 port security on vifs vif[123]2
>>>     -# Turn of l2 and l3 port security on vifs vif[123]3
>>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2 3; do
>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>     -        if test $j = 1; then
>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>>     -        elif test $j = 2; then
>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j"
>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>     f0:00:00:00:00:$i$j
>>>     -        else
>>>     -            extra_addr="f0:00:00:00:0$i:$i$j
>>>     fe80::ea2a:eaff:fe28:$i$j"
>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>>     -        fi
>>>     -    done
>>>     -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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv${1%?}
>>>     -}
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -
>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -#
>>>     -# This shell function causes an ip packet to be received on 
>>> INPORT.
>>>     -# The packet's content has Ethernet destination DST and source SRC
>>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>>     digits).
>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>     should
>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>     switch
>>>     -# port numbers, e.g. 11 for vif11.
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 
>>> reply_ha=$7
>>>     -    local
>>> request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -    hv=`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $request
>>>     -    if test $drop != 1; then
>>>     -        if test X$reply_ha = X; then
>>>     -            # Expect to receive the broadcast ARP on the other
>>>     logical switch ports
>>>     -            # if no reply is expected.
>>>     -            local i j
>>>     -            for i in 1 2 3; do
>>>     -                for j in 1 2 3; do
>>>     -                    if test $i$j != $inport; then
>>>     -                        echo $request >> $i$j.expected
>>>     -                    fi
>>>     -                done
>>>     -            done
>>>     -        else
>>>     -            # Expect to receive the reply, if any.
>>>     -            local
>>> reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
>>>     -            echo $reply >> $inport.expected
>>>     -        fi
>>>     -    fi
>>>     -}
>>>     -
>>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -# This function is similar to test_ip() except that it sends
>>>     -# ipv6 packet
>>>     -test_ipv6() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE
>>>     OUTPORT...
>>>     -# This function is similar to test_ipv6() except it specifies the
>>>     ICMPv6 type
>>>     -# of the test packet
>>>     -test_icmpv6() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     icmp_type=$6
>>>     -    local
>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000 
>>>
>>>     -    shift; shift; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# no port security
>>>     -sip=`ip_to_hex 192 168 0 12`
>>>     -tip=`ip_to_hex 192 168 0 13`
>>>     -# the arp packet should be allowed even if lp[123]1 is
>>>     -# not configured with mac f00000000023 and ip 192.168.0.12
>>>     -for i in 1 2 3; do
>>>     -    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 
>>> f00000000013
>>>     -    for j in 1 2 3; do
>>>     -        if test $i != $j; then
>>>     -            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip
>>>     $tip ${j}1
>>>     -        fi
>>>     -    done
>>>     -done
>>>     -
>>>     -# l2 port security
>>>     -sip=`ip_to_hex 192 168 0 12`
>>>     -tip=`ip_to_hex 192 168 0 13`
>>>     -
>>>     -# arp packet should be allowed since lp22 is configured with
>>>     -# mac f00000000022
>>>     -test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
>>>     -
>>>     -# arp packet should not be allowed since lp32 is not configured 
>>> with
>>>     -# mac f00000000021
>>>     -test_arp 32 f00000000021 f00000000021 $sip $tip 1
>>>     -
>>>     -# arp packet with sha set to f00000000021 should not be allowed
>>>     -# for lp12
>>>     -test_arp 12 f00000000012 f00000000021 $sip $tip 1
>>>     -
>>>     -# ip packets should be allowed and received since lp[123]2 do not
>>>     -# have l3 port security
>>>     -sip=`ip_to_hex 192 168 0 55`
>>>     -tip=`ip_to_hex 192 168 0 66`
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        if test $i != $j; then
>>>     -            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip
>>>     $tip ${j}2
>>>     -        fi
>>>     -    done
>>>     -done
>>>     -
>>>     -# ipv6 packets should be received by lp[123]2
>>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>>     -sip=fe800000000000000000000000000000
>>>     -tip=ff020000000000000000000000000000
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip 
>>> ${i}2
>>>     -done
>>>     -
>>>     -
>>>     -# l2 and l3 port security
>>>     -sip=`ip_to_hex 192 168 0 13`
>>>     -tip=`ip_to_hex 192 168 0 22`
>>>     -# arp packet should be allowed since lp13 is configured with
>>>     -# f00000000013 and 192.168.0.13
>>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>>     -
>>>     -# the arp packet should be dropped because lp23 is not configured
>>>     -# with mac f00000000022
>>>     -sip=`ip_to_hex 192 168 0 13`
>>>     -tip=`ip_to_hex 192 168 0 22`
>>>     -test_arp 23 f00000000022 f00000000022 $sip $tip 1
>>>     -
>>>     -# the arp packet should be dropped because lp33 is not configured
>>>     -# with ip 192.168.0.55
>>>     -spa=`ip_to_hex 192 168 0 55`
>>>     -tpa=`ip_to_hex 192 168 0 22`
>>>     -test_arp 33 f00000000031 f00000000031 $spa $tpa 1
>>>     -
>>>     -# ip packets should not be received by lp[123]3 since
>>>     -# l3 port security is enabled
>>>     -sip=`ip_to_hex 192 168 0 55`
>>>     -tip=`ip_to_hex 192 168 0 66`
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
>>>     -    done
>>>     -done
>>>     -
>>>     -# ipv6 packets should be dropped for lp[123]3 since
>>>     -# it is configured with only ipv4 address
>>>     -sip=fe800000000000000000000000000000
>>>     -tip=ff020000000000000000000000000000
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
>>>     -done
>>>     -
>>>     -# ipv6 packets should not be received by lp[123]3 with mac
>>>     f000000000$[123]3
>>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>>     -for i in 1 2 3; do
>>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
>>>     -done
>>>     -
>>>     -# lp13 has extra port security with mac f0000000113 and ipv6 addr
>>>     -# fe80::ea2a:eaff:fe28:0012
>>>     -
>>>     -# ipv4 packet should be dropped for lp13 with mac f0000000113
>>>     -sip=`ip_to_hex 192 168 0 13`
>>>     -tip=`ip_to_hex 192 168 0 23`
>>>     -test_ip 13 f00000000113 f00000000023 $sip $tip
>>>     -
>>>     -# ipv6 packet should be received by lp[123]3 with mac
>>>     f00000000${i}${i}3
>>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
>>>     -# lp11 can send ipv6 traffic as there is no port security
>>>     -sip=ee800000000000000000000000000000
>>>     -for i in 1 2 3; do
>>>     -    tip=fe80000000000000ea2aeafffe2800${i}3
>>>     -    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
>>>     -done
>>>     -
>>>     -
>>>     -# ipv6 packet should not be received by lp33 with mac f0000000333
>>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
>>>     -# configured with fe80::ea2a:eaff:fe28:0033
>>>     -# lp11 can send ipv6 traffic as there is no port security
>>>     -
>>>     -sip=ee800000000000000000000000000000
>>>     -tip=fe80000000000000ea2aeafffe280023
>>>     -test_ipv6 11 f00000000011 f00000000333 $sip $tip
>>>     -
>>>     -# ipv6 packet should be allowed for lp[123]3 with mac
>>>     f0000000${i}${i}3
>>>     -# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
>>>     -# and should be dropped for any other ip6.src
>>>     -# lp21 can receive ipv6 traffic as there is no port security
>>>     -
>>>     -tip=ee800000000000000000000000000000
>>>     -for i in 1 2 3; do
>>>     -    sip=fe80000000000000ea2aeafffe2800${i}3
>>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
>>>     -
>>>     -    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
>>>     -    sip=00000000000000000000000000000000
>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>     ff020000000000000000000000160000 83 21
>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>     ff020000000000000000000000160000 8f 21
>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>     ff0200000000000000ea2aeafffe2800 87 21
>>>     -    # Traffic to non-multicast traffic should be dropped
>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
>>>     -    # Traffic of other ICMPv6 types should be dropped
>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>     ff020000000000000000000000160000 80
>>>     -
>>>     -    # should be dropped
>>>     -    sip=ae80000000000000ea2aeafffe2800aa
>>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
>>>     -done
>>>     -
>>>     -# configure lsp13 to send and received IPv4 packets with an
>>>     address range
>>>     -ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13
>>>     192.168.0.13 20.0.0.4/24 <http://20.0.0.4/24> 10.0.0.0/24
>>>     <http://10.0.0.0/24>"
>>>     -
>>>     -sleep 2
>>>     -
>>>     -sip=`ip_to_hex 10 0 0 13`
>>>     -tip=`ip_to_hex 192 168 0 22`
>>>     -# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
>>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>>     -
>>>     -sip=`ip_to_hex 10 0 0 14`
>>>     -tip=`ip_to_hex 192 168 0 23`
>>>     -# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
>>>     -# with dst ip 192.168.0.23 should be allowed
>>>     -test_ip 13 f00000000013 f00000000023 $sip $tip 23
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 10 0 0 15`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 10.0.0.15 should be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 20 0 0 4`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 20.0.0.4 should be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 20 0 0 5`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 20.0.0.5 should not be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 20 0 0 255`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 20.0.0.255 should be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 192 168 0 255`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 192.168.0.255 should not be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>>     -
>>>     -sip=`ip_to_hex 192 168 0 33`
>>>     -tip=`ip_to_hex 224 0 0 4`
>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>> lsp13
>>>     -# with dst ip 224.0.0.4  should be received by lsp13
>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>     -
>>>     -#dump information including flow counters
>>>     -ovn-nbctl show
>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -echo "------ hv3 dump ------"
>>>     -as hv3 ovs-vsctl show
>>>     -as hv3 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>>     -# network. R1 has a switchs ls1 (191.168.1.0/24
>>>     <http://191.168.1.0/24>) connected to it.
>>>     -# R2 has ls2 (172.16.1.0/24 <http://172.16.1.0/24>) connected 
>>> to it.
>>>     -
>>>     -ls1_lp1_mac="f0:00:00:01:02:03"
>>>     -rp_ls1_mac="00:00:00:01:02:03"
>>>     -rp_ls2_mac="00:00:00:01:02:04"
>>>     -ls2_lp1_mac="f0:00:00:01:02:04"
>>>     -
>>>     -ls1_lp1_ip="192.168.1.2"
>>>     -ls2_lp1_ip="172.16.1.2"
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lr-add R2
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -
>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>>     type=router \
>>>     -  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
>>>     -
>>>     -# Connect ls2 to R2
>>>     -ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>>     type=router \
>>>     -  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
>>>     -
>>>     -# Connect R1 to R2
>>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>>     <http://20.0.0.1/24> peer=R2_R1
>>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>>     <http://20.0.0.2/24> peer=R1_R2
>>>     -
>>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.2
>>>     -ovn-nbctl lr-route-add R2 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.1
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
>>>     -
>>>     -# Create logical port ls2-lp1 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Packet to send.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>>     eth.dst==$rp_ls1_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>>     ip4.dst==$ls2_lp1_ip &&
>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Packet to Expect
>>>     -# The TTL should be decremented by 2.
>>>     -packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
>>>     -        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip &&
>>>     ip4.dst==$ls2_lp1_ip &&
>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>     -echo $packet | ovstest test-ovn expr-to-packets > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# Disable the ls2-lp1 port.
>>>     -ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
>>>     -
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# Generate the packet destined for ls2-lp1 and it should not be
>>>     delivered.
>>>     -# Packet to send.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>>     eth.dst==$rp_ls1_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>>     ip4.dst==$ls2_lp1_ip &&
>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>     -
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -# The 2nd packet sent shound not be received.
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
>>>     -AT_KEYWORDS([router-admin-state])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR - R1 has switch ls1 with two subnets attached to it
>>>     (191.168.1.0/24 <http://191.168.1.0/24>
>>>     -# and 172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24> 172.16.1.1/24
>>>     -ovn-nbctl <http://172.16.1.1/24-ovn-nbctl> lsp-add ls1 rp-ls1 --
>>>     set Logical_Switch_Port rp-ls1 type=router \
>>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     -          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03
>>>     192.168.1.2"
>>>     -
>>>     -# Create logical port ls1-lp2 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>     -          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 
>>> 172.16.1.2"
>>>     -
>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>     -    set interface vif2 external-ids:iface-id=ls1-lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Send ip packets between the two ports.
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Packet to send.
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>     -
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -
>>>     -#Disable router R1
>>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>     -
>>>     -# Packet to Expect
>>>     -expect_src_mac="000000010203"
>>>     -expect_dst_mac="f00000010204"
>>>     -echo
>>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
>>>     -AT_KEYWORDS([router-admin-state])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>     <http://191.168.1.0/24>) connected to it,
>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>>     type=router \
>>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>>     -
>>>     -# Connect ls2 to R1
>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>>     type=router \
>>>     -          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port ls2-lp1 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Send ip packets between the two ports.
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Packet to send.
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>     -
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -#Disable router R1
>>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Allow some time for the disabling of logical router R1 to
>>>     propagate.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>     -
>>>     -# Packet to Expect
>>>     -expect_src_mac="000000010204"
>>>     -expect_dst_mac="f00000010204"
>>>     -echo
>>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static 
>>> routes])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>>     -# network. R1 has switchess foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>)
>>>     -# connected to it.
>>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and bob
>>>     (172.16.2.0/24 <http://172.16.2.0/24>) connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lr-add R2
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add bob
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -          type=router options:router-port=alice
>>>     addresses=\"00:00:00:01:02:04\"
>>>     -
>>>     -# Connect bob to R2
>>>     -ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
>>>     <http://172.16.2.1/24>
>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob
>>>     type=router \
>>>     -          options:router-port=bob addresses=\"00:00:00:01:02:05\"
>>>     -
>>>     -# Connect R1 to R2
>>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>>     <http://20.0.0.1/24> peer=R2_R1
>>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>>     <http://20.0.0.2/24> peer=R1_R2
>>>     -
>>>     -#install static routes
>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -ovn-nbctl lr-route-add R2 172.16.2.0/24 <http://172.16.2.0/24>
>>>     20.0.0.2 R1_R2
>>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>>     20.0.0.1
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Create logical port bob1 in bob
>>>     -ovn-nbctl lsp-add bob bob1 \
>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -# Send ip packets between foo1 and bob1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump ----------"
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Packet to Expect at bob1
>>>     -src_mac="000000010205"
>>>     -dst_mac="f00000010205"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>>     -echo
>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Packet to Expect at alice1
>>>     -src_mac="000000010204"
>>>     -dst_mac="f00000010204"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>     -echo
>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send gratuitous arp on localnet])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0
>>>     -
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>     snoopvif options:tx_pcap=hv/snoopvif-tx.pcap
>>>     options:rxq_pcap=hv/snoopvif-rx.pcap])
>>>     -
>>>     -# Create a vif.
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>>     "f0:00:00:00:00:01 192.168.1.2"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>>     "f0:00:00:00:00:01"])
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>> network_name=physnet1])
>>>     -
>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>>     localvif1 external_ids:iface-id=localvif1])
>>>     -
>>>     -# Wait for packet to be received.
>>>     -echo
>>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>>
>>>     > expected
>>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>>     -
>>>     -# Check GARP packet when restart openflow connection.
>>>     -as hv
>>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>     -
>>>     -OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect"
>>>     hv/ovn-controller.log])
>>>     -
>>>     -as hv
>>>     -start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>>     -vofproto_dpif -vunixctl
>>>     -
>>>     -# Wait for packet to be received.
>>>     -echo
>>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>>
>>>     > expected
>>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>>     -
>>>     -# Delete the localnet ports.
>>>     -AT_CHECK([ovs-vsctl del-port localvif1])
>>>     -AT_CHECK([ovn-nbctl lsp-del ln_port])
>>>     -
>>>     -OVN_CLEANUP([hv])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>     LS "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>>     -# connected to it. R2 has alice (172.16.1.0/24
>>>     <http://172.16.1.0/24>) and R3 has bob (10.32.1.0/24
>>>     <http://10.32.1.0/24>)
>>>     -# connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lr-add R2
>>>     -ovn-nbctl lr-add R3
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add bob
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect bob to R3
>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
>>>     <http://10.32.1.1/24>
>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>     -    type=router options:router-port=bob
>>>     addresses=\"00:00:03:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Connect R3 to join
>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>     <http://20.0.0.3/24>
>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>> r3-join \
>>>     -    type=router options:router-port=R3_join
>>>     addresses='"00:00:04:01:02:05"'
>>>     -
>>>     -#install static routes
>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -ovn-nbctl lr-route-add R1 10.32.1.0/24 <http://10.32.1.0/24> 
>>> 20.0.0.3
>>>     -
>>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>>     20.0.0.1
>>>     -ovn-nbctl lr-route-add R2 10.32.1.0/24 <http://10.32.1.0/24> 
>>> 20.0.0.3
>>>     -
>>>     -ovn-nbctl lr-route-add R3 192.168.1.0/24 <http://192.168.1.0/24>
>>>     20.0.0.1
>>>     -ovn-nbctl lr-route-add R3 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Create logical port bob1 in bob
>>>     -ovn-nbctl lsp-add bob bob1 \
>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>     -
>>>     -# Send ip packets between foo1 and bob1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -echo "----------------------------"
>>>     -
>>>     -# Packet to Expect at bob1
>>>     -src_mac="000003010203"
>>>     -dst_mac="f00000010205"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>>     -echo
>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Packet to Expect at alice1
>>>     -src_mac="000002010203"
>>>     -dst_mac="f00000010204"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>     -echo
>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>> 10.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>     10.0.0.6 20.0.0.4"
>>>     -
>>>     -ovn-nbctl ls-add ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
>>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03
>>>     30.0.0.6 40.0.0.4"
>>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 
>>> 30.0.0.7"
>>>     -
>>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>>     <http://10.0.0.0/24> \
>>>     -options="\"server_id\"=\"10.0.0.1\"
>>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
>>>     -
>>>     -d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24
>>>     <http://30.0.0.0/24> \
>>>     -options="\"server_id\"=\"30.0.0.1\"
>>>     \"server_mac\"=\"ff:10:00:00:00:02\" \
>>>     -\"lease_time\"=\"3600\"")"
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>     -    ofport-request=3
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>>     -    ofport-request=4
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -sleep 2
>>>     -
>>>     -as hv1 ovs-vsctl show
>>>     -
>>>     -# This shell function sends a DHCP request packet
>>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
>>>     -test_dhcp() {
>>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5
>>>     request_ip=$6 use_ip=$7
>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>     -    if test $use_ip != 0; then
>>>     -        src_ip=$1
>>>     -        dst_ip=$2
>>>     -        shift; shift;
>>>     -    else
>>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>>     -    fi
>>>     -    if test $request_ip != 0; then
>>>     -        ip_len=0120
>>>     -        udp_len=010b
>>>     -    else
>>>     -        ip_len=011a
>>>     -        udp_len=0106
>>>     -    fi
>>>     -    local
>>> request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip} 
>>>
>>>     -    # udp header and dhcp header
>>>     -    request=${request}00440043${udp_len}0000
>>>     -
>>> request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac} 
>>>
>>>     -    # client hardware padding
>>>     -    request=${request}00000000000000000000
>>>     -    # server hostname
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # boot file name
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # dhcp magic cookie
>>>     -    request=${request}63825363
>>>     -    # dhcp message type
>>>     -    request=${request}3501${dhcp_type}
>>>     -    # dhcp unknown option
>>>     -    request=${request}d70701020304050607
>>>     -    # dhcp pad option
>>>     -    request=${request}00
>>>     -    if test $request_ip != 0; then
>>>     -        # dhcp requested ip
>>>     -        request=${request}3204${request_ip}
>>>     -    fi
>>>     -    # dhcp end option
>>>     -    request=${request}ff
>>>     -
>>>     -    for port in $inport "$@"; do
>>>     -        : >> $port.expected
>>>     -    done
>>>     -    if test $offer_ip != 0; then
>>>     -        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3
>>>     expected_dhcp_opts=$4
>>>     -        # total IP length will be the IP length of the request 
>>> packet
>>>     -        # (which is 272 in our case) + 8 (padding bytes) +
>>>     (expected_dhcp_opts / 2)
>>>     -        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>>     -        udp_len=`expr $ip_len - 20`
>>>     -        ip_len=$(printf "%x" $ip_len)
>>>     -        udp_len=$(printf "%x" $udp_len)
>>>     -        # $ip_len var will be in 3 digits i.e 134. So adding a
>>>     '0' before $ip_len
>>>     -        local
>>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>>
>>>     -        # udp header and dhcp header.
>>>     -        # $udp_len var will be in 3 digits. So adding a '0'
>>>     before $udp_len
>>>     -
>>> reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
>>>     -        # your ip address; 0 for NAK
>>>     -        if test $dhcp_reply_type = 06; then
>>>     -            reply=${reply}00000000
>>>     -        else
>>>     -            reply=${reply}${offer_ip}
>>>     -        fi
>>>     -        # next server ip address, relay agent ip address, client
>>>     mac address
>>>     -        reply=${reply}0000000000000000${src_mac}
>>>     -        # client hardware padding
>>>     -        reply=${reply}00000000000000000000
>>>     -        # server hostname
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -        # boot file name
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -        # dhcp magic cookie
>>>     -        reply=${reply}63825363
>>>     -
>>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>>
>>>     -        echo $reply >> $inport.expected
>>>     -    else
>>>     -        for outport; do
>>>     -            echo $request >> $outport.expected
>>>     -        done
>>>     -    fi
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Send DHCPDISCOVER.
>>>     -offer_ip=`ip_to_hex 10 0 0 4`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -request_ip=0
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0
>>>     ff1000000001 $server_ip 02 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 1.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap > 1.packets
>>>     -cat 1.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 1.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>     to receive
>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>     easier to test.
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the
>>>     offered IP
>>>     -# address in the Requested IP Address option.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -request_ip=$offer_ip
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>>     ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a
>>>     mismatched IP in
>>>     -# the Requested IP Address option, expect a DHCPNAK.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -request_ip=`ip_to_hex 10 0 0 7`
>>>     -expected_dhcp_opts=""
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>>     ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 3.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by
>>>     ovn-controller
>>>     -# but should be resumed without the reply.
>>>     -# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet
>>>     twice,
>>>     -# one from ovn-controller and the other from "ovs-ofctl resume."
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -offer_ip=0
>>>     -request_ip=0
>>>     -test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
>>>     -
>>>     -# NXT_RESUMEs should be 4.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# vif1-tx.pcap should have received the DHCPv4 (invalid) request
>>>     packet
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4
>>>     options defined.
>>>     -# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet
>>>     once.
>>>     -
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
>>>     -
>>>     -# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not
>>>     defined for
>>>     -# this lport.
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
>>>     -
>>>     -# NXT_RESUMEs should be 4.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
>>>     -#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
>>>     -
>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>>     set to 10.0.0.6
>>>     -# and ip4.dst set to 10.0.0.1.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=$offer_ip
>>>     -request_ip=0
>>>     -src_ip=$offer_ip
>>>     -dst_ip=$server_ip
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 5.
>>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>>     set to 10.0.0.6
>>>     -# and ip4.dst set to 255.255.255.255.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=$offer_ip
>>>     -request_ip=0
>>>     -src_ip=$offer_ip
>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 6.
>>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with a
>>>     mismatched IP in the
>>>     -# ciaddr, expect a DHCPNAK.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=`ip_to_hex 10 0 0 7`
>>>     -request_ip=0
>>>     -src_ip=$offer_ip
>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>     -expected_dhcp_opts=""
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 7.
>>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state without a
>>>     specifyied ciaddr,
>>>     -# expect a DHCPNAK.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -request_ip=0
>>>     -src_ip=$offer_ip
>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>     -expected_dhcp_opts=""
>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 8.
>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set
>>>     to 10.0.0.4.
>>>     -# The packet should not be received by ovn-controller.
>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 4`
>>>     -test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
>>>     -
>>>     -# NXT_RESUMEs should be 8.
>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# vif1-tx.pcap should have received the DHCPv4 request packet
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>>     10.0.0.4 ae70::4"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 
>>> ae70::5"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp3 \
>>>     --- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 
>>> ae70::22"
>>>     -
>>>     -d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
>>>     -
>>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>     -options="\"dhcpv6_stateless\"=\"true\"
>>>     \"server_id\"=\"00:00:00:10:00:01\"")"
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
>>>     -
>>>     -ovn-nbctl ls-add ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
>>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 
>>> be70::3"
>>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
>>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 
>>> be70::4"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>     -    ofport-request=3
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>>     -    ofport-request=4
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif5 -- \
>>>     -    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
>>>     -    options:tx_pcap=hv1/vif5-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif5-rx.pcap \
>>>     -    ofport-request=5
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -sleep 2
>>>     -
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -# This shell function sends a DHCPv6 request packet
>>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>>     OUTPORT...
>>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>>     DHCPv6
>>>     -# packet should be received twice (one from ovn-controller and
>>>     the other
>>>     -# from the "ovs-ofctl monitor br-int resume"
>>>     -test_dhcpv6() {
>>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>>     -    if test $msg_code != 0b; then
>>>     -        req_len=2a
>>>     -    else
>>>     -        req_len=1a
>>>     -    fi
>>>     -    local
>>> request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
>>>     -    # dst ip ff02::1:2
>>>     -    request=${request}ff020000000000000000000000010002
>>>     -    # udp header and dhcpv6 header
>>>     - request=${request}0222022300${req_len}ffff${msg_code}010203
>>>     -    # Client identifier
>>>     -    request=${request}0001000a00030001${src_mac}
>>>     -    # Add IA-NA (Identity Association for Non Temporary Address)
>>>     if msg_code
>>>     -    # is not 11 (information request packet)
>>>     -    if test $msg_code != 0b; then
>>>     - request=${request}0003000c0102030400000e1000001518
>>>     -    fi
>>>     -    shift; shift; shift; shift; shift;
>>>     -    if test $offer_ip != 0; then
>>>     -        local server_mac=000000100001
>>>     -        local server_lla=fe80000000000000020000fffe100001
>>>     -        local reply_code=07
>>>     -        if test $msg_code = 01; then
>>>     -            reply_code=02
>>>     -        fi
>>>     -        local msg_len=54
>>>     -        if test $offer_ip = 1; then
>>>     -            msg_len=28
>>>     -        fi
>>>     -        local
>>> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla} 
>>>
>>>     -        # udp header and dhcpv6 header
>>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>>     -        # Client identifier
>>>     -        reply=${reply}0001000a00030001${src_mac}
>>>     -        # IA-NA
>>>     -        if test $offer_ip != 1; then
>>>     -
>>> reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff 
>>>
>>>     -        fi
>>>     -        # Server identifier
>>>     -        reply=${reply}0002000a00030001${server_mac}
>>>     -        echo $reply | trim_zeros >> $inport.expected
>>>     -    else
>>>     -        for outport; do
>>>     -            echo $request | trim_zeros >> $outport.expected
>>>     -        done
>>>     -    fi
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -src_mac=f00000000001
>>>     -src_lla=fe80000000000000f20000fffe000001
>>>     -offer_ip=ae700000000000000000000000000004
>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>     -
>>>     -# NXT_RESUMEs should be 1.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>>     -# cat 1.expected | trim_zeros > expout
>>>     -cat 1.expected | cut -c -120 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
>>>     -# Skipping the UDP checksum
>>>     -cat 1.expected | cut -c 125- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
>>>     -
>>>     -rm  1.expected
>>>     -
>>>     -# Send invalid packet on ls1-lp2. ovn-controller should resume
>>>     the packet
>>>     -# without any modifications and the packet should be received by
>>>     ls1-lp1.
>>>     -# ls1-lp1 will receive the packet twice, one from the
>>>     ovn-controller after the
>>>     -# resume and the other from ovs-ofctl monitor resume.
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -
>>>     -src_mac=f00000000002
>>>     -src_lla=fe80000000000000f20000fffe000002
>>>     -offer_ip=ae700000000000000000000000000005
>>>     -# Set invalid msg_type
>>>     -
>>>     -test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
>>>     -
>>>     -# NXT_RESUMEs should be 2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# vif2-tx.pcap should not have received the DHCPv6 reply packet
>>>     -rm 2.packets
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap | trim_zeros > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>     -
>>>     -# vif1-tx.pcap should have received the DHCPv6 (invalid) request
>>>     packet
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>>     -cat 1.expected > expout
>>>     -AT_CHECK([cat 1.packets], [0], [expout])
>>>     -
>>>     -# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on
>>>     this port.
>>>     -# There should be no DHCPv6 reply from ovn-controller and the
>>>     request packet
>>>     -# should be received by ls2-lp2.
>>>     -
>>>     -src_mac=f00000000003
>>>     -src_lla=fe80000000000000f20000fffe000003
>>>     -test_dhcpv6 3 $src_mac $src_lla 01 0 4
>>>     -
>>>     -# NXT_RESUMEs should be 2 only.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# vif3-tx.pcap should not have received the DHCPv6 reply packet
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif3-tx.pcap | trim_zeros > 3.packets
>>>     -AT_CHECK([cat 3.packets], [0], [])
>>>     -
>>>     -# vif4-tx.pcap should have received the DHCPv6 request packet
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif4-tx.pcap | trim_zeros > 4.packets
>>>     -cat 4.expected > expout
>>>     -AT_CHECK([cat 4.packets], [0], [expout])
>>>     -
>>>     -# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless
>>>     mode for this port.
>>>     -# The DHCPv6 reply shouldn't contain offer_ip.
>>>     -src_mac=f00000000022
>>>     -src_lla=fe80000000000000f20000fffe000022
>>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>>     -test_dhcpv6 5 $src_mac $src_lla 01 1 5
>>>     -
>>>     -# NXT_RESUMEs should be 3.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif5-tx.pcap | trim_zeros > 5.packets
>>>     -# Skipping the UDP checksum
>>>     -cat 5.expected | cut -c 1-120,125- > expout
>>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>>     -
>>>     -# Send DHCPv6 information request (code 11) on ls1-lp3. The
>>>     DHCPv6 reply
>>>     -# shouldn't contain offer_ip
>>>     -src_mac=f00000000022
>>>     -src_lla=fe80000000000000f20000fffe000022
>>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>>     -rm -f 5.expected
>>>     -test_dhcpv6 5 $src_mac $src_lla 0b 1 5
>>>     -
>>>     -# NXT_RESUMEs should be 4.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif5-tx.pcap |
>>>     -trim_zeros > 5.packets
>>>     -# Skipping the UDP checksum
>>>     -cat 5.expected | cut -c 1-120,125- > expout
>>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>> "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>>     -# connected to it. R2 has alice (172.16.1.0/24
>>>     <http://172.16.1.0/24>) connected to it.
>>>     -# R2 is a gateway router.
>>>     -
>>>     -
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -
>>>     -#install static routes
>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>     -ip_prefix=172.16.1.0/24 <http://172.16.1.0/24> nexthop=20.0.0.2
>>>     -- add Logical_Router \
>>>     -R1 static_routes @lrt
>>>     -
>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>>     -- add Logical_Router \
>>>     -R2 static_routes @lrt
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 2
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -ovn-sbctl list chassis
>>>     -ovn-sbctl list encap
>>>     -echo "---------------------"
>>>     -
>>>     -# Packet to Expect at alice1
>>>     -src_mac="000002010203"
>>>     -dst_mac="f00000010204"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>     -
>>>     -echo "------ hv1 dump after packet 1 ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump after packet 1 ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -echo "----------------------------"
>>>     -
>>>     -echo $expected > expected
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Delete the router and re-create it. Things should work as 
>>> before.
>>>     -ovn-nbctl  lr-del R2
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -
>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>>     -- add Logical_Router \
>>>     -R2 static_routes @lrt
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -sleep 1
>>>     -
>>>     -# Send the packet again.
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -echo "------ hv1 dump after packet 2 ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump after packet 2 ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -echo "----------------------------"
>>>     -
>>>     -echo $expected >> expected
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
>>>     -AT_KEYWORDS([router-icmp-reply])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>     <http://191.168.1.0/24>) connected to it,
>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>     -    type=router options:router-port=ls1
>>>     addresses=\"00:00:00:01:02:f1\"
>>>     -
>>>     -# Connect ls2 to R1
>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>     -    type=router options:router-port=ls2
>>>     addresses=\"00:00:00:01:02:f2\"
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port ls2-lp1 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -for i in 1 2; do
>>>     -    : > vif$i.expected
>>>     -done
>>>     -# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>     IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an 
>>> ICMPv4
>>>     -# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
>>>     -# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and 
>>> EXP_ICMP_CHKSUM are
>>>     -# provided, then it should be the ip and icmp checksums of the 
>>> packet
>>>     -# responded; otherwise, no reply is expected.
>>>     -# In the absence of an ip checksum calculation helpers, this 
>>> relies
>>>     -# on the caller to provide the checksums for the ip and icmp 
>>> headers.
>>>     -# XXX This should be more systematic.
>>>     -#
>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>     -# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
>>>     -# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
>>>     -test_ipv4_icmp_request() {
>>>     -    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5
>>>     ip_chksum=$6 icmp_chksum=$7
>>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>>     -    shift; shift; shift; shift; shift; shift; shift
>>>     -    shift; shift
>>>     -
>>>     -    # Use ttl to exercise section 4.2.2.9 of RFC1812
>>>     -    local ip_ttl=01
>>>     -    local icmp_id=5fbf
>>>     -    local icmp_seq=0001
>>>     -    local icmp_data=$(seq 1 56 | xargs printf "%02x")
>>>     -    local icmp_type_code_request=0800
>>>     -    local
>>> icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>>
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload} 
>>>
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    if test X$exp_icmp_chksum != X; then
>>>     -        # Expect to receive the reply, if any. In same port where
>>>     packet was sent.
>>>     -        # Note: src and dst fields are expected to be reversed.
>>>     -        local icmp_type_code_response=0000
>>>     -        local reply_icmp_ttl=fe
>>>     -        local
>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>>
>>>     -        local
>>> reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>>
>>>     -        echo $reply >> vif$inport.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -# Send ping packet to router's ip addresses, from each of the 2
>>>     logical ports.
>>>     -rtr_l1_ip=$(ip_to_hex 192 168 1 1)
>>>     -rtr_l2_ip=$(ip_to_hex 172 16 1 1)
>>>     -l1_ip=$(ip_to_hex 192 168 1 2)
>>>     -l2_ip=$(ip_to_hex 172 16 1 2)
>>>     -
>>>     -# Ping router ip address that is on same subnet as the logical 
>>> port
>>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>>     -
>>>     -# Ping router ip address that is on the other side of the logical
>>>     ports
>>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>>     -
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list logical_flow
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for inport in 1 2; do
>>>     -    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap],
>>>     [vif$inport.expected])
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS,
>>>     1 LR])
>>>     -AT_KEYWORDS([policy-based-routing])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>     <http://191.168.1.0/24>) connected to it,
>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -ovn-nbctl ls-add ls3
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>     -    type=router options:router-port=ls1
>>>     addresses=\"00:00:00:01:02:f1\"
>>>     -
>>>     -# Connect ls2 to R1
>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>     -    type=router options:router-port=ls2
>>>     addresses=\"00:00:00:01:02:f2\"
>>>     -
>>>     -# Connect ls3 to R1
>>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
>>>     <http://20.20.1.1/24>
>>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>>     -    type=router options:router-port=ls3
>>>     addresses=\"00:00:00:01:02:f3\"
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port ls2-lp1 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Create logical port ls3-lp1 in ls3
>>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
>>>     -
>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add pbr-hv
>>>     -as pbr-hv
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ls1_ro_mac=00:00:00:01:02:f1
>>>     -ls1_ro_ip=192.168.1.1
>>>     -
>>>     -ls2_ro_mac=00:00:00:01:02:f2
>>>     -ls2_ro_ip=172.16.1.1
>>>     -
>>>     -ls3_ro_mac=00:00:00:01:02:f3
>>>     -
>>>     -ls1_p1_mac=00:00:00:01:02:03
>>>     -ls1_p1_ip=192.168.1.2
>>>     -
>>>     -ls2_p1_mac=00:00:00:01:02:04
>>>     -ls2_p1_ip=172.16.1.2
>>>     -
>>>     -ls3_p1_mac=00:00:00:01:02:05
>>>     -
>>>     -# Create a drop policy
>>>     -ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24
>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>     <http://172.16.1.0/24>" drop
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>>     "192.168.1.0" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>     ip4.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Check if packet hit the drop policy
>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24> actions=drop" | \
>>>     -    grep "priority=10" | \
>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Expected to drop the packet.
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>>     -rcvd_packet=`cat vif2.packets`
>>>     -AT_FAIL_IF([rcvd_packet = ""])
>>>     -
>>>     -# Override drop policy with allow
>>>     -ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24
>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>     <http://172.16.1.0/24>" allow
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>>     "192.168.1.0" | wc -l], [0], [dnl
>>>     -2
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>     ip4.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Check if packet hit the allow policy
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>     -    grep "192.168.1.0" | \
>>>     -    grep "priority=20" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>>     ip4.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>>     -
>>>     -# Override allow policy with reroute
>>>     -ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24
>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>     <http://172.16.1.0/24>" reroute 20.20.1.2
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>     -    grep "192.168.1.0" | \
>>>     -    grep "priority=30" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>     ip4.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -echo "southbound flows"
>>>     -
>>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>>     -echo "ovs flows"
>>>     -ovs-ofctl dump-flows br-int
>>>     -# Check if packet hit the allow policy
>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24>" | \
>>>     -    grep "priority=30" | \
>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -echo "packet hit reroute policy"
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>>     ip4.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>>     -
>>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>>     -
>>>     -OVN_CLEANUP([pbr-hv])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1
>>>     lport/LS, 1 LR])
>>>     -AT_KEYWORDS([policy-based-routing])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>     <http://191.168.1.0/24>) connected to it,
>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -ovn-nbctl ls-add ls3
>>>     -
>>>     -# Connect ls1 to R1
>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>     -    type=router options:router-port=ls1
>>>     addresses=\"00:00:00:01:02:f1\"
>>>     -
>>>     -# Connect ls2 to R1
>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>     -    type=router options:router-port=ls2
>>>     addresses=\"00:00:00:01:02:f2\"
>>>     -
>>>     -# Connect ls3 to R1
>>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
>>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>>     -    type=router options:router-port=ls3
>>>     addresses=\"00:00:00:01:02:f3\"
>>>     -
>>>     -# Create logical port ls1-lp1 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
>>>     -
>>>     -# Create logical port ls2-lp1 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
>>>     -
>>>     -# Create logical port ls3-lp1 in ls3
>>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
>>>     -
>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add pbr-hv
>>>     -as pbr-hv
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ls1_ro_mac=00:00:00:01:02:f1
>>>     -ls1_ro_ip=2001::1
>>>     -
>>>     -ls2_ro_mac=00:00:00:01:02:f2
>>>     -ls2_ro_ip=2002::1
>>>     -
>>>     -ls3_ro_mac=00:00:00:01:02:f3
>>>     -
>>>     -ls1_p1_mac=00:00:00:01:02:03
>>>     -ls1_p1_ip=2001::2
>>>     -
>>>     -ls2_p1_mac=00:00:00:01:02:04
>>>     -ls2_p1_ip=2002::2
>>>     -
>>>     -ls3_p1_mac=00:00:00:01:02:05
>>>     -
>>>     -# Create a drop policy
>>>     -ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 &&
>>>     ip6.dst==2002::/64" drop
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>>     | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>     ip6.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Check if packet hit the drop policy
>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
>>>     -    grep "priority=10" | \
>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Expected to drop the packet.
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>>     -rcvd_packet=`cat vif2.packets`
>>>     -AT_FAIL_IF([rcvd_packet = ""])
>>>     -
>>>     -# Override drop policy with allow
>>>     -ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 &&
>>>     ip6.dst==2002::/64" allow
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>>     | wc -l], [0], [dnl
>>>     -2
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>     ip6.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Check if packet hit the allow policy
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>     -    grep "2001" | \
>>>     -    grep "priority=20" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>>     ip6.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>>     -
>>>     -# Override allow policy with reroute
>>>     -ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 &&
>>>     ip6.dst==2002::/64" reroute 2003::2
>>>     -
>>>     -# Check logical flow
>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>     -    grep "2001" | \
>>>     -    grep "priority=30" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -# Send packet.
>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>     eth.dst==$ls1_ro_mac &&
>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>     ip6.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -echo "southbound flows"
>>>     -
>>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>>     -echo "ovs flows"
>>>     -ovs-ofctl dump-flows br-int
>>>     -# Check if packet hit the allow policy
>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
>>>     -    grep "priority=30" | \
>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>     -1
>>>     -])
>>>     -echo "packet hit reroute policy"
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>>     ip6.dst==$ls2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>>     -
>>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>>     -
>>>     -OVN_CLEANUP([pbr-hv])
>>>     -AT_CLEANUP
>>>     -
>>>     -# 1 hypervisor, 1 port
>>>     -# make sure that the port state is properly set to up and back 
>>> down
>>>     -# when created and deleted.
>>>     -AT_SETUP([ovn -- port state up and down])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl lsp-add ls1 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1 ovs-vsctl add-br br-phys
>>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>     -
>>>     -as hv1 ovs-vsctl del-port br-int vif1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# 1 hypervisor, 1 port
>>>     -# make sure that the OF rules created to support a datapath are
>>>     added/cleared
>>>     -# when logical switch is created and removed.
>>>     -AT_SETUP([ovn -- datapath rules added/removed])
>>>     -AT_KEYWORDS([cleanup])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1 ovs-vsctl add-br br-phys
>>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -# This shell function checks if OF rules in br-int have clauses
>>>     -# related to OVN datapaths. The caller determines if it should 
>>> find
>>>     -# a match in the output, or not.
>>>     -#
>>>     -# EXPECT_DATAPATH param determines whether flows that refer to
>>>     -#                 datapath to should be present or not. 0 means
>>>     -#                 they should not be.
>>>     -# STAGE_INFO param is a simple string to help identify the stage
>>>     -#            in the test when this function was invoked.
>>>     -test_datapath_in_of_rules() {
>>>     -    local expect_datapath=$1 stage_info=$2
>>>     -    echo "------ ovn-nbctl show ${stage_info} ------"
>>>     -    ovn-nbctl show
>>>     -    echo "------ ovn-sbctl show ${stage_info} ------"
>>>     -    ovn-sbctl show
>>>     -    echo "------ OF rules ${stage_info} ------"
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
>>>     -    # if there is a datapath mentioned in the output, check for 
>>> the
>>>     -    # magic keyword that represents one, based on the exit 
>>> status of
>>>     -    # a quiet grep
>>>     -    if test $expect_datapath != 0; then
>>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [0], 
>>> [ignore-nolog])
>>>     -    else
>>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [1], 
>>> [ignore-nolog])
>>>     -    fi
>>>     -}
>>>     -
>>>     -test_datapath_in_of_rules 0 "before ls+port create"
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl lsp-add ls1 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>>     -
>>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>     -
>>>     -test_datapath_in_of_rules 1 "after port is bound"
>>>     -
>>>     -as hv1 ovs-vsctl del-port br-int vif1
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>>     -
>>>     -ovn-nbctl lsp-set-addresses lp1
>>>     -ovn-nbctl lsp-del lp1
>>>     -ovn-nbctl ls-del ls1
>>>     -
>>>     -# wait for earlier changes to take effect
>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>     -
>>>     -# ensure OF rules are no longer present. There used to be a bug 
>>> here.
>>>     -test_datapath_in_of_rules 0 "after lport+ls removal"
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- nd_na ])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -#TODO: since patch port for IPv6 logical router port is not ready
>>>     not,
>>>     -#  so we are not going to test vifs on different lswitches 
>>> cases. Try
>>>     -#  to update for that once relevant stuff implemented.
>>>     -
>>>     -# In this test cases we create 1 lswitch, it has 2 VIF ports 
>>> attached
>>>     -# with. NS packet we test, from one VIF for another VIF, will be
>>>     replied
>>>     -# by local ovn-controller, but not by target VIF.
>>>     -
>>>     -# Create hypervisors and logical switch lsw0.
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3
>>>     fd81:ce49:a948:0:f816:3eff:fe94:598"
>>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98
>>>     192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
>>>     -
>>>     -# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>     external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap
>>>     options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
>>>     fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae
>>>     192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>>     -
>>>     -# Add ACL rule for ICMPv6 on lsw0
>>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  
>>> allow-related
>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>>     icmp6'  allow-related
>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>>     icmp6'  allow-related
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv1${1%?}
>>>     -}
>>>     -for i in 1 2; do
>>>     -    : > $i.expected
>>>     -done
>>>     -
>>>     -# Complete Neighbor Solicitation packet and Neighbor
>>>     Advertisement packet
>>>     -# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
>>>     -# vif2 will not receive NS packet, since ovn-controller will
>>>     reply for it.
>>> -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598 
>>>
>>> -na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae 
>>>
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
>>>     -echo $na_packet >> 1.expected
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -
>>>     -for i in 1 2; do
>>>     -    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- address sets modification/removal smoke test])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
>>>     -ovn-nbctl set Address_Set $row name=set1
>>>     addresses=\"1.1.1.1,1.1.1.2\"
>>>     -ovn-nbctl destroy Address_Set $row
>>>     -
>>>     -sleep 1
>>>     -
>>>     -# A bug previously existed in the address set support code
>>>     -# that caused ovn-controller to crash after an address set
>>>     -# was updated and then removed.  This test case ensures
>>>     -# that ovn-controller is at least still running after
>>>     -# creating, updating, and deleting an address set.
>>>     -AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ipam])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Add a port to a switch that does not have a subnet set, then
>>>     set the
>>>     -# subnet which should result in an address being allocated for
>>>     the port.
>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>>     subnet=192.168.1.0/24
>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>     get Logical-Switch-Port p0 dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>>     -])
>>>     -
>>>     -# Add 9 more ports to sw0, addresses should all be unique.
>>>     -for n in `seq 1 9`; do
>>>     -    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses
>>>     "p$n" dynamic
>>>     -done
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p1
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:04 192.168.1.3"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p2
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:05 192.168.1.4"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p3
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:06 192.168.1.5"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p4
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:07 192.168.1.6"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p5
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:08 192.168.1.7"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p6
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:09 192.168.1.8"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p7
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:0a 192.168.1.9"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p8
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:0b 192.168.1.10"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p9
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:0c 192.168.1.11"
>>>     -])
>>>     -
>>>     -# Trying similar tests with a second switch. MAC addresses should
>>>     be unique
>>>     -# across both switches but IP's only need to be unique within the
>>>     same switch.
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw1 other_config
>>>     subnet=192.168.1.0/24
>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>     get Logical-Switch-Port p10 dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:0d 192.168.1.2"
>>>     -])
>>>     -
>>>     -for n in `seq 11 19`; do
>>>     -    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses
>>>     "p$n" dynamic
>>>     -done
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p11
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:0e 192.168.1.3"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p12
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:0f 192.168.1.4"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p13
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:10 192.168.1.5"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p14
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:11 192.168.1.6"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p15
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:12 192.168.1.7"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p16
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:13 192.168.1.8"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p17
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:14 192.168.1.9"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p18
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:15 192.168.1.10"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p19
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:16 192.168.1.11"
>>>     -])
>>>     -
>>>     -# Change a port's address to test for multiple ip's for a single
>>>     address entry
>>>     -# and addresses set by the user.
>>>     -ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2
>>>     192.168.1.12 192.168.1.14"
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p20
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:18 192.168.1.13"
>>>     -])
>>>     -
>>>     -# Test for logical router port address management.
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
>>>     -network="192.168.1.1/24 <http://192.168.1.1/24>"
>>>     mac=\"0a:00:00:a8:01:19\" \
>>>     --- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
>>>     --- set Logical_Switch_Port rp-sw0 type=router 
>>> options:router-port=sw0
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p21
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:1a 192.168.1.15"
>>>     -])
>>>     -
>>>     -# Test for address reuse after logical port is deleted.
>>>     -ovn-nbctl lsp-del p0
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p23
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:03 192.168.1.2"
>>>     -])
>>>     -
>>>     -# Test for multiple addresses to one logical port.
>>>     -ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
>>>     -"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p26
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:17 192.168.1.16"
>>>     -])
>>>     -
>>>     -# Test for exhausting subnet address space.
>>>     -ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config
>>>     subnet=172.16.1.0/30
>>>     -ovn-nbctl <http://172.16.1.0/30-ovn-nbctl> --wait=sb lsp-add sw2
>>>     p27 -- lsp-set-addresses p27 dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p27
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:10:01:03 172.16.1.2"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p28
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:00:00:01"
>>>     -])
>>>     -
>>>     -# Test that address management does not add duplicate MAC for
>>>     lsp/lrp peers.
>>>     -ovn-nbctl create Logical_Router name=R2
>>>     -ovn-nbctl ls-add sw3
>>>     -ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
>>>     -"0a:00:00:a8:01:18"
>>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
>>>     -network="192.168.2.1/24 <http://192.168.2.1/24>"
>>>     mac=\"0a:00:00:a8:01:18\" \
>>>     --- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
>>>     --- set Logical_Switch_Port rp-sw3 type=router 
>>> options:router-port=sw3
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 
>>> dynamic
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p30
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:1d 192.168.1.17"
>>>     -])
>>>     -
>>>     -# Test static MAC address with dynamically allocated IP
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
>>>     -"fe:dc:ba:98:76:54 dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>     dynamic_addresses], [0],
>>>     -     ["fe:dc:ba:98:76:54 192.168.1.18"
>>>     -])
>>>     -
>>>     -# Update the static MAC address with dynamically allocated IP and
>>>     check
>>>     -# if the MAC address is updated in
>>>     'Logical_Switch_Port.dynamic_adddresses'
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 
>>> dynamic"
>>>     -
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>     dynamic_addresses], [0],
>>>     -     ["fe:dc:ba:98:76:55 192.168.1.18"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:1e 192.168.1.18"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 
>>> dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>     dynamic_addresses], [0],
>>>     -     ["fe:dc:ba:98:76:56 192.168.1.18"
>>>     -])
>>>     -
>>>     -
>>>     -# Test the exclude_ips from the IPAM list
>>>     -ovn-nbctl --wait=sb set logical_switch sw0 \
>>>     -other_config:exclude_ips="192.168.1.19 192.168.1.21
>>>     192.168.1.23..192.168.1.50"
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
>>>     -"dynamic"
>>>     -# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p32
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:1e 192.168.1.20"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
>>>     -"dynamic"
>>>     -# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p33
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:1f 192.168.1.22"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
>>>     -"dynamic"
>>>     -# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is
>>>     excluded.
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p34
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:34 192.168.1.51"
>>>     -])
>>>     -
>>>     -# Now clear the exclude_ips list. 192.168.1.19 should be assigned.
>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>     other_config:exclude_ips="invalid"
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
>>>     -"dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p35
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:20 192.168.1.19"
>>>     -])
>>>     -
>>>     -# Set invalid data in exclude_ips list. It should be ignored.
>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>     other_config:exclude_ips="182.168.1.30"
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
>>>     -"dynamic"
>>>     -# 192.168.1.21 should be assigned as that's the next free one.
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:21 192.168.1.21"
>>>     -])
>>>     -
>>>     -# Clear the dynamic addresses assignment request.
>>>     -ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>>     dynamic_addresses], [0],
>>>     -         [[[]]
>>>     -])
>>>     -
>>>     -# Set IPv6 prefix
>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>     other_config:ipv6_prefix="aef0::"
>>>     -ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
>>>     -"dynamic"
>>>     -
>>>     -# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6
>>>     should be
>>>     -# - aef0::800:ff:fe00:26 (EUI64)
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p37
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb ls-add sw4
>>>     -ovn-nbctl --wait=sb set Logical-switch sw4
>>>     other_config:ipv6_prefix="bef0::" \
>>>     --- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
>>>     <http://192.168.2.0/30>
>>>     -ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
>>>     -"dynamic"
>>>     -
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p38
>>>     dynamic_addresses], [0],
>>>     -     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
>>>     -"f0:00:00:00:10:12 dynamic"
>>>     -
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p39
>>>     dynamic_addresses], [0],
>>>     -     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
>>>     -])
>>>     -
>>>     -# Test the case where IPv4 addresses are exhausted and IPv6
>>>     prefix is set
>>>     -# p40 should not have an IPv4 address since the pool is exhausted
>>>     -ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
>>>     -"dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p40
>>>     dynamic_addresses], [0],
>>>     -         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
>>>     -])
>>>     -
>>>     -# Test dynamic changes on switch ports.
>>>     -#
>>>     -ovn-nbctl --wait=sb ls-add sw5
>>>     -ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
>>>     -"dynamic"
>>>     -# p41 will start with nothing
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         [[[]]
>>>     -])
>>>     -
>>>     -# Set a subnet. Now p41 should have an ipv4 address, too
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>>     subnet=192.168.1.0/24
>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>>     -         ["0a:00:00:a8:01:22 192.168.1.2"
>>>     -])
>>>     -
>>>     -# Clear the other_config. The IPv4 address should be gone
>>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         [[[]]
>>>     -])
>>>     -
>>>     -# Set an IPv6 prefix. Now p41 should have an IPv6 address.
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>>     other_config:ipv6_prefix="aef0::"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
>>>     -])
>>>     -
>>>     -# Change the MAC address to a static one. The IPv6 address should
>>>     update.
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b 
>>> dynamic"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
>>>     -])
>>>     -
>>>     -# Change the IPv6 prefix. The IPv6 address should update.
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>>     other_config:ipv6_prefix="bef0::"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
>>>     -])
>>>     -
>>>     -# Clear the other_config. The IPv6 address should be gone
>>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         [[[]]
>>>     -])
>>>     -
>>>     -# Set the subnet again. Now p41 should get the IPv4 address again.
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>>     subnet=192.168.1.0/24
>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>>     -         ["f0:00:00:00:10:2b 192.168.1.2"
>>>     -])
>>>     -
>>>     -# Add an excluded IP address that conflicts with p41. p41 should
>>>     update.
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
>>>     -exclude_ips="192.168.1.2"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         ["f0:00:00:00:10:2b 192.168.1.3"
>>>     -])
>>>     -
>>>     -# Add static ip address
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
>>>     -ovn-nbctl list Logical-Switch-Port p41
>>>     -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
>>>     -"dynamic 192.168.1.101"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>     dynamic_addresses], [0],
>>>     -         ["0a:00:00:a8:01:65 192.168.1.100"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p42
>>>     dynamic_addresses], [0],
>>>     -         ["0a:00:00:a8:01:66 192.168.1.101"
>>>     -])
>>>     -
>>>     -# define a mac address prefix
>>>     -ovn-nbctl ls-add sw6
>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>     options:mac_prefix="00:11:22:33:44:55"
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw6
>>>     other_config:subnet=192.168.100.0/24
>>>     -for <http://192.168.100.0/24-for> n in $(seq 1 3); do
>>>     -    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses
>>>     "p5$n" dynamic
>>>     -done
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p51
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:a8:64:03 192.168.100.2"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p52
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:a8:64:04 192.168.100.3"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p53
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:a8:64:05 192.168.100.4"
>>>     -])
>>>     -
>>>     -# verify configuration order does not break IPAM/MACAM
>>>     -ovn-nbctl ls-add sw7
>>>     -for n in $(seq 1 3); do
>>>     -    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses
>>>     "p7$n" dynamic
>>>     -done
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw7
>>>     other_config:ipv6_prefix="bef0::"
>>>     -p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 
>>> dynamic_addresses)
>>>     -p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 
>>> dynamic_addresses)
>>>     -p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 
>>> dynamic_addresses)
>>>     -AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
>>>     -AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
>>>     -AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
>>>     -
>>>     -# request to assign mac only
>>>     -#
>>>     -ovn-nbctl ls-add sw8
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw8 
>>> other_config:mac_only=true
>>>     -for n in $(seq 1 3); do
>>>     -    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses
>>>     "p8$n" dynamic
>>>     -done
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p81
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:00:00:06"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p82
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:00:00:07"
>>>     -])
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p83
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:00:00:08"
>>>     -])
>>>     -
>>>     -# clear mac_prefix and check it is allocated in a random manner
>>>     -ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
>>>     -ovn-nbctl ls-add sw9
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw9 
>>> other_config:mac_only=true
>>>     -ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 
>>> dynamic
>>>     -
>>>     -mac_prefix=$(ovn-nbctl --wait=sb get NB_Global .
>>>     options:mac_prefix | tr -d \")
>>>     -port_addr=$(ovn-nbctl get Logical-Switch-Port p91
>>>     dynamic_addresses | tr -d \")
>>>     -AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
>>>     -
>>>     -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
>>>     -ovn-nbctl ls-add sw10
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>>     other_config:ipv6_prefix="ae01::"
>>>     -ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101
>>>     "dynamic ae01::1"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p101
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:00:00:0a ae01::1"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>>     other_config:subnet=192.168.110.0/24
>>>     -ovn-nbctl <http://192.168.110.0/24-ovn-nbctl> --wait=sb lsp-add
>>>     sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 
>>> ae01::2"
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p102
>>>     dynamic_addresses], [0],
>>>     -    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
>>>     -])
>>>     -
>>>     -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 northd-backup
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ipam connectivity])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -# Test for a ping using dynamically allocated addresses.
>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>     -ovn-nbctl ls-add foo -- add Logical_Switch foo other_config
>>>     subnet=192.168.1.0/24
>>>     -ovn-nbctl <http://192.168.1.0/24-ovn-nbctl> ls-add alice -- add
>>>     Logical_Switch alice other_config subnet=192.168.2.0/24
>>>     <http://192.168.2.0/24>
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -          options:router-port=foo \
>>>     -          -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect alice to R1
>>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice type=router \
>>>     -          options:router-port=alice 
>>> addresses=\"00:00:00:01:02:04\"
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl --wait=sb lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "dynamic"
>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>     foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl --wait=sb lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "dynamic"
>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>     alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
>>>     -
>>>     -# Create logical port foo2 in foo
>>>     -ovn-nbctl --wait=sb lsp-add foo foo2 \
>>>     --- lsp-set-addresses foo2 "dynamic"
>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>     foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
>>>     -
>>>     -# Create a hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=foo2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>     -    set interface hv1-vif3 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>     -    ofport-request=3
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and foo2
>>>     -src_mac="0a0000a80103"
>>>     -dst_mac="0a0000a80104"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="0a0000a80103"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Packet to Expect at foo2
>>>     -src_mac="0a0000a80103"
>>>     -dst_mac="0a0000a80104"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>> -expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > received1.packets
>>>     -echo $expected > expout
>>>     -AT_CHECK([cat received1.packets], [0], [expout])
>>>     -
>>>     -# Packet to Expect at alice1
>>>     -src_mac="000000010204"
>>>     -dst_mac="0a0000a80203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif3-tx.pcap > received2.packets
>>>     -echo $expected > expout
>>>     -AT_CHECK([cat received2.packets], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ovs-vswitchd restart])
>>>     -AT_KEYWORDS([vswitchd])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>> 10.0.0.4"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -sleep 2
>>>     -
>>>     -as hv1 ovs-vsctl show
>>>     -
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
>>>     -
>>>     -echo "Total flows before vswitchd restart = " $total_flows
>>>     -
>>>     -# Code taken from ovs-save utility
>>>     -save_flows () {
>>>     -    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
>>>     -    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
>>>     -            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> 
>>> restore_flows.sh
>>>     -    echo "EOF" >> restore_flows.sh
>>>     -}
>>>     -
>>>     -restart_vswitchd () {
>>>     -    restore_flows=$1
>>>     -
>>>     -    if test $restore_flows = true; then
>>>     -        save_flows
>>>     -    fi
>>>     -
>>>     -    as hv1
>>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>     -
>>>     -    if test $restore_flows = true; then
>>>     -        as hv1
>>>     -        ovs-vsctl --no-wait set open_vswitch .
>>>     other_config:flow-restore-wait="true"
>>>     -    fi
>>>     -
>>>     -    as hv1
>>>     -    start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>>     -vofproto_dpif -vunixctl
>>>     -    ovs-ofctl dump-flows br-int
>>>     -
>>>     -    if test $restore_flows = true; then
>>>     -        sh ./restore_flows.sh
>>>     -        echo "Flows after restore"
>>>     -        as hv1
>>>     -        ovs-ofctl dump-flows br-int
>>>     -        ovs-vsctl --no-wait --if-exists remove open_vswitch .
>>>     other_config \
>>>     -            flow-restore-wait="true"
>>>     -    fi
>>>     -}
>>>     -
>>>     -# Save the flows, restart vswitchd and restore the flows
>>>     -restart_vswitchd true
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>>     | wc -l`
>>>     -    echo "Total flows after vswitchd restart = "
>>>     $total_flows_after_restart
>>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>>     -])
>>>     -
>>>     -# Restart vswitchd without restoring
>>>     -restart_vswitchd false
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>>     | wc -l`
>>>     -    echo "Total flows after vswitchd restart = "
>>>     $total_flows_after_restart
>>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>>     -])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send arp for nexthop])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Topology: Two LSs - ls1 and ls2 are connected via router r0
>>>     -
>>>     -# Create logical switches
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -
>>>     -# Create  router
>>>     -ovn-nbctl create Logical_Router name=lr0
>>>     -
>>>     -# Add router ls1p1 port to gateway router
>>>     -ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
>>>     -ovn-nbctl <http://192.168.0.1/24-ovn-nbctl> lsp-add ls1 ls1lp1 --
>>>     set Logical_Switch_Port ls1lp1  \
>>>     -    type=router options:router-port=lrp-ls1lp1 \
>>>     -    addresses='"f0:00:00:00:00:01 192.168.0.1"'
>>>     -
>>>     -# Add router ls2p2 port to gateway router
>>>     -ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
>>>     -ovn-nbctl <http://192.168.1.1/24-ovn-nbctl> lsp-add ls2 ls2lp1 --
>>>     set Logical_Switch_Port ls2lp1 \
>>>     -    type=router options:router-port=lrp-ls2lp1 \
>>>     -    addresses='"f0:00:00:00:00:02 192.168.1.1"'
>>>     -
>>>     -# Set default gateway (nexthop) to 192.168.1.254
>>>     -ovn-nbctl lr-route-add lr0 "0.0.0.0/0 <http://0.0.0.0/0>"
>>>     192.168.1.254 lrp-ls2lp1
>>>     -
>>>     -# Create logical port ls1lp2 in ls1
>>>     -ovn-nbctl lsp-add ls1 ls1lp2 \
>>>     --- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
>>>     -
>>>     -# Create logical port ls2lp2 in ls2
>>>     -ovn-nbctl lsp-add ls2 ls2lp2 \
>>>     --- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
>>>     -    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
>>>     -    options:tx_pcap=hv1/ls1lp2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
>>>     -    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
>>>     -    options:tx_pcap=hv1/ls2lp2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -ovn-sbctl list chassis
>>>     -ovn-sbctl list encap
>>>     -echo "---------------------"
>>>     -
>>>     -echo "------Flows dump-----"
>>>     -as hv1
>>>     -ovs-ofctl dump-flows
>>>     -echo "---------------------"
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -src_mac="f00000000003"
>>>     -dst_mac="f00000000001"
>>>     -src_ip=`ip_to_hex 192 168 0 2`
>>>     -dst_ip=`ip_to_hex 8 8 8 8`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -# Send IP packet destined to 8.8.8.8 from lsp1lp2
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
>>>     -
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -# ARP packet should be received with Target IP Address set to
>>>     192.168.1.254 and
>>>     -# not 8.8.8.8
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ls2lp2-tx.pcap | trim_zeros > packets
>>> -expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe" 
>>>
>>>     -echo $expected > expout
>>>     -AT_CHECK([cat packets], [0], [expout])
>>>     -cat packets
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -# Create logical switch
>>>     -ovn-nbctl ls-add ls0
>>>     -# Create gateway router
>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>     -# Add router port to gateway router
>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>     <http://192.168.0.1/24>
>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>>     -    type=router options:router-port=lrp0
>>>     addresses='"f0:00:00:00:00:01"'
>>>     -# Add nat-address option
>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="f0:00:00:00:00:01 192.168.0.2"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0
>>>     -
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>> network_name=physnet1])
>>>     -
>>>     -# Wait until the patch ports are created in hv1 to connect br-int
>>>     to br-eth0
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>     -
>>>     -# Wait for packet to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>
>>>     -echo $expected > expout
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>
>>>     -echo $expected >> expout
>>>     -AT_CHECK([sort packets], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in
>>>     localnet])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -# Create logical switch
>>>     -ovn-nbctl ls-add ls0
>>>     -# Create gateway router
>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>     -# Add router port to gateway router
>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>     <http://192.168.0.1/24>
>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>>     -    type=router options:router-port=lrp0
>>>     addresses='"f0:00:00:00:00:01"'
>>>     -# Add nat-address option
>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="router"
>>>     -# Add NAT rules
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>>     <http://10.0.0.0/24>])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
>>>     -# Add load balancers
>>>     -AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80
>>>     <http://192.168.0.3:80> 10.0.0.2:80
>>>     <http://10.0.0.2:80>,10.0.0.3:80 <http://10.0.0.3:80>])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>     -AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080
>>>     <http://192.168.0.3:8080> 10.0.0.2:8080
>>>     <http://10.0.0.2:8080>,10.0.0.3:8080 <http://10.0.0.3:8080>])
>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl \
>>>     -    -- add-br br-phys \
>>>     -    -- add-br br-eth0
>>>     -
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>> network_name=physnet1])
>>>     -
>>>     -# Wait until the patch ports are created to connect br-int to 
>>> br-eth0
>>>     -OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>     -
>>>     -ovn-sbctl list port_binding lrp0-rp
>>>     -echo "*****"
>>>     -ovn-nbctl list logical_switch_port lrp0-rp
>>>     -ovn-nbctl list logical_router_port lrp0
>>>     -ovn-nbctl show
>>>     -# Wait for packet to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>
>>>     -echo $expected > expout
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>
>>>     -echo $expected >> expout
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003" 
>>>
>>>     -echo $expected >> expout
>>>     -AT_CHECK([sort packets], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- delete mac bindings])
>>>     -ovn_start
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl -- add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -# Create logical switch ls0
>>>     -ovn-nbctl ls-add ls0
>>>     -# Create ports lp0, lp1 in ls0
>>>     -ovn-nbctl lsp-add ls0 lp0
>>>     -ovn-nbctl lsp-add ls0 lp1
>>>     -ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
>>>     -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
>>>     -dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" |
>>>     cut -f2 -d " "`
>>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>>     logical_port=lp0 mac="mac1"
>>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>>     logical_port=lp1 mac="mac2"
>>>     -ovn-sbctl find MAC_Binding
>>>     -# Delete port lp0 and check that its MAC_Binding is deleted.
>>>     -ovn-nbctl lsp-del lp0
>>>     -ovn-sbctl find MAC_Binding
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0
>>>     | wc -l` = 0])
>>>     -# Delete logical switch ls0 and check that its MAC_Binding is
>>>     deleted.
>>>     -ovn-nbctl ls-del ls0
>>>     -ovn-sbctl find MAC_Binding
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- conntrack zone allocation])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# 2 logical switches "foo" (192.168.1.0/24
>>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>>     <http://172.16.1.0/24>)
>>>     -# connected to a router R1.
>>>     -# foo has foo1 to act as a client.
>>>     -# bar has bar1, bar2, bar3 to act as servers.
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -for i in foo1 bar1 bar2 bar3; do
>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>     -        set interface $i external-ids:iface-id=$i \
>>>     -        options:tx_pcap=hv1/$i-tx.pcap \
>>>     -        options:rxq_pcap=hv1/$i-rx.pcap
>>>     -done
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port bar1, bar2 and bar3 in bar
>>>     -for i in `seq 1 3`; do
>>>     -    ip=`expr $i + 1`
>>>     -    ovn-nbctl lsp-add bar bar$i \
>>>     -    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
>>>     -done
>>>     -
>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep
>>>     REG13 | wc -l` -eq 4])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- tag allocation])
>>>     -ovn_start
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>     -
>>>     -dnl When a tag is provided, no allocation is done
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>>     -])
>>>     -dnl The same 'tag' gets created in southbound database.
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c0"], [0], [3
>>>     -])
>>>     -
>>>     -dnl Allocate tags and see it getting created in both NB and SB
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c1"], [0], [1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c2"], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c3"], [0], [4
>>>     -])
>>>     -
>>>     -dnl A different parent.
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c4"], [0], [1
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c5"], [0], [2
>>>     -])
>>>     -
>>>     -dnl Delete a logical port and create a new one.
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c6"], [0], [1
>>>     -])
>>>     -
>>>     -dnl Restart northd to see that the same allocation remains.
>>>     -as northd
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>     -start_daemon ovn-northd \
>>>     -    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>     -    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>     -
>>>     -dnl Create a switch to make sure that ovn-northd has run through
>>>     the main loop.
>>>     -AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>     -])
>>>     -
>>>     -dnl Create a switch port with a tag that has already been 
>>> allocated.
>>>     -dnl It should go through fine with a duplicate tag.
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="c7"], [0], [2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>     -])
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add ls2])
>>>     -dnl When there is no parent_name provided (for say, 'localnet'),
>>>     'tag_request'
>>>     -dnl gets copied to 'tag'
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
>>>     -])
>>>     -dnl The same 'tag' gets created in southbound database.
>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>     port_binding \
>>>     -logical_port="local0"], [0], [25
>>>     -])
>>>     -dnl If 'tag_request' is 0 for localnet, nothing gets written to 
>>> 'tag'
>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1])
>>>     -dnl change the tag_request.
>>>     -AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1
>>>     tag_request=50])
>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on
>>>     localnet])
>>>     -ovn_start
>>>     -ovn-nbctl ls-add lsw0
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -    ovs-vsctl add-br br-eth0
>>>     -    AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>     -done
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>> network_name=physnet1])
>>>     -
>>>     -
>>>     -# Create 3 vifs.
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>>     "f0:00:00:00:00:01 192.168.1.1"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>>     "f0:00:00:00:00:01"])
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2
>>>     "f0:00:00:00:00:02 192.168.1.2"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif2
>>>     "f0:00:00:00:00:02"])
>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif3
>>>     "f0:00:00:00:00:03 192.168.1.3"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif3
>>>     "f0:00:00:00:00:03"])
>>>     -
>>>     -# Bind the localvif1 to hv1.
>>>     -as hv1
>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>>     localvif1 external_ids:iface-id=localvif1])
>>>     -
>>>     -# On hv1, check that there are no flows outputting bcast to tunnel
>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>     -
>>>     -# On hv2, check that no flow outputs bcast to tunnel to hv1.
>>>     -as hv2
>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>     -
>>>     -# Now bind vif2 on hv2.
>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface
>>>     localvif2 external_ids:iface-id=localvif2])
>>>     -
>>>     -# At this point, the broadcast flow on vif2 should be deleted.
>>>     -# because, there is now a localnet vif bound (table=32
>>>     programming logic)
>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>     -
>>>     -# Verify that the local net patch port exists on hv2.
>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>     -
>>>     -# Now bind vif3 on hv2.
>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface
>>>     localvif3 external_ids:iface-id=localvif3])
>>>     -
>>>     -# Verify that the local net patch port still exists on hv2
>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>     -
>>>     -# Delete localvif2
>>>     -AT_CHECK([ovn-nbctl lsp-del localvif2])
>>>     -
>>>     -# Verify that the local net patch port still exists on hv2,
>>>     -# because, localvif3 is still bound.
>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -AT_SETUP([ovn -- ACL logging])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -for i in lp1 lp2; do
>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>     -        set interface $i external-ids:iface-id=$i \
>>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>>     -done
>>>     -
>>>     -lp1_mac="f0:00:00:00:00:01"
>>>     -lp1_ip="192.168.1.2"
>>>     -
>>>     -lp2_mac="f0:00:00:00:00:02"
>>>     -lp2_ip="192.168.1.3"
>>>     -
>>>     -ovn-nbctl ls-add lsw0
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>>     -ovn-nbctl --wait=sb sync
>>>     -
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>>     -ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0
>>>     to-lport 1000 'tcp.dst==81' drop
>>>     -
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
>>>     -ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0
>>>     to-lport 1000 'tcp.dst==83' allow
>>>     -
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
>>>     -ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85'
>>>     allow-related
>>>     -
>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
>>>     -ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow
>>>     acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
>>>     -
>>>     -ovn-sbctl dump-flows
>>>     -
>>>     -
>>>     -# Send packet that should be dropped without logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should be dropped with logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should be allowed without logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should be allowed with logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should allow related flows without logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should allow related flows with logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should be rejected without logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Send packet that should be rejected with logging.
>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>> eth.dst==$lp2_mac &&
>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>> ip4.dst==$lp2_ip &&
>>>     -        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log'
>>>     hv/ovn-controller.log) ])
>>>     -
>>>     -AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed
>>>     's/.*name=/name=/'], [0], [dnl
>>>     -name="drop-flow", verdict=drop, severity=alert:
>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn 
>>>
>>>     -name="allow-flow", verdict=allow, severity=info:
>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn 
>>>
>>>     -name="<unnamed>", verdict=allow, severity=info:
>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn 
>>>
>>>     -name="reject-flow", verdict=reject, severity=alert:
>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn 
>>>
>>>     -])
>>>     -
>>>     -OVN_CLEANUP([hv])
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -AT_SETUP([ovn -- ACL rate-limited logging])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -for i in lp1 lp2; do
>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>     -        set interface $i external-ids:iface-id=$i \
>>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>>     -done
>>>     -
>>>     -lp1_mac="f0:00:00:00:00:01"
>>>     -lp1_ip="192.168.1.2"
>>>     -
>>>     -lp2_mac="f0:00:00:00:00:02"
>>>     -lp2_ip="192.168.1.3"
>>>     -
>>>     -ovn-nbctl ls-add lsw0
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>>     -ovn-nbctl --wait=sb sync
>>>     -
>>>     -
>>>     -# Add an ACL that rate-limits logs at 10 per second.
>>>     -ovn-nbctl meter-add http-rl1 drop 10 pktps
>>>     -ovn-nbctl --log --severity=alert --meter=http-rl1
>>>     --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>>     -
>>>     -# Add an ACL that rate-limits logs at 5 per second.
>>>     -ovn-nbctl meter-add http-rl2 drop 5 pktps
>>>     -ovn-nbctl --log --severity=alert --meter=http-rl2
>>>     --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
>>>     -
>>>     -# Add an ACL that doesn't rate-limit logs.
>>>     -ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0
>>>     to-lport 1000 'tcp.dst==82' drop
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -# For each ACL, send 100 packets.
>>>     -for i in `seq 1 100`; do
>>>     -    ovs-appctl netdev-dummy/receive lp1
>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)' 
>>>
>>>     -
>>>     -    ovs-appctl netdev-dummy/receive lp1
>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)' 
>>>
>>>     -
>>>     -    ovs-appctl netdev-dummy/receive lp1
>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)' 
>>>
>>>     -done
>>>     -
>>>     -# The rate at which packets are sent is highly system-dependent,
>>>     so we
>>>     -# can't count on precise drop counts.  To work around that, we 
>>> just
>>>     -# check that exactly 100 "http-acl3" actions were logged and that
>>>     there
>>>     -# were more "http-acl1" actions than "http-acl2" ones.
>>>     -OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3'
>>>     hv/ovn-controller.log) ])
>>>     -
>>>     -# On particularly slow or overloaded systems, the transmission
>>>     rate may
>>>     -# be lower than the configured meter rate.  To prevent false test
>>>     -# failures, we check the duration count of the meter, and if it's
>>>     -# greater than nine seconds, just skip the test.
>>>     -d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep
>>>     "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s 
>>> .*/\1/')
>>>     -
>>>     -echo "Meter duration: $d_secs"
>>>     -AT_SKIP_IF([test $d_secs -gt 9])
>>>     -
>>>     -# Print some information that may help debugging.
>>>     -as hv ovs-appctl -t ovn-controller meter-table-list
>>>     -as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
>>>     -
>>>     -n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
>>>     -n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
>>>     -n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
>>>     -
>>>     -AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
>>>     -AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
>>>     -
>>>     -OVN_CLEANUP([hv])
>>>     -AT_CLEANUP
>>>     -
>>>     -
>>>     -AT_SETUP([ovn -- DSCP marking and meter check])
>>>     -AT_KEYWORDS([ovn])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add lsw0
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp3
>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>     -ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
>>>     -ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
>>>     -ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
>>>     -ovn-nbctl --wait=sb sync
>>>     -net_add n1
>>>     -sim_add hv
>>>     -as hv
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap
>>>     options:rxq_pcap=vif1-rx.pcap ofport-request=1
>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>     external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap
>>>     options:rxq_pcap=vif2-rx.pcap ofport-request=2
>>>     -
>>>     -AT_CAPTURE_FILE([trace])
>>>     -ovn_trace () {
>>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>>     -}
>>>     -
>>>     -# Extracts nw_tos from the final flow from ofproto/trace output
>>>     and prints
>>>     -# it on stdout.  Prints "none" if no nw_tos was included.
>>>     -get_final_nw_tos() {
>>>     -    if flow=$(grep '^Final flow:' stdout); then :; else
>>>     -       # The output didn't have a final flow.
>>>     -       return 99
>>>     -    fi
>>>     -
>>>     -    tos=$(echo "$flow" | sed -n
>>>     's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
>>>     -    case $tos in
>>>     -        '') echo none ;;
>>>     -        *) echo $tos ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -# check_tos TOS
>>>     -#
>>>     -# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set
>>>     to TOS.
>>>     -check_tos() {
>>>     -    # First check with ovn-trace for logical flows.
>>>     -    echo "checking for tos $1"
>>>     -    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
>>>     -     echo 'output("lp2");') > expout
>>>     -    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src
>>>     == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src ==
>>>     1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
>>>     -
>>>     -    # Then re-check with ofproto/trace for a physical packet.
>>>     -    AT_CHECK([ovs-appctl ofproto/trace br-int
>>> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'], 
>>>
>>>     [0], [stdout-nolog])
>>>     -    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
>>>     -])
>>>     -}
>>>     -
>>>     -# check at L2
>>>     -AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src ==
>>>     f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0],
>>>     [output("lp2");
>>>     -])
>>>     -AT_CHECK([ovs-appctl ofproto/trace br-int
>>> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'],
>>>     [0], [stdout-nolog])
>>>     -AT_CHECK([get_final_nw_tos], [0], [none
>>>     -])
>>>     -
>>>     -# check at L3 without dscp marking
>>>     -check_tos 0
>>>     -
>>>     -# Mark DSCP with a valid value
>>>     -qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS
>>>     priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\
>>>     is_chassis_resident(\"lp1\")" direction="from-lport" -- set
>>>     Logical_Switch lsw0 qos_rules=@lp1-qos)
>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>>     -])
>>>     -check_tos 48
>>>     -
>>>     -# check at hv without qos meter
>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>     meter | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# Update the meter rate
>>>     -ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
>>>     -
>>>     -# check at hv with a qos meter table
>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>     rate=100 | wc -l], [0], [1
>>>     -])
>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>     meter | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# Update the DSCP marking
>>>     -ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
>>>     -check_tos 63
>>>     -
>>>     -# Update the meter rate
>>>     -ovn-nbctl --wait=hv set QoS $qos_id
>>>     bandwidth=rate=4294967295,burst=4294967295
>>>     -
>>>     -# check at hv with a qos meter table
>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>     burst_size=4294967295 | wc -l], [0], [1
>>>     -])
>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>     meter | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\""
>>>     direction="to-lport"
>>>     -check_tos 63
>>>     -
>>>     -# Disable DSCP marking
>>>     -ovn-nbctl --wait=hv qos-del lsw0
>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
>>>     -])
>>>     -check_tos 0
>>>     -
>>>     -# check at hv without qos meter
>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>     meter | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# check meter with chassis not resident
>>>     -ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" &&
>>>     is_chassis_resident("lp3")' rate=11123 burst=111230
>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# check no meter table
>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>     meter | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>     rate=11123 | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -OVN_CLEANUP([hv])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- read-only sb db:ptcp access])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -
>>>     -: > .$1.db.~lock~
>>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>     -
>>>     -# Add read-only remote to sb ovsdb-server
>>>     -AT_CHECK(
>>>     -  [ovsdb-tool transact ovn-sb.db \
>>>     -     ['["OVN_Southbound",
>>>     -       {"op": "insert",
>>>     -        "table": "SB_Global",
>>>     -        "row": {
>>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>>     -       {"op": "insert",
>>>     -        "table": "Connection",
>>>     -        "uuid-name": "xyz",
>>>     -        "row": {"target": "ptcp:0:127.0.0.1",
>>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>>     -
>>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock
>>>     --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
>>>     -
>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>     -
>>>     -# read-only accesses should succeed
>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global],
>>>     [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list
>>>     Connection], [0], [stdout], [ignore])
>>>     -
>>>     -# write access should fail
>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch
>>>     vxlan 1.2.4.8], [1], [ignore],
>>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>>     allowed when database server is in read only mode","error":"not
>>>     allowed"}
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- read-only sb db:pssl access])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>     -\\]"])
>>>     -
>>>     -: > .$1.db.~lock~
>>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>     -
>>>     -# Add read-only remote to sb ovsdb-server
>>>     -AT_CHECK(
>>>     -  [ovsdb-tool transact ovn-sb.db \
>>>     -     ['["OVN_Southbound",
>>>     -       {"op": "insert",
>>>     -        "table": "SB_Global",
>>>     -        "row": {
>>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>>     -       {"op": "insert",
>>>     -        "table": "Connection",
>>>     -        "uuid-name": "xyz",
>>>     -        "row": {"target": "pssl:0:127.0.0.1",
>>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>>     -
>>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
>>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>>     - --private-key="$PKIDIR/testpki-privkey2.pem" \
>>>     - --certificate="$PKIDIR/testpki-cert2.pem" \
>>>     - --ca-cert="$PKIDIR/testpki-cacert.pem" \
>>>     -                          ovn-sb.db
>>>     -
>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>     -
>>>     -# read-only accesses should succeed
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -                    list SB_Global], [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -                    list Connection], [0], [stdout], [ignore])
>>>     -
>>>     -# write access should fail
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
>>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>>     allowed when database server is in read only mode","error":"not
>>>     allowed"}
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- nb connection/ssl commands])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>     -\\]"])
>>>     -
>>>     -: > .$1.db.~lock~
>>>     -ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
>>>     -
>>>     -# Start nb db server using db connection/ssl entries (unpopulated
>>>     initially)
>>>     -start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
>>>     - --remote=db:OVN_Northbound,NB_Global,connections \
>>>     - --private-key=db:OVN_Northbound,SSL,private_key \
>>>     - --certificate=db:OVN_Northbound,SSL,certificate \
>>>     - --ca-cert=db:OVN_Northbound,SSL,ca_cert \
>>>     -                          ovn-nb.db
>>>     -
>>>     -# Populate SSL configuration entries in nb db
>>>     -AT_CHECK(
>>>     -    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>>     -                       $PKIDIR/testpki-cert.pem \
>>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>>     [stdout], [ignore])
>>>     -
>>>     -# Populate a passive SSL connection in nb db
>>>     -AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0],
>>>     [stdout], [ignore])
>>>     -
>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>     -
>>>     -# Verify SSL connetivity to nb db server
>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          list NB_Global],
>>>     -         [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          list Connection],
>>>     -         [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          get-connection],
>>>     -         [0], [stdout], [ignore])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- sb connection/ssl commands])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>     -\\]"])
>>>     -
>>>     -: > .$1.db.~lock~
>>>     -ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>     -
>>>     -# Start sb db server using db connection/ssl entries (unpopulated
>>>     initially)
>>>     -start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
>>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>>     - --private-key=db:OVN_Southbound,SSL,private_key \
>>>     - --certificate=db:OVN_Southbound,SSL,certificate \
>>>     - --ca-cert=db:OVN_Southbound,SSL,ca_cert \
>>>     -                          ovn-sb.db
>>>     -
>>>     -# Populate SSL configuration entries in sb db
>>>     -AT_CHECK(
>>>     -    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>>     -                       $PKIDIR/testpki-cert.pem \
>>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>>     [stdout], [ignore])
>>>     -
>>>     -# Populate a passive SSL connection in sb db
>>>     -AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0],
>>>     [stdout], [ignore])
>>>     -
>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>     -
>>>     -# Verify SSL connetivity to sb db server
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          list SB_Global],
>>>     -         [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          list Connection],
>>>     -         [0], [stdout], [ignore])
>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>     -                    --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>     -          get-connection],
>>>     -         [0], [stdout], [ignore])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- nested containers])
>>>     -ovn_start
>>>     -
>>>     -# Physical network:
>>>     -# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
>>>     -
>>>     -# Logical network:
>>>     -# 3 Logical switches - "mgmt" (172.16.1.0/24
>>>     <http://172.16.1.0/24>), "foo" (192.168.1.0/24
>>>     <http://192.168.1.0/24>)
>>>     -# and "bar" (192.168.2.0/24 <http://192.168.2.0/24>). They are
>>>     all connected to router R1.
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl ls-add mgmt
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -
>>>     -# Connect mgmt to R1
>>>     -ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt
>>>     type=router \
>>>     -          options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>>     type=router \
>>>     -          options:router-port=bar addresses=\"00:00:00:01:02:04\"
>>>     -
>>>     -# "mgmt" has VM1 and VM2 connected
>>>     -ovn-nbctl lsp-add mgmt vm1 \
>>>     --- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
>>>     -
>>>     -ovn-nbctl lsp-add mgmt vm2 \
>>>     --- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# "foo1" and "foo2" are containers belonging to switch "foo"
>>>     -# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as
>>>     parent_port.
>>>     -ovn-nbctl lsp-add foo foo1 vm1 1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
>>>     -
>>>     -ovn-nbctl lsp-add foo foo2 vm2 2 \
>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>     -
>>>     -# "bar1" and "bar2" are containers belonging to switch "bar"
>>>     -# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as
>>>     parent_port.
>>>     -ovn-nbctl lsp-add bar bar1 vm1 2 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
>>>     -
>>>     -ovn-nbctl lsp-add bar bar2 vm2 1 \
>>>     --- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>>>     -
>>>     -# bar3 is a standalone VM belonging to switch "bar"
>>>     -ovn-nbctl lsp-add bar bar3 \
>>>     --- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int vm1 -- \
>>>     -    set interface vm1 external-ids:iface-id=vm1 \
>>>     -    options:tx_pcap=hv1/vm1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vm1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int bar3 -- \
>>>     -    set interface bar3 external-ids:iface-id=bar3 \
>>>     -    options:tx_pcap=hv1/bar3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/bar3-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int vm2 -- \
>>>     -    set interface vm2 external-ids:iface-id=vm2 \
>>>     -    options:tx_pcap=hv2/vm2-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vm2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and foo2 (same switch, different
>>>     HVs and
>>>     -# different VLAN tags).
>>>     -src_mac="f00000010205"
>>>     -dst_mac="f00000010206"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at foo2
>>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet > expected
>>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>>     -
>>>     -# Send ip packets between foo1 and bar2 (different switch,
>>>     different HV)
>>>     -src_mac="f00000010205"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at bar2
>>>     -src_mac="000000010204"
>>>     -dst_mac="f00000010208"
>>> -packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet >> expected
>>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>>     -
>>>     -# Send ip packets between foo1 and bar1
>>>     -# (different switch, loopback to same vm but different tag)
>>>     -src_mac="f00000010205"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at bar1
>>>     -src_mac="000000010204"
>>>     -dst_mac="f00000010207"
>>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet > expected1
>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>     -
>>>     -# Send ip packets between bar1 and bar3
>>>     -# (same switch. But one is container and another is a 
>>> standalone VM)
>>>     -src_mac="f00000010207"
>>>     -dst_mac="f00000010209"
>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at bar3
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet > expected
>>>     -OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
>>>     -
>>>     -# Send ip packets between foo1 and vm1.
>>>     -(different switch, container to the VM hosting it.)
>>>     -src_mac="f00000010205"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at vm1
>>>     -src_mac="000000010202"
>>>     -dst_mac="f00000010203"
>>> -packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet >> expected1
>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>     -
>>>     -# Send packets from vm1 to bar1.
>>>     -(different switch, A hosting VM to a container inside it)
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010202"
>>>     -src_ip=`ip_to_hex 172 16 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at vm1
>>>     -src_mac="000000010204"
>>>     -dst_mac="f00000010207"
>>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo  $packet >> expected1
>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>     -
>>>     -# Send broadcast packet from foo1. foo1 should not receive the
>>>     same packet.
>>>     -src_mac="f00000010205"
>>>     -dst_mac="ffffffffffff"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>     -
>>>     -# expected packet at VM1
>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based
>>>     routes])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>     LS "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and bar
>>>     -# (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>     -#
>>>     -# R2 and R3 are gateway routers.
>>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and R3 has
>>>     bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     -# connected to it. Note how both alice and bob have the same
>>>     subnet behind it.
>>>     -# We are trying to simulate external network via those 2
>>>     switches. In real
>>>     -# world the switch ports of these switches will have addresses
>>>     set as "unknown"
>>>     -# to make them learning switches. Or those switches will be
>>>     "localnet" ones.
>>>     -
>>>     -# Create three hypervisors and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=bar1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>     -    set interface hv3-vif1 external-ids:iface-id=bob1 \
>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add bob
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>>     type=router \
>>>     -    options:router-port=bar addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect bob to R3
>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>     <http://172.16.1.2/24>
>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>     -    type=router options:router-port=bob
>>>     addresses=\"00:00:03:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Connect R3 to join
>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>     <http://20.0.0.3/24>
>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>> r3-join \
>>>     -    type=router options:router-port=R3_join
>>>     addresses='"00:00:04:01:02:05"'
>>>     -
>>>     -# Install static routes with source ip address as the policy for
>>>     routing.
>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>     go via R3.
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>     <http://192.168.1.0/24> 20.0.0.2
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>     <http://192.168.2.0/24> 20.0.0.3
>>>     -
>>>     -# Install static routes with destination ip address as the policy
>>>     for routing.
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port bar1 in bar
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
>>>     -
>>>     -# Create logical port bob1 in bob
>>>     -ovn-nbctl lsp-add bob bob1 \
>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and bar1
>>>     -# (East-west traffic should flow normally)
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>     -
>>>     -# Send ip packets between bar1 and bob1
>>>     -src_mac="f00000010204"
>>>     -dst_mac="000001010204"
>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>>     -#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
>>>     -
>>>     -# Packet to expect at bar1
>>>     -src_mac="000001010204"
>>>     -dst_mac="f00000010204"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo $expected > expected
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -
>>>     -# Packet to Expect at alice1
>>>     -src_mac="000002010203"
>>>     -dst_mac="f00000010205"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo $expected > expected
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Packet to Expect at bob1
>>>     -src_mac="000003010203"
>>>     -dst_mac="f00000010206"
>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo $expected > expected
>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>>     10.0.0.4 aef0::4"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>     10.0.0.6 20.0.0.4"
>>>     -
>>>     -DNS1=`ovn-nbctl create DNS records={}`
>>>     -DNS2=`ovn-nbctl create DNS records={}`
>>>     -
>>>     -ovn-nbctl set DNS $DNS1 records:vm1.ovn.org
>>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>>     -ovn-nbctl set DNS $DNS1 records:vm2.ovn.org
>>>     <http://vm2.ovn.org>="10.0.0.6 20.0.0.4"
>>>     -ovn-nbctl set DNS $DNS2 records:vm3.ovn.org
>>>     <http://vm3.ovn.org>="40.0.0.4"
>>>     -
>>>     -ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -sleep 2
>>>     -as hv1 ovs-vsctl show
>>>     -
>>>     -echo "*************************"
>>>     -ovn-sbctl list DNS
>>>     -echo "*************************"
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -# set_dns_params host_name
>>>     -# Sets the dns_req_data and dns_resp_data
>>>     -set_dns_params() {
>>>     -    local hname=$1
>>>     -    local ttl=00000e10
>>>     -    an_count=0001
>>>     -    type=0001
>>>     -    case $hname in
>>>     -    vm1)
>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>     -        query_name=03766d31036f766e036f726700
>>>     -        # IPv4 address - 10.0.0.4
>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>>     -        ;;
>>>     -    vm2)
>>>     -        # vm2.ovn.org <http://vm2.ovn.org>
>>>     -        query_name=03766d32036f766e036f726700
>>>     -        # IPv4 address - 10.0.0.6
>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000006
>>>     -        # IPv4 address - 20.0.0.4
>>>     -
>>> expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004 
>>>
>>>     -        an_count=0002
>>>     -        ;;
>>>     -    vm3)
>>>     -        # vm3.ovn.org <http://vm3.ovn.org>
>>>     -        query_name=03766d33036f766e036f726700
>>>     -        # IPv4 address - 40.0.0.4
>>>     - expected_dns_answer=${query_name}00010001${ttl}000428000004
>>>     -        ;;
>>>     -    vm1_ipv6_only)
>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>     -        query_name=03766d31036f766e036f726700
>>>     -        # IPv6 address - aef0::4
>>>     -        type=001c
>>>     -
>>> expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004 
>>>
>>>     -        ;;
>>>     -    vm1_ipv4_v6)
>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>     -        query_name=03766d31036f766e036f726700
>>>     -        type=00ff
>>>     -        an_count=0002
>>>     -        # IPv4 address - 10.0.0.4
>>>     -        # IPv6 address - aef0::4
>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>>     -
>>> expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
>>>     -
>>> expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004 
>>>
>>>     -        ;;
>>>     -    vm1_invalid_type)
>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>     -        query_name=03766d31036f766e036f726700
>>>     -        # IPv6 address - aef0::4
>>>     -        type=0002
>>>     -        ;;
>>>     -    vm1_incomplete)
>>>     -        # set type to none
>>>     -        type=''
>>>     -    esac
>>>     -    # TTL - 3600
>>>     -    local dns_req_header=010201200001000000000000
>>>     -    local dns_resp_header=010281200001${an_count}00000000
>>>     - dns_req_data=${dns_req_header}${query_name}${type}0001
>>>     -
>>> dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} 
>>>
>>>     -}
>>>     -
>>>     -# This shell function sends a DNS request packet
>>>     -# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
>>>     -test_dns() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     dns_reply=$6
>>>     -    local dns_query_data=$7
>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>     -    # Packet size => IPv4 header (20) + UDP header (8) +
>>>     -    #                DNS data (header + query)
>>>     -    ip_len=`expr 28 + ${#dns_query_data} / 2`
>>>     -    udp_len=`expr $ip_len - 20`
>>>     -    ip_len=$(printf "%x" $ip_len)
>>>     -    udp_len=$(printf "%x" $udp_len)
>>>     -    local
>>> request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
>>>     - request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
>>>     -    # dns data
>>>     -    request=${request}${dns_query_data}
>>>     -
>>>     -    if test $dns_reply != 0; then
>>>     -        local dns_reply=$1
>>>     -        ip_len=`expr 28 + ${#dns_reply} / 2`
>>>     -        udp_len=`expr $ip_len - 20`
>>>     -        ip_len=$(printf "%x" $ip_len)
>>>     -        udp_len=$(printf "%x" $udp_len)
>>>     -        local
>>> reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
>>>     - 
>>> reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
>>>     -        echo $reply >> $inport.expected
>>>     -    else
>>>     -        for outport; do
>>>     -            echo $request >> $outport.expected
>>>     -        done
>>>     -    fi
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>>     -}
>>>     -
>>>     -test_dns6() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     dns_reply=$6
>>>     -    local dns_query_data=$7
>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>     -    # Packet size => UDP header (8) +
>>>     -    #                DNS data (header + query)
>>>     -    ip_len=`expr 8 + ${#dns_query_data} / 2`
>>>     -    udp_len=$ip_len
>>>     -    ip_len=$(printf "%x" $ip_len)
>>>     -    udp_len=$(printf "%x" $udp_len)
>>>     -    local
>>> request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
>>>     -    request=${request}9234003500${udp_len}0000
>>>     -    #dns data
>>>     -    request=${request}${dns_query_data}
>>>     -
>>>     -    if test $dns_reply != 0; then
>>>     -        local dns_reply=$1
>>>     -        ip_len=`expr 8 + ${#dns_reply} / 2`
>>>     -        udp_len=$ip_len
>>>     -        ip_len=$(printf "%x" $ip_len)
>>>     -        udp_len=$(printf "%x" $udp_len)
>>>     -        local
>>> reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
>>>     - reply=${reply}0035923400${udp_len}0000${dns_reply}
>>>     -        echo $reply >> $inport.expected
>>>     -    else
>>>     -        for outport; do
>>>     -            echo $request >> $outport.expected
>>>     -        done
>>>     -    fi
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
>>>     -}
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>     -
>>>     -set_dns_params vm2
>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=1
>>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 1.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap > 1.packets
>>>     -cat 1.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 1.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -set_dns_params vm1
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=1
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Clear the query name options for ls1-lp2
>>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
>>>     <http://vm2.ovn.org>
>>>     -
>>>     -set_dns_params vm2
>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=0
>>>     -test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data
>>>     -
>>>     -# NXT_RESUMEs should be 3.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap > 1.packets
>>>     -AT_CHECK([cat 1.packets], [0], [])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Clear the query name for ls1-lp1
>>>     -# Since ls1 has no query names configued,
>>>     -# ovn-northd should not add the DNS flows.
>>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
>>>     <http://vm1.ovn.org>
>>>     -
>>>     -set_dns_params vm1
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=0
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data
>>>     -
>>>     -# NXT_RESUMEs should be 3 only.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Test IPv6 (AAAA records) using IPv4 packet.
>>>     -# Add back the DNS options for ls1-lp1.
>>>     -ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org
>>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>>     -
>>>     -set_dns_params vm1_ipv6_only
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=1
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 4.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
>>>     -set_dns_params vm1_ipv4_v6
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=1
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 5.
>>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -cat 2.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 2.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Invalid type.
>>>     -set_dns_params vm1_invalid_type
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=0
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data
>>>     -
>>>     -# NXT_RESUMEs should be 6.
>>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Incomplete DNS packet.
>>>     -set_dns_params vm1_incomplete
>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=0
>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data
>>>     -
>>>     -# NXT_RESUMEs should be 7.
>>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Add one more DNS record to the ls1.
>>>     -ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 
>>> $DNS2"
>>>     -
>>>     -set_dns_params vm3
>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>     -dns_reply=1
>>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 8.
>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap > 1.packets
>>>     -cat 1.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat 1.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -# Try DNS query over IPv6
>>>     -set_dns_params vm1
>>>     -src_ip=aef00000000000000000000000000004
>>>     -dst_ip=aef00000000000000000000000000001
>>>     -dns_reply=1
>>>     -test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>     $dns_req_data $dns_resp_data
>>>     -
>>>     -# NXT_RESUMEs should be 9.
>>>     -OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap > 1.packets
>>>     -# Skipping the UDP checksum.
>>>     -cat 1.expected | cut -c 1-120,125- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
>>>     -
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -rm -f 1.expected
>>>     -rm -f 2.expected
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA
>>>     distributed router gateway port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add gw1
>>>     -as gw1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -sim_add gw2
>>>     -as gw2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>     -
>>>     -sim_add ext1
>>>     -as ext1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl \
>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>     -                                     chassis_name=gw1 \
>>>     -                                     priority=20 -- \
>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>     -                                     chassis_name=gw2 \
>>>     -                                     priority=10 -- \
>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port outside1 in outside
>>>     -ovn-nbctl lsp-add outside outside1 \
>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# Create localnet port in alice
>>>     -ovn-nbctl lsp-add alice ln-alice
>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>>     -# mapping to the external network, is the one generating packets
>>>     -as gw1 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -as gw2 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -as ext1 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 2
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -test_ip_packet()
>>>     -{
>>>     -    local active_gw=$1
>>>     -    local backup_gw=$2
>>>     -    local backup_vswitchd_dead=$3
>>>     -
>>>     -    # Send ip packet between foo1 and outside1
>>>     -    src_mac="f00000010203" # foo1 mac
>>>     -    dst_mac="000001010203" # rp-foo mac (internal router leg)
>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -    # ARP request packet to expect at outside1
>>>     -
>>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>>
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -    # Send ARP reply from outside1 back to the router
>>>     -    # XXX: note, we could avoid this if we plug this port into a
>>>     netns
>>>     -    # and setup the IP address into the port, so the kernel would
>>>     simply reply
>>>     -    src_mac="000002010203"
>>>     -    reply_mac="f00000010204"
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>>     -
>>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>>
>>>     -
>>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>>     -
>>>     -    OVS_WAIT_UNTIL([
>>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>>     table=66 | \
>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>     -    ])
>>>     -
>>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>>     -    src_mac="000002010203"
>>>     -    dst_mac="f00000010204"
>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -
>>> expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    echo $expected > ext1-vif1.expected
>>>     -
>>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>
>>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>>>     -
>>>     -    if test $backup_vswitchd_dead != 1; then
>>>     -        # Reset the file only if vswitchd in backup gw is alive
>>>     -        as $backup_gw reset_pcap_file br-phys_n1
>>>     $backup_gw/br-phys_n1
>>>     -    fi
>>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>>     -
>>>     -    # Resend packet from foo1 to outside1
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -    sleep 1
>>>     -
>>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap > packets
>>>     -    cat packets | grep $expected > exp
>>>     -    # Its possible that $active_gw/br-phys_n1-tx.pcap may have
>>>     received multiple
>>>     -    # garp packets. So consider only the first packet.
>>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>>     -    AT_CHECK([cat exp], [0], [expout])
>>>     -    rm -f expout
>>>     -    if test $backup_vswitchd_dead != 1; then
>>>     -        # Check for backup gw only if vswitchd is alive
>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap > packets
>>>     -        AT_CHECK([grep $expected packets | sort], [0], [])
>>>     -    fi
>>>     -}
>>>     -
>>>     -test_ip_packet gw1 gw2 0
>>>     -
>>>     -ovn-nbctl --timeout=3 --wait=hv \
>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>     -                                     chassis_name=gw1 \
>>>     -                                     priority=10 -- \
>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>     -                                     chassis_name=gw2 \
>>>     -                                     priority=20 -- \
>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -test_ip_packet gw2 gw1 0
>>>     -
>>>     -# Get the claim count of both gw1 and gw2.
>>>     -gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log |
>>>     wc -l`
>>>     -gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log |
>>>     wc -l`
>>>     -
>>>     -# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
>>>     -as gw2
>>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>     -
>>>     -# gw1 should claim the cr-alice and the claim count of gw1 
>>> should be
>>>     -# incremented by 1.
>>>     -gw1_claim_ct=$((gw1_claim_ct+1))
>>>     -
>>>     -OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
>>>     -| grep -c "cr-alice: Claiming"`])
>>>     -
>>>     -AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
>>>     -grep -c "cr-alice: Claiming"`])
>>>     -
>>>     -test_ip_packet gw1 gw2 1
>>>     -
>>>     -as gw2
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>     -
>>>     -OVN_CLEANUP([hv1],[gw1],[ext1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA
>>>     distributed router gateway port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add gw1
>>>     -as gw1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -sim_add gw2
>>>     -as gw2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>     -
>>>     -sim_add ext1
>>>     -as ext1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R0
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add join
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -#Connect foo to R0
>>>     -ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
>>>     -    type=router options:router-port=R0-foo \
>>>     -    -- lsp-set-addresses foo-R0 router
>>>     -
>>>     -#Connect R0 to join
>>>     -ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
>>>     <http://100.60.1.1/24>
>>>     -ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port 
>>> join-R0 \
>>>     -    type=router options:router-port=R0-join \
>>>     -    -- lsp-set-addresses join-R0 router
>>>     -
>>>     -#Connect join to R1
>>>     -ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
>>>     <http://100.60.1.2/24>
>>>     -ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port 
>>> join-R1 \
>>>     -    type=router options:router-port=R1-join \
>>>     -    -- lsp-set-addresses join-R1 router
>>>     -
>>>     -#add route rules
>>>     -ovn-nbctl lr-route-add R0 0.0.0.0/0 <http://0.0.0.0/0> 100.60.1.2
>>>     -ovn-nbctl lr-route-add R1 192.168.0.0/16 <http://192.168.0.0/16>
>>>     100.60.1.1
>>>     -
>>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -
>>>     -ovn-nbctl \
>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>     -                                     chassis_name=gw1 \
>>>     -                                     priority=20 -- \
>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>     -                                     chassis_name=gw2 \
>>>     -                                     priority=10 -- \
>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port outside1 in outside
>>>     -ovn-nbctl lsp-add outside outside1 \
>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# Create localnet port in alice
>>>     -ovn-nbctl lsp-add alice ln-alice
>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>>     -# mapping to the external network, is the one generating packets
>>>     -as gw1 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -as gw2 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -as ext1 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>     -
>>>     -# hv1 should be in 'ref_chassis' of the ha_chasssi_group as 
>>> logical
>>>     -# switch 'foo' can reach the router 'R1' (which has gw router 
>>> port)
>>>     -# via foo1 -> foo -> R0 -> join -> R1
>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="hv1"`
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$hv1_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 2
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -test_ip_packet()
>>>     -{
>>>     -    local active_gw=$1
>>>     -    local backup_gw=$2
>>>     -
>>>     -    # Send ip packet between foo1 and outside1
>>>     -    src_mac="f00000010203" # foo1 mac
>>>     -    dst_mac="000001010203" # foo-R0 mac (internal router leg)
>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -    # ARP request packet to expect at outside1
>>>     -
>>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>>
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -    # Send ARP reply from outside1 back to the router
>>>     -    # XXX: note, we could avoid this if we plug this port into a
>>>     netns
>>>     -    # and setup the IP address into the port, so the kernel would
>>>     simply reply
>>>     -    src_mac="000002010203"
>>>     -    reply_mac="f00000010204"
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>>     -
>>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>>
>>>     -
>>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>>     -
>>>     -    OVS_WAIT_UNTIL([
>>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>>     table=66 | \
>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>     -    ])
>>>     -
>>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>>     -    src_mac="000002010203"
>>>     -    dst_mac="f00000010204"
>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>     -
>>> expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    echo $expected > ext1-vif1.expected
>>>     -
>>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>
>>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>>     -
>>>     -    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
>>>     -    as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
>>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>>     -
>>>     -    # Resend packet from foo1 to outside1
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap > packets
>>>     -    cat packets | grep $expected > exp
>>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>>     -    AT_CHECK([cat exp], [0], [expout])
>>>     -
>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap > packets
>>>     -    AT_CHECK([grep $expected packets | sort], [0], [])
>>>     -}
>>>     -
>>>     -test_ip_packet gw1 gw2
>>>     -
>>>     -ovn-nbctl --timeout=3 --wait=hv \
>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>     -                                     chassis_name=gw1 \
>>>     -                                     priority=10 -- \
>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>     -                                     chassis_name=gw2 \
>>>     -                                     priority=20 -- \
>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -test_ip_packet gw2 gw1
>>>     -
>>>     -OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 1 LR with distributed router gateway port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR R1 that has switches foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>) and
>>>     -# alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>     The logical port
>>>     -# between R1 and alice has a "redirect-chassis" specified,
>>>     -# i.e. it is the distributed router gateway port.
>>>     -# Switch alice also has a localnet port defined.
>>>     -# An additional switch outside has a localnet port and the
>>>     -# same subnet as alice (172.16.1.0/24 <http://172.16.1.0/24>).
>>>     -
>>>     -# Physical network:
>>>     -# Three hypervisors hv[123].
>>>     -# hv1 hosts vif foo1.
>>>     -# hv2 is the "redirect-chassis" that hosts the distributed
>>>     -# router gateway port.
>>>     -# hv3 hosts vif outside1.
>>>     -# In order to show that connectivity works only through hv2,
>>>     -# an initial round of tests is run without any bridge-mapping
>>>     -# defined for the localnet on hv2.  These tests are expected
>>>     -# to fail.
>>>     -# Subsequent tests are run after defining the bridge-mapping
>>>     -# for the localnet on hv2. These tests are expected to succeed.
>>>     -
>>>     -# Create three hypervisors and create OVS ports corresponding
>>>     -# to logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -# 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
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24> \
>>>     -    -- set Logical_Router_Port alice 
>>> options:redirect-chassis="hv2"
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port outside1 in outside
>>>     -ovn-nbctl lsp-add outside outside1 \
>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# Create localnet port in alice
>>>     -ovn-nbctl lsp-add alice ln-alice
>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
>>>     -as hv1 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -as hv3 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 2
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -ovn-sbctl list chassis
>>>     -ovn-sbctl list encap
>>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>>     -ovn-sbctl list Gateway_Chassis
>>>     -echo "------ Port_Binding chassisredirect -------"
>>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>>     -echo "-------------------------------------------"
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv3 dump ----------"
>>>     -as hv3 ovs-ofctl show br-int
>>>     -as hv3 ovs-ofctl dump-flows br-int
>>>     -echo "--------------------------"
>>>     -
>>>     -
>>>     -# Check that redirect mapping is programmed only on hv2
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep
>>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep
>>>     =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
>>>     -])
>>>     -# Check that hv1 sends chassisredirect port traffic to hv2
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep
>>>     =0x3,metadata=0x1 | grep output | wc -l], [0], [1
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep
>>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>>     -])
>>>     -# Check that arp reply on distributed gateway port is only
>>>     programmed on hv2
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep
>>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep
>>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -
>>>     -: > hv2-vif1.expected
>>>     -: > hv3-vif1.expected
>>>     -
>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>     -#
>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>     provided, then
>>>     -# it should be the hardware address of the target to expect to
>>>     receive in an
>>>     -# ARP reply; otherwise no reply is expected.
>>>     -#
>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>     -# SPA and TPA are each 8 hex digits.
>>>     -test_arp() {
>>>     -    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
>>>     -    local
>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>     $request
>>>     -
>>>     -    if test X$reply_ha != X; then
>>>     -        # Expect to receive the reply, if any.
>>>     -        local
>>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>
>>>     -        echo $reply >> hv${hv}-vif$inport.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -rtr_ip=$(ip_to_hex 172 16 1 1)
>>>     -foo_ip=$(ip_to_hex 192 168 1 2)
>>>     -outside_ip=$(ip_to_hex 172 16 1 3)
>>>     -
>>>     -echo $rtr_ip
>>>     -echo $foo_ip
>>>     -echo $outside_ip
>>>     -
>>>     -# ARP for router IP address from outside1, no response expected
>>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>     -
>>>     -# Send ip packet between foo1 and outside1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>     -
>>>     -# Now add bridge-mappings on hv2, which should make everything 
>>> work
>>>     -as hv2 ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>>     to br-phys
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>>     -grep "Port patch-br-int-to-ln-alice" | wc -l`])
>>>     -
>>>     -# ARP for router IP address from outside1
>>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
>>>     -
>>>     -# hv3-vif1.expected should also have the gw router port garp 
>>> packet.
>>> -exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>
>>>     -echo $exp_gw_ip_garp >> hv3-vif1.expected
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>     -
>>>     -# Send ip packet between foo1 and outside1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -# Packet to Expect at outside1
>>>     -src_mac="000002010203"
>>>     -dst_mac="f00000010204"
>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -echo "------ hv1 dump ----------"
>>>     -as hv1 ovs-ofctl show br-int
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv2 dump ----------"
>>>     -as hv2 ovs-ofctl show br-int
>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>     -echo "------ hv3 dump ----------"
>>>     -as hv3 ovs-ofctl show br-int
>>>     -as hv3 ovs-ofctl dump-flows br-int
>>>     -echo "----------------------------"
>>>     -
>>>     -echo $expected >> hv3-vif1.expected
>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>     -
>>>     -#Check ovn-trace over "chassisredirect" port
>>>     -AT_CAPTURE_FILE([trace])
>>>     -ovn_trace () {
>>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>>     -}
>>>     -
>>>     -echo 'ip.ttl--;' > expout
>>>     -echo 'eth.src = 00:00:02:01:02:03;' >> expout
>>>     -echo 'eth.dst = f0:00:00:01:02:04;' >> expout
>>>     -echo 'output("ln-alice");' >> expout
>>>     -AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src ==
>>>     f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src ==
>>>     192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0],
>>>     [expout])
>>>     -
>>>     -# Create logical port alice1 in alice on hv1
>>>     -as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
>>>     -
>>>     -# Create logical port foo2 in foo on hv2
>>>     -as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=foo2 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovn-nbctl lsp-add foo foo2 \
>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -: > hv1-vif2.expected
>>>     -
>>>     -# Send ip packet between alice1 and foo2
>>>     -src_mac="f00000010205"
>>>     -dst_mac="000002010203"
>>>     -src_ip=`ip_to_hex 172 16 1 4`
>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>>     -
>>>     -# Packet to Expect at foo2
>>>     -src_mac="000001010203"
>>>     -dst_mac="f00000010206"
>>>     -src_ip=`ip_to_hex 172 16 1 4`
>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -echo $expected >> hv2-vif1.expected
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
>>>     -
>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding
>>>     logical_port=cr-alice | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice
>>>     options redirect-chassis
>>>     -
>>>     -AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc
>>>     -l], [0], [0
>>>     -])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed
>>>     router])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -# Create logical switches
>>>     -ovn-nbctl ls-add ls0
>>>     -ovn-nbctl ls-add ls1
>>>     -# Create distributed router
>>>     -ovn-nbctl create Logical_Router name=lr0
>>>     -# Add distributed gateway port to distributed router
>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>     <http://192.168.0.1/24> \
>>>     -    -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>>     -    type=router options:router-port=lrp0 addresses="router"
>>>     -# Add router port to ls1
>>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>>     <http://10.0.0.1/24>
>>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>>>     -    type=router options:router-port=lrp1 addresses="router"
>>>     -# Add logical ports for NAT rules
>>>     -ovn-nbctl lsp-add ls1 foo1 \
>>>     --- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
>>>     -ovn-nbctl lsp-add ls1 foo2 \
>>>     --- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
>>>     -# Add nat-addresses option
>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="router"
>>>     -# Add NAT rules
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>>     <http://10.0.0.0/24>])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3
>>>     10.0.0.3 foo1 f0:00:00:00:00:03])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4
>>>     10.0.0.4 foo2 f0:00:00:00:00:04])
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -# Initially test with no bridge-mapping on hv2, expect to receive
>>>     no packets
>>>     -
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -# Initially test with no bridge-mapping on hv3
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port
>>>     network_name=physnet1])
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 2
>>>     -
>>>     -# Expect no packets when hv2 bridge-mapping is not present
>>>     -: > packets
>>>     -OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
>>>     -
>>>     -# Add bridge-mapping on hv2
>>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -
>>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>>     to br-phys
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>     -
>>>     -# Wait for packets to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>
>>>     -echo $expected > expout
>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>
>>>     -echo $expected >> expout
>>>     -AT_CHECK([sort packets], [0], [expout])
>>>     -sort packets | cat
>>>     -
>>>     -# Temporarily remove nat-addresses option to avoid race conditions
>>>     -# due to GARP backoff
>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 
>>> nat-addresses=""
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>     -
>>>     -# Add OVS ports for foo1 and foo2 on hv3
>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>     -    set interface hv3-vif1 external-ids:iface-id=foo1 \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv3-vif2 -- \
>>>     -    set interface hv3-vif2 external-ids:iface-id=foo2 \
>>>     -    ofport-request=2
>>>     -
>>>     -# Add bridge-mapping on hv3
>>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -
>>>     -# Wait until the patch ports are created in hv3 to connect br-int
>>>     to br-phys
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>     -
>>>     -# Re-add nat-addresses option
>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="router"
>>>     -
>>>     -# Wait for packets to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>> -garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003" 
>>>
>>>     -echo $garp_1 > expout
>>> -garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004" 
>>>
>>>     -echo $garp_2 >> expout
>>>     -
>>>     -cat packets | grep $garp_1 | head -1 > exp
>>>     -cat packets | grep $garp_2 | head -1 >> exp
>>>     -AT_CHECK([cat exp], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# VLAN traffic for external network redirected through
>>>     distributed router
>>>     -# gateway port should use vlans(i.e input network vlan tag)
>>>     across hypervisors
>>>     -# instead of tunneling.
>>>     -AT_SETUP([ovn -- vlan traffic for external network with
>>>     distributed router gateway port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# # One LR R1 that has switches foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>) and
>>>     -# # alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>     it.  The logical port
>>>     -# # between R1 and alice has a "redirect-chassis" specified,
>>>     -# # i.e. it is the distributed router gateway port(172.16.1.6).
>>>     -# # Switch alice also has a localnet port defined.
>>>     -# # An additional switch outside has the same subnet as alice
>>>     -# # (172.16.1.0/24 <http://172.16.1.0/24>), a localnet port and
>>>     nexthop port(172.16.1.1)
>>>     -# # which will receive the packet destined for external network
>>>     -# # (i.e 8.8.8.8 as destination ip).
>>>     -
>>>     -# Physical network:
>>>     -# # Four hypervisors hv[1234].
>>>     -# # hv1 hosts vif foo1.
>>>     -# # hv2 is the "redirect-chassis" that hosts the distributed
>>>     router gateway port.
>>>     -# # Later to test GARPs for the router port - foo, hv2 and hv4
>>>     are added to the ha_chassis_group
>>>     -# # hv3 hosts nexthop port vif outside1.
>>>     -# # All other tests connect hypervisors to network n1 through
>>>     br-phys for tunneling.
>>>     -# # But in this test, hv1 won't connect to n1(and no br-phys in
>>>     hv1), and
>>>     -# # in order to show vlans(instead of tunneling) used between hv1
>>>     and hv2,
>>>     -# # a new network n2 created and hv1 and hv2 connected to this
>>>     network through br-ex.
>>>     -# # hv2 and hv3 are still connected to n1 network through br-phys.
>>>     -net_add n1
>>>     -
>>>     -# We are not calling ovn_attach for hv1, to avoid adding br-phys.
>>>     -# Tunneling won't work in hv1 as ovn-encap-ip is not added to any
>>>     bridge in hv1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -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,vxlan \
>>>     -    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
>>>     -    -- add-br br-int \
>>>     -    -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true \
>>>     -    -- set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=public:br-ex
>>>     -
>>>     -start_daemon ovn-controller
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl set Open_vSwitch .
>>> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>>     -
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings="phys:br-phys"
>>>     -
>>>     -sim_add hv4
>>>     -as hv4
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>     -ovs-vsctl set Open_vSwitch .
>>> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>>     -
>>>     -# Create network n2 for vlan connectivity between hv1 and hv2
>>>     -net_add n2
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-ex
>>>     -net_attach n2 br-ex
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl add-br br-ex
>>>     -net_attach n2 br-ex
>>>     -
>>>     -as hv4
>>>     -ovs-vsctl add-br br-ex
>>>     -net_attach n2 br-ex
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect alice to R1 as distributed router gateway port
>>>     (172.16.1.6) on hv2
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24
>>>     <http://172.16.1.6/24> \
>>>     -    -- set Logical_Router_Port alice 
>>> options:redirect-chassis="hv2"
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router \
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port outside1 in outside, which is a nexthop 
>>> address
>>>     -# for 172.16.1.0/24 <http://172.16.1.0/24>
>>>     -ovn-nbctl lsp-add outside outside1 \
>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
>>>     -
>>>     -# Set default gateway (nexthop) to 172.16.1.1
>>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>"
>>>     172.16.1.1 alice
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24
>>>     <http://192.168.1.1/24>])
>>>     -ovn-nbctl set Logical_Switch_Port rp-alice
>>>     options:nat-addresses=router
>>>     -
>>>     -ovn-nbctl lsp-add foo ln-foo
>>>     -ovn-nbctl lsp-set-addresses ln-foo unknown
>>>     -ovn-nbctl lsp-set-options ln-foo network_name=public
>>>     -ovn-nbctl lsp-set-type ln-foo localnet
>>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
>>>     -
>>>     -# Create localnet port in alice
>>>     -ovn-nbctl lsp-add alice ln-alice
>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -# Check that there is a logical flow in logical switch foo's 
>>> pipeline
>>>     -# to set the outport to rp-foo (which is expected).
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>>     ls_in_l2_lkup | \
>>>     -grep rp-foo | grep -v is_chassis_resident | wc -l`])
>>>     -
>>>     -# Set the option 'reside-on-redirect-chassis' for foo
>>>     -ovn-nbctl set logical_router_port foo
>>>     options:reside-on-redirect-chassis=true
>>>     -# Check that there is a logical flow in logical switch foo's 
>>> pipeline
>>>     -# to set the outport to rp-foo with the condition
>>>     is_chassis_redirect.
>>>     -ovn-sbctl dump-flows foo
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>>     ls_in_l2_lkup | \
>>>     -grep rp-foo | grep is_chassis_resident | wc -l`])
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list nat
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -ovn-sbctl list chassis
>>>     -echo "---------------------"
>>>     -
>>>     -for chassis in hv1 hv2 hv3; do
>>>     -    as $chassis
>>>     -    echo "------ $chassis dump ----------"
>>>     -    ovs-vsctl show br-int
>>>     -    ovs-ofctl show br-int
>>>     -    ovs-ofctl dump-flows br-int
>>>     -    echo "--------------------------"
>>>     -done
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -foo1_ip=$(ip_to_hex 192 168 1 2)
>>>     -gw_ip=$(ip_to_hex 172 16 1 6)
>>>     -dst_ip=$(ip_to_hex 8 8 8 8)
>>>     -nexthop_ip=$(ip_to_hex 172 16 1 1)
>>>     -
>>>     -foo1_mac="f00000010203"
>>>     -foo_mac="000001010203"
>>>     -gw_mac="000002010203"
>>>     -nexthop_mac="f00000010204"
>>>     -
>>>     -# Send ip packet from foo1 to 8.8.8.8
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000001010203"
>>> -packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -# Wait for GARPs announcing gw IP to arrive
>>>     -OVS_WAIT_UNTIL([
>>>     -    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>     -    ])
>>>     -
>>>     -# VLAN tagged packet with router port(192.168.1.1) MAC as
>>>     destination MAC
>>>     -# is expected on bridge connecting hv1 and hv2
>>> -expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo $expected > hv1-br-ex_n2.expected
>>>     -
>>>     -# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
>>>     -# As connection tracking not enabled for this test, snat can't be
>>>     done on the packet.
>>>     -# We still see foo1 as the source ip address. But source
>>>     mac(gateway MAC) and
>>>     -# dest mac(nexthop mac) are properly configured.
>>> -expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000 
>>>
>>>     -echo $expected > hv3-vif1.expected
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
>>>     -as hv3 reset_pcap_file hv3-vif1 hv3/vif1
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -sleep 2
>>>     -
>>>     -# On hv1, table 32 check that no packet goes via the tunnel port
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
>>>     -| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -ip_packet() {
>>>     -    grep "1010203f00000010203"
>>>     -}
>>>     -
>>>     -# Check vlan tagged packet on the bridge connecting hv1 and hv2
>>>     with the
>>>     -# foo1's mac.
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
>>>     -cat hv1-br-ex_n2.expected > expout
>>>     -AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
>>>     -
>>>     -# Check expected packet on nexthop interface
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
>>>     -cat hv3-vif1.expected > expout
>>>     -AT_CHECK([sort hv3-vif1], [0], [expout])
>>>     -
>>>     -# Test the GARP for the router port ip - 192.168.1.1
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>     -
>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>>     -
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
>>>     -
>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>     ha_chassis_group name=hagrp1`
>>>     -ovn-nbctl remove logical_router_port alice options 
>>> redirect-chassis
>>>     -ovn-nbctl --wait=sb set logical_router_port alice
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -# When hv2 claims the gw router port cr-alice, it should send out
>>>     -# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
>>>     -
>>>     -# foo1 (on hv1) should receive GARP without VLAN tag
>>> -exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101" 
>>>
>>>     -echo $exp_garp_on_foo1 > foo1.expout
>>>     -
>>>     -# ovn-controller on hv2 should send garp with VLAN tag
>>> -sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101" 
>>>
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>>     -# Wait until we receive atleast 1 packet
>>>     -OVS_WAIT_UNTIL([test 1=`$PYTHON
>>>     "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-ex_n2-tx.pcap | wc -l`])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-ex_n2-tx.pcap | head -1 > packets
>>>     -echo $sent_garp > expout
>>>     -AT_CHECK([cat packets], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv4/br-ex_n2-tx.pcap > empty
>>>     -AT_CHECK([cat empty], [0], [])
>>>     -
>>>     -# Make hv4 master
>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
>>>     -
>>>     -# Wait till cr-alice is claimed by hv4
>>>     -hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>> name=hv4)
>>>     -# check that the chassis redirect port has been claimed by the
>>>     gw1 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -# Reset the pcap file for hv2/br-ex_n2. From now on
>>>     ovn-controller in hv2
>>>     -# should not send GARPs for the router ports.
>>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>>     -
>>>     -echo $sent_garp > br-ex_n2.expout
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>>     -OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
>>>     -
>>>     -sleep 2
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-ex_n2-tx.pcap > empty
>>>     -AT_CHECK([cat empty], [0], [])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
>>>     -AT_KEYWORDS([ovn-nd_ra])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# In this test case we create 1 lswitch with 3 VIF ports attached,
>>>     -# and a lrouter connected to the lswitch.
>>>     -# We generate the Router solicitation packet and verify the
>>>     Router Advertisement
>>>     -# reply packet from the ovn-controller.
>>>     -
>>>     -# Create hypervisor and logical switch lsw0, logical router lr0,
>>>     attach lsw0
>>>     -# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode
>>>     column to
>>>     -# 'slaac' to allow lrp0 send RA for SLAAC mode.
>>>     -ovn-nbctl ls-add lsw0
>>>     -ovn-nbctl lr-add lr0
>>>     -ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
>>>     -ovn-nbctl set Logical_Router_Port lrp0
>>>     ipv6_ra_configs:address_mode="slaac"
>>>     -ovn-nbctl \
>>>     -    -- lsp-add lsw0 lsp0 \
>>>     -    -- set Logical_Switch_Port lsp0 type=router \
>>>     -                     options:router-port=lrp0 \
>>>     -                     addresses='"fa:16:3e:00:00:01
>>>     fdad:1234:5678::1"'
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
>>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
>>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
>>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
>>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>>     -
>>>     -ovn-nbctl lsp-add lsw0 lp3
>>>     -ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
>>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>>     -ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
>>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>>     -
>>>     -# Add ACL rule for ICMPv6 on lsw0
>>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  
>>> allow-related
>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>>     icmp6'  allow-related
>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>>     icmp6'  allow-related
>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 &&
>>>     icmp6'  allow-related
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>     -    set interface hv1-vif3 external-ids:iface-id=lp3 \
>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>     -    ofport-request=3
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -# Make sure that ovn-controller has installed the corresponding
>>>     OF Flow.
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>     -
>>>     -# This shell function sends a Router Solicitation packet.
>>>     -# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
>>>     -test_ipv6_ra() {
>>>     -    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
>>>     prefix_opt=$6
>>>     -    local
>>> request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac} 
>>>
>>>     -
>>>     -    local len=24
>>>     -    local mtu_opt=""
>>>     -    if test $mtu != 0; then
>>>     -        len=`expr $len + 8`
>>>     -        mtu_opt=05010000${mtu}
>>>     -    fi
>>>     -
>>>     -    if test ${#prefix_opt} != 0; then
>>>     - prefix_opt=${prefix_opt}fdad1234567800000000000000000000
>>>     -        len=`expr $len + ${#prefix_opt} / 2`
>>>     -    fi
>>>     -
>>>     -    len=$(printf "%x" $len)
>>>     -    local lrp_mac=fa163e000001
>>>     -    local lrp_lla=fe80000000000000f8163efffe000001
>>>     -    local
>>> reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt} 
>>>
>>>     -    echo $reply >> $inport.expected
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} 
>>> $request
>>>     -}
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>     -
>>>     -# MTU is not set and the address mode is set to slaac
>>>     -addr_mode=00
>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>     -src_mac=fa163e000002
>>>     -src_lla=fe80000000000000f8163efffe000002
>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
>>>     $default_prefix_option_config
>>>     -
>>>     -# NXT_RESUME should be 1.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap  > 1.packets
>>>     -
>>>     -cat 1.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum.
>>>     -cat 1.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -rm -f *.expected
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>     -
>>>     -# Set the MTU to 1500
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>     ipv6_ra_configs:mtu=1500
>>>     -
>>>     -# Make sure that ovn-controller has installed the corresponding
>>>     OF Flow.
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>     -
>>>     -addr_mode=00
>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>     -src_mac=fa163e000003
>>>     -src_lla=fe80000000000000f8163efffe000003
>>>     -mtu=000005dc
>>>     -
>>>     -test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
>>>     $default_prefix_option_config
>>>     -
>>>     -# NXT_RESUME should be 2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap  > 2.packets
>>>     -
>>>     -cat 2.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum.
>>>     -cat 2.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -rm -f *.expected
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>     -
>>>     -# Set the address mode to dhcpv6_stateful
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>>     -# Make sure that ovn-controller has installed the corresponding
>>>     OF Flow.
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>     -
>>>     -addr_mode=80
>>> -default_prefix_option_config=03044080ffffffffffffffff00000000
>>>     -src_mac=fa163e000004
>>>     -src_lla=fe80000000000000f8163efffe000004
>>>     -mtu=000005dc
>>>     -
>>>     -test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
>>>     $default_prefix_option_config
>>>     -
>>>     -# NXT_RESUME should be 3.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif3-tx.pcap  > 3.packets
>>>     -
>>>     -cat 3.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum.
>>>     -cat 3.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -rm -f *.expected
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>     -
>>>     -# Set the address mode to dhcpv6_stateless
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>>     -# Make sure that ovn-controller has installed the corresponding
>>>     OF Flow.
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>     -
>>>     -addr_mode=40
>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>     -src_mac=fa163e000002
>>>     -src_lla=fe80000000000000f8163efffe000002
>>>     -mtu=000005dc
>>>     -
>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>>     $default_prefix_option_config
>>>     -
>>>     -# NXT_RESUME should be 4.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap  > 1.packets
>>>     -
>>>     -cat 1.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum.
>>>     -cat 1.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -rm -f *.expected
>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>     -
>>>     -# Set the address mode to invalid.
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>     ipv6_ra_configs:address_mode=invalid
>>>     -# Make sure that ovn-controller has not installed any OF Flow for
>>>     IPv6 ND RA.
>>>     -OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int |
>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>     -
>>>     -addr_mode=40
>>>     -default_prefix_option_config=""
>>>     -src_mac=fa163e000002
>>>     -src_lla=fe80000000000000f8163efffe000002
>>>     -mtu=000005dc
>>>     -
>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>>     $default_prefix_option_config
>>>     -
>>>     -# NXT_RESUME should be 4 only.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif1-tx.pcap  > 1.packets
>>>     -AT_CHECK([cat 1.packets], [0], [])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- /32 router IP address])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# 2 LS 'foo' and 'alice' connected via router R1.
>>>     -# R1 connects to 'alice' with a /32 IP address. We use static
>>>     routes and
>>>     -# nexthop to push traffic to a logical port in switch 'alice'
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>     type=router \
>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>     -
>>>     -# Connect alice to R1.
>>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
>>>     <http://172.16.1.1/32>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -          type=router options:router-port=alice
>>>     addresses=\"00:00:00:01:02:04\"
>>>     -
>>>     -# Create logical port foo1 in foo
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical port alice1 in alice
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
>>>     -
>>>     -#install default route in R1 to use alice1's IP address as nexthop
>>>     -ovn-nbctl lr-route-add R1 0.0.0.0/0 <http://0.0.0.0/0> 10.0.0.2 
>>> alice
>>>     -
>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>     logical ports.
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -
>>>     -# 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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -# Send ip packets between foo1 and alice1
>>>     -src_mac="f00000010203"
>>>     -dst_mac="000000010203"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -
>>>     -# Send the first packet to trigger a ARP response and 
>>> population of
>>>     -# mac_bindings table.
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" |
>>>     wc -l` -gt 0])
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -# Packet to Expect at 'alice1'
>>>     -src_mac="000000010204"
>>>     -dst_mac="f00000010204"
>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>>     -echo
>>> "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>
>>>     > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -# Add localport to the switch
>>>     -ovn-nbctl lsp-add ls1 lp01
>>>     -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
>>>     -ovn-nbctl lsp-set-type lp01 localport
>>>     -
>>>     -net_add n1
>>>     -
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -    ovs-vsctl add-port br-int vif01 -- \
>>>     -        set Interface vif01 external-ids:iface-id=lp01 \
>>>     - options:tx_pcap=hv${i}/vif01-tx.pcap \
>>>     - options:rxq_pcap=hv${i}/vif01-rx.pcap \
>>>     -                              ofport-request=${i}0
>>>     -
>>>     -    ovs-vsctl add-port br-int vif${i}1 -- \
>>>     -        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
>>>     - options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
>>>     - options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
>>>     -                              ofport-request=${i}1
>>>     -
>>>     -    ovn-nbctl lsp-add ls1 lp${i}1
>>>     -    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
>>>     -    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
>>>     -
>>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = 
>>> xup])
>>>     -done
>>>     -
>>>     -ovn-nbctl --wait=sb sync
>>>     -ovn-sbctl dump-flows
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    echo hv${1%?}
>>>     -}
>>>     -#
>>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is
>>>     specified as
>>>     -# logical switch port numbers, e.g. 11 for vif11.
>>>     -#
>>>     -# EOUT is the end-to-end output port, that is, where the packet
>>>     will end up
>>>     -# after possibly bouncing through one or more localnet ports.
>>>     LOUT is the
>>>     -# logical output port, which might be a localnet port, as seen by
>>>     ovn-trace
>>>     -# (which doesn't know what localnet ports are connected to and
>>>     therefore can't
>>>     -# figure out the end-to-end answer).
>>>     -#
>>>     -# DEFHV is the default hypervisor from where the packet is going
>>>     to be sent
>>>     -# if the source port is a localport.
>>>     -for i in 1 2; do
>>>     -    for j in 0 1; do
>>>     -        : > $i$j.expected
>>>     -    done
>>>     -done
>>>     -test_packet() {
>>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
>>>     -    echo "$@"
>>>     -
>>>     -    # First try tracing the packet.
>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>>     eth.src==$src && eth.type==0x$eth"
>>>     -    if test $lout != drop; then
>>>     -        echo "output(\"$lout\");"
>>>     -    fi > expout
>>>     -    AT_CAPTURE_FILE([trace])
>>>     -    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed
>>>     '1,/Minimal trace/d'], [0], [expout])
>>>     -
>>>     -    # Then actually send a packet, for an end-to-end test.
>>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>>     -    hv=`vif_to_hv $inport`
>>>     -    # If hypervisor 0 (localport) use the defhv parameter
>>>     -    if test $hv = hv0; then
>>>     -        hv=$defhv
>>>     -    fi
>>>     -    vif=vif$inport
>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>     -    if test $eout != drop; then
>>>     -        echo $packet >> ${eout#lp}.expected
>>>     -    fi
>>>     -}
>>>     -
>>>     -
>>>     -# lp11 and lp21 are on different hypervisors
>>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>>     -
>>>     -# Both VIFs should be able to reach the localport on their own HV
>>>     -test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
>>>     -test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
>>>     -
>>>     -# Packet sent from localport on same hv should reach the vif
>>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 
>>> lp11 hv1
>>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 
>>> lp21 hv2
>>>     -
>>>     -# Packet sent from localport on different hv should be dropped
>>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop 
>>> lp21 hv1
>>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop 
>>> lp11 hv2
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2; do
>>>     -    for j in 0 1; do
>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -# create gateways with external network connectivity
>>>     -
>>>     -for i in 1 2; do
>>>     -    sim_add gw$i
>>>     -    as gw$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -    ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -done
>>>     -
>>>     -ovn-nbctl ls-add inside
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -# create hypervisors with a vif port each to an internal network
>>>     -
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.1$i
>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>     -        ofport-request=1
>>>     -
>>>     -        ovn-nbctl lsp-add inside inside$i \
>>>     -            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i
>>>     192.168.1.10$i"
>>>     -
>>>     -done
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -# Connect inside to R1
>>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>>     rp-inside \
>>>     -    type=router options:router-port=inside \
>>>     -    -- lsp-set-addresses rp-inside router
>>>     -
>>>     -# Connect outside to R1 as distributed router gateway port on 
>>> gw1+gw2
>>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>>     <http://192.168.0.101/24>
>>>     -
>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>>     -- \
>>>     -          --id=@gc1 create Gateway_Chassis \
>>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>>     -- \
>>>     -          set Logical_Router_Port outside
>>>     'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>>     rp-outside \
>>>     -    type=router options:router-port=outside \
>>>     -    -- lsp-set-addresses rp-outside router
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -echo "---------NB dump-----"
>>>     -ovn-nbctl show
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router
>>>     -echo "---------------------"
>>>     -ovn-nbctl list logical_router_port
>>>     -echo "---------------------"
>>>     -
>>>     -echo "---------SB dump-----"
>>>     -ovn-sbctl list datapath_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl list port_binding
>>>     -echo "---------------------"
>>>     -ovn-sbctl dump-flows
>>>     -echo "---------------------"
>>>     -ovn-sbctl list chassis
>>>     -ovn-sbctl list encap
>>>     -echo "---------------------"
>>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>>     -ovn-sbctl list Gateway_Chassis
>>>     -echo "------ Port_Binding chassisredirect -------"
>>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>>     -echo "-------------------------------------------"
>>>     -
>>>     -# There should be one ha_chassis_group with the name "outside"
>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>     -ha_chassis_group name="outside"`
>>>     -
>>>     -AT_CHECK([test $ha_chassi_grp_name = outside])
>>>     -
>>>     -# There should be 2 ha_chassis rows in SB DB.
>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
>>>     -grep -v chassis-name | awk '{print $3}' \
>>>     -| grep '-' | wc -l ], [0], [2
>>>     -])
>>>     -
>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>> ha_chassis_group`
>>>     -# Trim the spaces.
>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>     -
>>>     -ha_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
>>>     -do
>>>     -    ha_ch_list="$ha_ch_list $i"
>>>     -done
>>>     -
>>>     -# Trim the spaces.
>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>     -
>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>     -
>>>     -for chassis in gw1 gw2 hv1 hv2; do
>>>     -    as $chassis
>>>     -    echo "------ $chassis dump ----------"
>>>     -    ovs-ofctl show br-int
>>>     -    ovs-ofctl dump-flows br-int
>>>     -    echo "--------------------------"
>>>     -done
>>>     -bfd_dump() {
>>>     -    for chassis in gw1 gw2 hv1 hv2; do
>>>     -        as $chassis
>>>     -        echo "------ $chassis dump (BFD)----"
>>>     -        echo "BFD (from $chassis):"
>>>     -        # dump BFD config and status to the other chassis
>>>     -        for chassis2 in gw1 gw2 hv1 hv2; do
>>>     -            if [[ "$chassis" != "$chassis2" ]]; then
>>>     -                echo " -> $chassis2:"
>>>     -                echo "   $(ovs-vsctl --bare --columns
>>>     bfd,bfd_status find Interface name=ovn-$chassis2-0)"
>>>     -            fi
>>>     -        done
>>>     -        echo "--------------------------"
>>>     -    done
>>>     -}
>>>     -
>>>     -bfd_dump
>>>     -
>>>     -hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>>     Interface name=ovn-gw1-0)
>>>     -hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>>     Interface name=ovn-gw2-0)
>>>     -hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>>     Interface name=ovn-gw1-0)
>>>     -hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>>     Interface name=ovn-gw2-0)
>>>     -
>>>     -echo $hv1_gw1_ofport
>>>     -echo $hv1_gw2_ofport
>>>     -echo $hv2_gw1_ofport
>>>     -echo $hv2_gw2_ofport
>>>     -
>>>     -echo "--- hv1 ---"
>>>     -as hv1 ovs-ofctl dump-flows br-int table=32
>>>     -
>>>     -echo "--- hv2 ---"
>>>     -as hv2 ovs-ofctl dump-flows br-int table=32
>>>     -
>>>     -gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>> name=gw1)
>>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>> name=gw2)
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw1
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# make sure ARP responder flows for outside router port reside on
>>>     gw1 too
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# check that the chassis redirect port has been claimed by the
>>>     gw1 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="hv1"`
>>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="hv2"`
>>>     -
>>>     -exp_ref_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>     -do
>>>     -    if test $i = $hv1_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    elif test $i = $hv2_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    fi
>>>     -done
>>>     -
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -
>>>     -# at this point, we invert the priority of the gw chassis between
>>>     gw1 and gw2
>>>     -
>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>     -                    name=outside_gw1 chassis_name=gw1 priority=10
>>>     -- \
>>>     -          --id=@gc1 create Gateway_Chassis \
>>>     -                    name=outside_gw2 chassis_name=gw2 priority=20
>>>     -- \
>>>     -          set Logical_Router_Port outside
>>>     'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -
>>>     -# XXX: Let the change propagate down to the ovn-controllers
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -# we make sure that the hypervisors noticed, and inverted the
>>>     slave ports
>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# check that the chassis redirect port has been reclaimed by the
>>>     gw2 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -# check BFD enablement on tunnel ports from gw1 #########
>>>     -as gw1
>>>     -for chassis in gw2 hv1 hv2; do
>>>     -    echo "checking gw1 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -
>>>     -
>>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>>     -as gw2
>>>     -for chassis in gw1 hv1 hv2; do
>>>     -    echo "checking gw2 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -
>>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>>     -as hv1
>>>     -for chassis in gw1 gw2; do
>>>     -    echo "checking hv1 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -# make sure BFD is not enabled to hv2, we don't need it
>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-hv2-0],[0],
>>>     -         [[
>>>     -]])
>>>     -
>>>     -
>>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>>     -as hv2
>>>     -for chassis in gw1 gw2; do
>>>     -    echo "checking hv2 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -# make sure BFD is not enabled to hv1, we don't need it
>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-hv1-0],[0],
>>>     -         [[
>>>     -]])
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw2 now
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# disconnect GW2 from the network, GW1 should take over
>>>     -as gw2
>>>     -port=${sandbox}_br-phys
>>>     -as main ovs-vsctl del-port n1 $port
>>>     -
>>>     -bfd_dump
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw2 now
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# check that the chassis redirect port has been reclaimed by the
>>>     gw1 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
>>>     -as gw2
>>>     -for chassis in gw1 hv1 hv2; do
>>>     -    echo "checking gw2 -> $chassis"
>>>     -    OVS_WAIT_UNTIL([
>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0)
>>>     -    test "$bfd_cfg" = "enable=true min_rx=2000"
>>>     -])
>>>     -done
>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
>>>     -for chassis in gw1 hv1 hv2; do
>>>     -    echo "checking gw2 -> $chassis"
>>>     -    OVS_WAIT_UNTIL([
>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0)
>>>     -    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
>>>     -])
>>>     -done
>>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
>>>     -for chassis in gw1 hv1 hv2; do
>>>     -    echo "checking gw2 -> $chassis"
>>>     -    OVS_WAIT_UNTIL([
>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0)
>>>     -    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
>>>     -])
>>>     -done
>>>     -
>>>     -# Delete the inside1 vif. The ref_chassis in ha_chassis_group
>>>     shouldn't have
>>>     -# reference to hv1.
>>>     -as hv1 ovs-vsctl del-port hv1-vif1
>>>     -
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$hv2_ch_uuid" = "$ref_ch_list"])
>>>     -
>>>     -# Delete the inside2 vif.
>>>     -ovn-sbctl show
>>>     -
>>>     -echo "Deleting hv2-vif1"
>>>     -as hv2 ovs-vsctl del-port hv2-vif1
>>>     -
>>>     -# ref_chassis of ha_chassis_group should be empty
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     exp_ref_ch_list=""
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# Delete the Gateway_Chassis for lrp - outside
>>>     -ovn-nbctl clear Logical_Router_Port outside gateway_chassis
>>>     -
>>>     -# There shoud be no ha_chassis_group rows in SB DB.
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc 
>>> -l`])
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>     -
>>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>>     -ovn-nbctl remove NB_Global . options "bfd-min-tx"
>>>     -ovn-nbctl remove NB_Global . options "bfd-mult"
>>>     -
>>>     -# Now test with HA chassis group instead of Gateway chassis in 
>>> NB DB
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>     -
>>>     -ovn-nbctl list ha_chassis_group
>>>     -ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>     ha_chassis_group name=hagrp1`
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
>>>     -
>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>> rows
>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>     -# a logical router port.
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>     -
>>>     -# Associate hagrp1 to outside logical router port
>>>     -ovn-nbctl set Logical_Router_Port outside
>>>     ha_chassis_group=$hagrp1_uuid
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>>     -find ha_chassis_group | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>     chassis | \
>>>     -grep -v chassis-name | wc -l`])
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw1
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# make sure ARP responder flows for outside router port reside on
>>>     gw1 too
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# check that the chassis redirect port has been claimed by the
>>>     gw1 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -# Re add the ovs ports.
>>>     -for i in 1 2; do
>>>     -    as hv$i
>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>     -        ofport-request=1
>>>     -done
>>>     -
>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="hv1"`
>>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>     name="hv2"`
>>>     -
>>>     -exp_ref_ch_list=''
>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>     -do
>>>     -    if test $i = $hv1_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    elif test $i = $hv2_ch_uuid; then
>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>     -    fi
>>>     -done
>>>     -
>>>     -OVS_WAIT_UNTIL(
>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>     ha_chassis_group | sort`
>>>     -     # Trim the spaces.
>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>     -
>>>     -# Increase the priority of gw2
>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>     -grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>>     -| wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# check that the chassis redirect port has been reclaimed by the
>>>     gw2 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -# check BFD enablement on tunnel ports from gw1 #########
>>>     -as gw1
>>>     -for chassis in gw2 hv1 hv2; do
>>>     -    echo "checking gw1 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -
>>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>>     -as gw2
>>>     -for chassis in gw1 hv1 hv2; do
>>>     -    echo "checking gw2 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -
>>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>>     -as hv1
>>>     -for chassis in gw1 gw2; do
>>>     -    echo "checking hv1 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -# make sure BFD is not enabled to hv2, we don't need it
>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-hv2-0],[0],
>>>     -         [[
>>>     -]])
>>>     -
>>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>>     -as hv2
>>>     -for chassis in gw1 gw2; do
>>>     -    echo "checking hv2 -> $chassis"
>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-$chassis-0],[0],
>>>     -             [[enable=true
>>>     -]])
>>>     -done
>>>     -# make sure BFD is not enabled to hv1, we don't need it
>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>     name=ovn-hv1-0],[0],
>>>     -         [[
>>>     -]])
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw2 now
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# disconnect GW2 from the network, GW1 should take over
>>>     -as gw2
>>>     -port=${sandbox}_br-phys
>>>     -as main ovs-vsctl del-port n1 $port
>>>     -
>>>     -bfd_dump
>>>     -
>>>     -# make sure that flows for handling the outside router port
>>>     reside on gw2 now
>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>     -]])
>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>     -]])
>>>     -
>>>     -# check that the chassis redirect port has been reclaimed by the
>>>     gw1 chassis
>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>     Port_Binding \
>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>     -]])
>>>     -
>>>     -OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA
>>>     distributed router])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -ovn-nbctl ls-add ls0
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl create Logical_Router name=lr0
>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
>>>     <http://192.168.0.100/24>
>>>     -
>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>     -                    name=outside_gw1 chassis_name=hv2 priority=10
>>>     -- \
>>>     -          --id=@gc1 create Gateway_Chassis \
>>>     -                    name=outside_gw2 chassis_name=hv3 
>>> priority=1 -- \
>>>     -          set Logical_Router_Port lrp0 
>>> 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
>>>     -    type=router options:router-port=lrp0 addresses="router"
>>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>>     <http://10.0.0.1/24>
>>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
>>>     -    type=router options:router-port=lrp1 addresses="router"
>>>     -
>>>     -# Add NAT rules
>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24
>>>     <http://10.0.0.0/24>])
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -
>>>     -sim_add hv3
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>     -
>>>     -# Create a localnet port.
>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>> network_name=physnet1])
>>>     -
>>>     -# wait for earlier changes to take effect
>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>     -# add nat-addresses option
>>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="router"
>>>     -
>>>     -# Wait for packets to be received through hv2.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -only_broadcast_from_lrp1() {
>>>     -    grep "fffffffffffff00000000001"
>>>     -}
>>>     -
>>> -garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>>
>>>     -echo $garp > expout
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv1_snoop_tx
>>>     -echo "packets on hv1-snoopvif:"
>>>     -cat hv1_snoop_tx
>>>     -AT_CHECK([sort hv1_snoop_tx], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv2_br_phys_tx
>>>     -echo "packets on hv2 br-phys tx"
>>>     -cat hv2_br_phys_tx
>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv3_br_phys_tx
>>>     -echo "packets on hv3 br-phys tx"
>>>     -cat hv3_br_phys_tx
>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
>>>     -
>>>     -
>>>     -# at this point, we invert the priority of the gw chassis between
>>>     hv2 and hv3
>>>     -
>>>     -ovn-nbctl --wait=hv \
>>>     -          --id=@gc0 create Gateway_Chassis \
>>>     -                    name=outside_gw1 chassis_name=hv2 
>>> priority=1 -- \
>>>     -          --id=@gc1 create Gateway_Chassis \
>>>     -                    name=outside_gw2 chassis_name=hv3 priority=10
>>>     -- \
>>>     -          set Logical_Router_Port lrp0 
>>> 'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -
>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>     -
>>>     -# Wait for packets to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq >  hv1_snoopvif_tx
>>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv3_br_phys_tx
>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv2_br_phys_tx
>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>>     -
>>>     -# change localnet port tag.
>>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
>>>     -
>>>     -# wait for earlier changes to take effect
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int
>>>     table=65 | \
>>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>>     -])
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int
>>>     table=65 | \
>>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>>     -])
>>>     -
>>>     -# update nat-addresses option
>>>     -ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
>>>     -
>>>     -#Wait until the Port_Binding.nat_addresses is cleared.
>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns
>>>     nat_addresses find port_binding \
>>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>>     -
>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>     -
>>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>>     nat-addresses="router"
>>>     -
>>>     -#Wait until the Port_Binding.nat_addresses is set.
>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns
>>>     nat_addresses find port_binding \
>>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>>     -
>>>     -# Wait for packets to be received.
>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>> -garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>>
>>>     -echo $garp > expout
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq >  hv1_snoopvif_tx
>>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv3_br_phys_tx
>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>     uniq > hv2_br_phys_tx
>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't
>>>     bounce the master])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -# create two gateways with external network connectivity
>>>     -for i in 1 2; do
>>>     -    sim_add gw$i
>>>     -    as gw$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -    ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -done
>>>     -
>>>     -ovn-nbctl ls-add inside
>>>     -ovn-nbctl ls-add outside
>>>     -
>>>     -# create one hypervisors with a vif port the internal network
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=inside1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovn-nbctl lsp-add inside inside1 \
>>>     -        -- lsp-set-addresses inside1 "f0:00:00:01:22:01
>>>     192.168.1.101"
>>>     -
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -
>>>     -# Connect inside to R1
>>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>>     rp-inside \
>>>     -    type=router options:router-port=inside \
>>>     -    -- lsp-set-addresses rp-inside router
>>>     -
>>>     -# Connect outside to R1 as distributed router gateway port on 
>>> gw1+gw2
>>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>>     <http://192.168.0.101/24>
>>>     -
>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>>     -- \
>>>     -          --id=@gc1 create Gateway_Chassis \
>>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>>     -- \
>>>     -          set Logical_Router_Port outside
>>>     'gateway_chassis=[@gc0,@gc1]'
>>>     -
>>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>>     rp-outside \
>>>     -    type=router options:router-port=outside \
>>>     -    -- lsp-set-addresses rp-outside router
>>>     -
>>>     -# Create localnet port in outside
>>>     -ovn-nbctl lsp-add outside ln-outside
>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -# currently when ovn-controller is restarted, the old entry is
>>>     deleted
>>>     -# and a new one is created, which leaves the Gateway_Chassis with
>>>     -# an empty chassis for a while. NOTE: restarting ovn-controller
>>>     in tests
>>>     -# doesn't have the same effect because "name" is conserved, and 
>>> the
>>>     -# Chassis entry is not replaced.
>>>     -
>>>     -> gw1/ovn-controller.log
>>>     -
>>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>> name=gw2)
>>>     -ovn-sbctl destroy Chassis $gw2_chassis
>>>     -
>>>     -OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport"
>>>     gw1/ovn-controller.log`])
>>>     -
>>>     -OVN_CLEANUP([gw1],[gw2],[hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
>>>     -AT_KEYWORDS([ovn-nd_ns for unknown mac])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add sw0_ip6
>>>     -ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
>>>     -ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
>>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
>>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>>     -
>>>     -ovn-nbctl lr-add lr0_ip6
>>>     -ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01
>>>     aef0:0:0:0:0:0:0:0/64
>>>     -ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
>>>     -ovn-nbctl lsp-set-type lrp0_ip6-attachment router
>>>     -ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
>>>     -ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
>>>     -ovn-nbctl set logical_router_port lrp0_ip6
>>>     ipv6_ra_configs:address_mode=slaac
>>>     -
>>>     -ovn-nbctl ls-add public
>>>     -ovn-nbctl lsp-add public ln-public
>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>>     -
>>>     -ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
>>>     -2001:db8:1:0:200:02ff:fe01:0204/64 \
>>>     --- set Logical_Router_port ip6_public 
>>> options:redirect-chassis="hv1"
>>>     -
>>>     -#install static route
>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>     -ip_prefix="\:\:/0" 
>>> nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
>>>     --- add Logical_Router lr0_ip6 static_routes @lrt
>>>     -
>>>     -ovn-nbctl lsp-add public rp-ip6_public -- set 
>>> Logical_Switch_Port \
>>>     -rp-ip6_public  type=router options:router-port=ip6_public \
>>>     --- lsp-set-addresses rp-ip6_public router
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
>>>     -
>>>     -# There should be 2 Neighbor Advertisement flows for the router 
>>> port
>>>     -# aef0:: ip address in logical switch pipeline with action
>>>     nd_na_router.
>>>     -AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
>>>     -grep "nd_na_router" | wc -l], [0], [2
>>>     -])
>>>     -
>>>     -# There should be 4 Neighbor Advertisement flows with action
>>>     nd_na_router
>>>     -# in the router pipeline for the router lr0_ip6.
>>>     -AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
>>>     -wc -l], [0], [4
>>>     -])
>>>     -
>>>     -cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public |
>>>     grep _uuid | cut -f2 -d ":"`
>>>     -
>>>     -# There is only one chassis.
>>>     -chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d 
>>> ":"`
>>>     -OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding
>>>     $cr_uuid chassis`])
>>>     -
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for
>>>     unknown MAC
>>>     -# addresses. ovn-controller should generate an IPv6 NS request
>>>     for IPv6
>>>     -# packets whose MAC is unknown (in the ARP_REQUEST router
>>>     pipeline stage.
>>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -# This function sends ipv6 packet
>>>     -test_ipv6() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
>>>     -
>>>     -    local
>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
>>>     -    packet=${packet}8000000000000000
>>>     -
>>>     -    src_mac=000002010204
>>>     -
>>> expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
>>>     - 
>>> expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
>>>     - expected_packet=${expected_packet}${nd_target}0101${src_mac}
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} 
>>> $packet
>>>     -    rm -f ipv6_ns.expected
>>>     -    echo $expected_packet >> ipv6_ns.expected
>>>     -}
>>>     -
>>>     -src_mac=506400000002
>>>     -dst_mac=00000000af01
>>>     -src_ip=aef0000000000000526400fffe000002
>>>     -dst_ip=20010db800010000020002fffe010205
>>>     -dst_mcast_mac=3333ff010205
>>>     -mcast_node_ip=ff0200000000000000000001ff010205
>>>     -nd_target=20010db800010000020002fffe010205
>>>     -# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
>>>     -# should be received by the ports attached to br-phys.
>>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>>     -$mcast_node_ip $nd_target
>>>     -
>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>>     " " -f1)])
>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>>     " -f1)])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-phys_n1-tx.pcap | \
>>>     -trim_zeros > 1.packets
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-phys-tx.pcap | \
>>>     -trim_zeros > 2.packets
>>>     -
>>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum
>>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -# Now send a packet with destination ip other than
>>>     -# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>     -reset_pcap_file br-phys hv1/br-phys
>>>     -
>>>     -src_mac=506400000002
>>>     -dst_mac=00000000af01
>>>     -src_ip=aef0000000000000526400fffe000002
>>>     -dst_ip=20020ab8000100000200020000020306
>>>     -# multicast mac of the nexthop IP - 
>>> 2001:db8:1:0:200:02ff:fe01:1305
>>>     -dst_mcast_mac=3333ff011305
>>>     -mcast_node_ip=ff0200000000000000000001ff011305
>>>     -nd_target=20010db800010000020002fffe011305
>>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>>     -$mcast_node_ip $nd_target
>>>     -
>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>>     " " -f1)])
>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>>     " -f1)])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-phys_n1-tx.pcap | \
>>>     -trim_zeros > 1.packets
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-phys-tx.pcap | \
>>>     -trim_zeros > 2.packets
>>>     -
>>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>     -
>>>     -# Skipping the ICMPv6 checksum
>>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- options:requested-chassis for logical port])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -
>>>     -ovn-nbctl ls-add ls0
>>>     -ovn-nbctl lsp-add ls0 lsp0
>>>     -
>>>     -# create two hypervisors, each with one vif port
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- \
>>>     -set Interface hv1-vif0 ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.12
>>>     -ovs-vsctl -- add-port br-int hv2-vif0 -- \
>>>     -set Interface hv2-vif0 ofport-request=1
>>>     -
>>>     -# Allow only chassis hv1 to bind logical port lsp0.
>>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -# Retrieve hv1 and hv2 chassis UUIDs from southbound database
>>>     -ovn-sbctl wait-until chassis hv1
>>>     -ovn-sbctl wait-until chassis hv2
>>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
>>>     -hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
>>>     -
>>>     -# (1) Chassis hv2 should not bind lsp0 when requested-chassis 
>>> is hv1.
>>>     -echo "verifying that hv2 does not bind lsp0 when hv2
>>>     physical/logical mapping is added"
>>>     -as hv2
>>>     -ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0"
>>>     hv2/ovn-controller.log)])
>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding logical_port=lsp0) = x], [0], [])
>>>     -
>>>     -# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and
>>>     OFTABLE_LOG_TO_PHY tables.
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [1], [])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>>     output], [1], [])
>>>     -
>>>     -# (3) Chassis hv1 should bind lsp0 when physical to logical
>>>     mapping exists on hv1.
>>>     -echo "verifying that hv1 binds lsp0 when hv1 physical/logical
>>>     mapping is added"
>>>     -as hv1
>>>     -ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>>>     -
>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>>     hv1/ovn-controller.log)])
>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>>     -
>>>     -# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and
>>>     OFTABLE_LOG_TO_PHY tables.
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [0], [ignore])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>     actions=output:1], [0], [ignore])
>>>     -
>>>     -# (5) Chassis hv1 should release lsp0 binding and chassis hv2
>>>     should bind lsp0 when
>>>     -# the requested chassis for lsp0 is changed from hv1 to hv2.
>>>     -echo "verifying that lsp0 binding moves when requested-chassis is
>>>     changed"
>>>     -
>>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>>     this chassis" hv1/ovn-controller.log)])
>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding logical_port=lsp0) = x"$hv2_uuid"])
>>>     -
>>>     -# (6) Chassis hv2 should add flows and hv1 should not.
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [0], [ignore])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>>     actions=output:1], [0], [ignore])
>>>     -
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [1], [])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>     output], [1], [])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- options:requested-chassis with hostname])
>>>     -
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls0
>>>     -ovn-nbctl lsp-add ls0 lsp0
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0
>>>     ofport-request=1
>>>     -
>>>     -ovn-sbctl wait-until chassis hv1
>>>     -hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis
>>>     name=hv1)
>>>     -echo "hv1_hostname=${hv1_hostname}"
>>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>>     requested-chassis=${hv1_hostname}
>>>     -as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>>>     -
>>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
>>>     -echo "hv1_uuid=${hv1_uuid}"
>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>>     hv1/ovn-controller.log)])
>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [0], [ignore])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>     actions=output:1], [0], [ignore])
>>>     -
>>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>>     requested-chassis=non-existant-chassis
>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>>     this chassis" hv1/ovn-controller.log)])
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>     port_binding logical_port=lsp0) = x], [0], [])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>     in_port=1], [1], [])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>     output], [1], [])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IPv6 periodic RA])
>>>     -ovn_start
>>>     -
>>>     -# This test sets up two hypervisors.
>>>     -# hv1 and hv2 run ovn-controllers, and
>>>     -# each has a VIF connected to the same
>>>     -# logical switch in OVN. The logical
>>>     -# switch is connected to a logical
>>>     -# router port that is configured to send
>>>     -# periodic router advertisements.
>>>     -#
>>>     -# The reason for having two ovn-controller
>>>     -# hypervisors is to ensure that the
>>>     -# periodic RAs being sent by each ovn-controller
>>>     -# are kept to their local hypervisors. If the
>>>     -# packets are not kept local, then each port
>>>     -# will receive too many RAs.
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -sim_add hv2
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -
>>>     -ovn-nbctl lr-add ro
>>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
>>>     -
>>>     -ovn-nbctl ls-add sw
>>>     -ovn-nbctl lsp-add sw sw-ro
>>>     -ovn-nbctl lsp-set-type sw-ro router
>>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>>     -ovn-nbctl lsp-add sw sw-p1
>>>     -ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02
>>>     aef0::200:ff:fe00:2"
>>>     -ovn-nbctl lsp-add sw sw-p2
>>>     -ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03
>>>     aef0::200:ff:fe00:3"
>>>     -
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:send_periodic=true
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:address_mode=slaac
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:max_interval=4
>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:min_interval=3
>>>     -
>>>     -for i in 1 2 ; do
>>>     -    as hv$i
>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>     -        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>     -        ofport-request=1
>>>     -done
>>>     -
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -
>>>     -}
>>>     -
>>>     -construct_expected_ra() {
>>>     -    local src_mac=000000000001
>>>     -    local dst_mac=333300000001
>>>     -    local src_addr=fe80000000000000020000fffe000001
>>>     -    local dst_addr=ff020000000000000000000000000001
>>>     -
>>>     -    local mtu=$1
>>>     -    local ra_mo=$2
>>>     -    local ra_prefix_la=$3
>>>     -
>>>     -    local slla=0101${src_mac}
>>>     -    local mtu_opt=""
>>>     -    if test $mtu != 0; then
>>>     -        mtu_opt=05010000${mtu}
>>>     -    fi
>>>     -    shift 3
>>>     -
>>>     -    local prefix=""
>>>     -    while [[ $# -gt 0 ]] ; do
>>>     -        local size=$1
>>>     -        local net=$2
>>>     -
>>> prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net} 
>>>
>>>     -        shift 2
>>>     -    done
>>>     -
>>>     -    local 
>>> ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
>>>     -    local icmp=8600XXXX${ra}
>>>     -
>>>     -    local ip_len=$(expr ${#icmp} / 2)
>>>     -    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
>>>     -
>>>     -    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
>>>     -    local eth=${dst_mac}${src_mac}86dd${ip}
>>>     -    local packet=${eth}
>>>     -    echo $packet >> expected
>>>     -}
>>>     -
>>>     -ra_test() {
>>>     -    construct_expected_ra $@
>>>     -
>>>     -    for i in hv1 hv2 ; do
>>>     -        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut
>>>     -d " " -f1)])
>>>     -
>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" $i/vif1-tx.pcap > packets
>>>     -
>>>     -        cat expected | cut -c -112 > expout
>>>     -        AT_CHECK([cat packets | cut -c -112], [0], [expout])
>>>     -
>>>     -        # Skip ICMPv6 checksum.
>>>     -        cat expected | cut -c 117- > expout
>>>     -        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
>>>     -
>>>     -        rm -f packets
>>>     -        as $i reset_pcap_file $i-vif1 $i/vif1
>>>     -    done
>>>     -
>>>     -    rm -f expected
>>>     -}
>>>     -
>>>     -# Baseline test with no MTU
>>>     -ra_test 0 00 c0 40 aef00000000000000000000000000000
>>>     -
>>>     -# Now make sure an MTU option makes it
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:mtu=1500
>>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
>>>     -
>>>     -# Now test for multiple network prefixes
>>>     -ovn-nbctl --wait=hv set Logical_Router_port ro-sw
>>>     networks='aef0\:\:1/64 fd0f\:\:1/48'
>>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30
>>>     fd0f0000000000000000000000000000
>>>     -
>>>     -# Test a different address mode now
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>>     -ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30
>>>     fd0f0000000000000000000000000000
>>>     -
>>>     -# And the other address mode
>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>>     -ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30
>>>     fd0f0000000000000000000000000000
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ACL reject rule test])
>>>     -AT_KEYWORDS([acl-reject])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>     IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv4 packet with
>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>     of the icmp destination
>>>     -# unreachable frame generated from ACL rule hit
>>>     -#
>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>     -# HV is a hypervisor number
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>> digits
>>>     -test_ip_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ipv4_dst=$6 ip_chksum=$7
>>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>>     -    shift 9
>>>     -
>>>     -    local ip_ttl=ff
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>>
>>>     -
>>>     -    local reply_icmp_ttl=ff
>>>     -    local icmp_type_code_response=0301
>>>     -    local icmp_data=00000000
>>>     -    local
>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>>
>>>     -    local
>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>     EXP_ICMP_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv6 packet with
>>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
>>>     -# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination
>>>     unreachable frame generated from ACL rule hit
>>>     -test_ipv6_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>     ipv6_dst=$6 exp_icmp_chksum=$7
>>>     -    shift 7
>>>     -
>>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>>     -    local 
>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
>>>     -
>>>     -    local
>>> reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>     IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>>     EXP_TCP_RST_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an TCP syn segment with
>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT,
>>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>>     checksums of the tcp reset segment generated from ACL rule hit
>>>     -#
>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>     -# HV is an hypervisor number
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>>     each 4 hex digits
>>>     -test_tcp_syn_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ipv4_dst=$6 ip_chksum=$7
>>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>>     -    shift 12
>>>     -
>>>     -    local ip_ttl=ff
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>
>>>     -
>>>     -    local tcp_rst_ttl=ff
>>>     -    local
>>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# Create hypervisors hv[123].
>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>     -# Add all of the vifs to a single logical switch sw0.
>>>     -
>>>     -net_add n1
>>>     -ovn-nbctl ls-add sw0
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2 3; do
>>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>>     192.168.1.$i$j"
>>>     -
>>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>>     -                set interface vif$i$j \
>>>     -                external-ids:iface-id=sw0-p$i$j \
>>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>     -                ofport-request=$i$j
>>>     -    done
>>>     -done
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>     -sleep 1
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    : > vif${i}1.expected
>>>     -done
>>>     -
>>>     -ovn-nbctl --log acl-add sw0 to-lport 1000 "outport ==
>>>     \"sw0-p12\"" reject
>>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>>     \"sw0-p11\"" reject
>>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>>     \"sw0-p21\"" reject
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>>     -
>>>     -test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168
>>>     1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
>>>     -test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168
>>>     1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
>>>     -test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168
>>>     1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
>>>     -
>>>     -test_ipv6_packet 11 1 000000000011 000000000021
>>>     fe80000000000000020001fffe000001 
>>> fe80000000000000020001fffe000002 6183
>>>     -
>>>     -test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex
>>>     192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 
>>> 4486
>>>     -test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex
>>>     192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 
>>> 4486
>>>     -test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex
>>>     192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 
>>> 4486
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], 
>>> [vif${i}1.expected])
>>>     -done
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- Port Groups])
>>>     -AT_KEYWORDS([ovnpg])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -#
>>>     -# Three logical switches ls1, ls2, ls3.
>>>     -# One logical router lr0 connected to ls[123],
>>>     -# with nine subnets, three per logical switch:
>>>     -#
>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>> <http://192.168.11.0/24>
>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>> <http://192.168.12.0/24>
>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>> <http://192.168.13.0/24>
>>>     -#    ...
>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>> <http://192.168.33.0/24>
>>>     -#
>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>     first two
>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>     -#
>>>     -# This test will create two port groups and uses them in ACL.
>>>     -
>>>     -get_lsp_uuid () {
>>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>>     -}
>>>     -
>>>     -pg1_ports=
>>>     -pg2_ports=
>>>     -for i in 1 2 3; do
>>>     -    ovn-nbctl ls-add ls$i
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            ovn-nbctl \
>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>>     -            if test $i != 3 && test $k == 1; then
>>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>>     -            fi
>>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>>     -            if test $i != 1 && test $k == 2; then
>>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>>     -            fi
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>     192.168.$i$j.254/24
>>>     -        ovn-nbctl \
>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>     type=router \
>>>     -                             options:router-port=lrp$i$j \
>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>>     -
>>>     -# create ACLs on all lswitches to drop traffic from pg2 to pg1
>>>     -ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src
>>>     == $pg2_ip4' drop
>>>     -ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src
>>>     == $pg2_ip4' drop
>>>     -ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src
>>>     == $pg2_ip4' drop
>>>     -
>>>     -# Physical network:
>>>     -#
>>>     -# Three hypervisors hv[123].
>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>     lp?13 on hv3.
>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>     on hv3.
>>>     -# lp?3[123] all on hv3.
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    case $1 in dnl (
>>>     -        ?11) echo 1 ;; dnl (
>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its
>>>     logical router
>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>     -vif_to_lrp() {
>>>     -    echo ${1%?}
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its logical
>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>     -vif_to_ls() {
>>>     -    echo ${1%??}
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -done
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            hv=`vif_to_hv $i$j$k`
>>>     -                as hv$hv ovs-vsctl \
>>>     -                -- add-port br-int vif$i$j$k \
>>>     -                -- set Interface vif$i$j$k \
>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>     -                    ofport-request=$i$j$k
>>>     -        done
>>>     -    done
>>>     -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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -#
>>>     -# This shell function causes a packet to be received on INPORT.
>>>     The packet's
>>>     -# content has Ethernet destination DST and source SRC (each
>>>     exactly 12 hex
>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs
>>>     (zero or
>>>     -# more) list the VIFs on which the packet should be received.
>>>     INPORT and the
>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>>     for vif123.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            : > $i$j$k.expected
>>>     -        done
>>>     -    done
>>>     -done
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    in_ls=`vif_to_ls $inport`
>>>     -    in_lrp=`vif_to_lrp $inport`
>>>     -    for outport; do
>>>     -        out_ls=`vif_to_ls $outport`
>>>     -        if test $in_ls = $out_ls; then
>>>     -            # Ports on the same logical switch receive exactly
>>>     the same packet.
>>>     -            echo $packet
>>>     -        else
>>>     -            # Routing decrements TTL and updates source and 
>>> dest MAC
>>>     -            # (and checksum).
>>>     -            out_lrp=`vif_to_lrp $outport`
>>>     -            echo
>>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -        fi >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>     -as hv1 ovn-sbctl list port_binding
>>>     -as hv1 ovn-sbctl list datapath_binding
>>>     -as hv1 ovn-sbctl list port_group
>>>     -as hv1 ovn-sbctl list address_set
>>>     -as hv1 ovn-sbctl dump-flows
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Send IP packets between all pairs of source and destination 
>>> ports,
>>>     -# packets matches ACL (pg2 to pg1) should be dropped
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -for is in 1 2 3; do
>>>     -  for js in 1 2 3; do
>>>     -    for ks in 1 2 3; do
>>>     -      bcast=
>>>     -      s=$is$js$ks
>>>     -      smac=f00000000$s
>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>     -      for id in 1 2 3; do
>>>     -          for jd in 1 2 3; do
>>>     -              for kd in 1 2 3; do
>>>     -                d=$id$jd$kd
>>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>>     -                if test $is = $id; then dmac=f00000000$d; else
>>>     dmac=00000000ff$is$js; fi
>>>     -                if test $d != $s; then unicast=$d; else 
>>> unicast=; fi
>>>     -
>>>     -                # packets matches ACL should be dropped
>>>     -                if test $id != 3 && test $kd == 1; then
>>>     -                    if test $is != 1 && test $ks == 2; then
>>>     -                        unicast=
>>>     -                    fi
>>>     -                fi
>>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>>     -              done
>>>     -          done
>>>     -        done
>>>     -      done
>>>     -  done
>>>     -done
>>>     -
>>>     -# Allow some time for packet forwarding.
>>>     -# XXX This can be improved.
>>>     -sleep 1
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>     -                              [$i$j$k.expected])
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ACLs on Port Groups])
>>>     -AT_KEYWORDS([ovnpg_acl])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -#
>>>     -# Three logical switches ls1, ls2, ls3.
>>>     -# One logical router lr0 connected to ls[123],
>>>     -# with nine subnets, three per logical switch:
>>>     -#
>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>> <http://192.168.11.0/24>
>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>> <http://192.168.12.0/24>
>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>> <http://192.168.13.0/24>
>>>     -#    ...
>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>> <http://192.168.33.0/24>
>>>     -#
>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>     first two
>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>     -#
>>>     -# This test will create two port groups and ACLs will be applied
>>>     on them.
>>>     -
>>>     -get_lsp_uuid () {
>>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>>     -}
>>>     -
>>>     -pg1_ports=
>>>     -pg2_ports=
>>>     -for i in 1 2 3; do
>>>     -    ovn-nbctl ls-add ls$i
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            ovn-nbctl \
>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>>     -            if test $i != 3 && test $k == 1; then
>>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>>     -            fi
>>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>>     -            if test $i != 1 && test $k == 2; then
>>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>>     -            fi
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>     192.168.$i$j.254/24
>>>     -        ovn-nbctl \
>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>     type=router \
>>>     -                             options:router-port=lrp$i$j \
>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>>     -
>>>     -# create ACLs on pg1 to drop traffic from pg2 to pg1
>>>     -ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
>>>     -ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
>>>     -        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
>>>     -
>>>     -# Physical network:
>>>     -#
>>>     -# Three hypervisors hv[123].
>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>     lp?13 on hv3.
>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>     on hv3.
>>>     -# lp?3[123] all on hv3.
>>>     -
>>>     -# Given the name of a logical port, prints the name of the 
>>> hypervisor
>>>     -# on which it is located.
>>>     -vif_to_hv() {
>>>     -    case $1 in dnl (
>>>     -        ?11) echo 1 ;; dnl (
>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its
>>>     logical router
>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>     -vif_to_lrp() {
>>>     -    echo ${1%?}
>>>     -}
>>>     -
>>>     -# Given the name of a logical port, prints the name of its logical
>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>     -vif_to_ls() {
>>>     -    echo ${1%??}
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2 3; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -done
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            hv=`vif_to_hv $i$j$k`
>>>     -                as hv$hv ovs-vsctl \
>>>     -                -- add-port br-int vif$i$j$k \
>>>     -                -- set Interface vif$i$j$k \
>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>     -                    ofport-request=$i$j$k
>>>     -        done
>>>     -    done
>>>     -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
>>>     -
>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>     -# XXX This should be more systematic.
>>>     -sleep 1
>>>     -
>>>     -lsp_to_mac() {
>>>     -    echo f0:00:00:00:0${1:0:1}:${1:1:2}
>>>     -}
>>>     -
>>>     -lrp_to_mac() {
>>>     -    echo 00:00:00:00:ff:$1
>>>     -}
>>>     -
>>>     -# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE 
>>> OUTPORT...
>>>     -#
>>>     -# This shell function causes a ICMP packet to be received on 
>>> INPORT.
>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>     should
>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>     switch
>>>     -# port numbers, e.g. 123 for vif123.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            : > $i$j$k.expected
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -test_icmp() {
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     icmp_type=$6
>>>     -    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
>>>     -                  eth.dst==$dst_mac && ip.ttl==64 && 
>>> ip4.src==$src_ip
>>>     -                  && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
>>>     -                  icmp4.code==0"
>>>     -    shift; shift; shift; shift; shift; shift
>>>     -    hv=hv`vif_to_hv $inport`
>>>     -    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -    in_ls=`vif_to_ls $inport`
>>>     -    in_lrp=`vif_to_lrp $inport`
>>>     -    for outport; do
>>>     -        out_ls=`vif_to_ls $outport`
>>>     -        if test $in_ls = $out_ls; then
>>>     -            # Ports on the same logical switch receive exactly
>>>     the same packet.
>>>     -            echo $packet | ovstest test-ovn expr-to-packets
>>>     -        else
>>>     -            # Routing decrements TTL and updates source and 
>>> dest MAC
>>>     -            # (and checksum).
>>>     -            out_lrp=`vif_to_lrp $outport`
>>>     -            exp_smac=`lrp_to_mac $out_lrp`
>>>     -            exp_dmac=`lsp_to_mac $outport`
>>>     -            exp_packet="eth.src==$exp_smac && 
>>> eth.dst==$exp_dmac &&
>>>     -                ip.ttl==63 && ip4.src==$src_ip && 
>>> ip4.dst==$dst_ip &&
>>>     -                icmp4.type==$icmp_type && icmp4.code==0"
>>>     -            echo $exp_packet | ovstest test-ovn expr-to-packets
>>>     -
>>>     -        fi >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>     -as hv1 ovn-sbctl list port_binding
>>>     -as hv1 ovn-sbctl list datapath_binding
>>>     -as hv1 ovn-sbctl list port_group
>>>     -as hv1 ovn-sbctl list address_set
>>>     -as hv1 ovn-sbctl dump-flows
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Send IP packets between all pairs of source and destination 
>>> ports,
>>>     -# packets matches ACL1 but not ACL2 should be dropped
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -for is in 1 2 3; do
>>>     -  for js in 1 2 3; do
>>>     -    for ks in 1 2 3; do
>>>     -      bcast=
>>>     -      s=$is$js$ks
>>>     -      slsp_mac=`lsp_to_mac $s`
>>>     -      slrp_mac=`lrp_to_mac $is$js`
>>>     -      sip=192.168.$is$js.$ks
>>>     -      for id in 1 2 3; do
>>>     -          for jd in 1 2 3; do
>>>     -              for kd in 1 2 3; do
>>>     -                d=$id$jd$kd
>>>     -                dlsp_mac=`lsp_to_mac $d`
>>>     -                dlrp_mac=`lrp_to_mac $id$jd`
>>>     -                dip=192.168.$id$jd.$kd
>>>     -                if test $is = $id; then dmac=$dlsp_mac; else
>>>     dmac=$slrp_mac; fi
>>>     -                if test $d != $s; then unicast=$d; else 
>>> unicast=; fi
>>>     -
>>>     -                # packets matches ACL1 but not ACL2 should be 
>>> dropped
>>>     -                if test $id != 3 && test $kd == 1; then
>>>     -                    if test $is == 1 || test $ks != 2; then
>>>     -                        unicast=
>>>     -                    fi
>>>     -                fi
>>>     -                # icmp request (type = 8)
>>>     -                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
>>>     -
>>>     -                # if packets are not dropped, test the return
>>>     traffic (icmp echo)
>>>     -                # to make sure stateful works, too.
>>>     -                if test x$unicast != x; then
>>>     -                    if test $is = $id; then dmac=$slsp_mac; else
>>>     dmac=$dlrp_mac; fi
>>>     -                    # icmp echo (type = 0)
>>>     -                    test_icmp $unicast $dlsp_mac $dmac $dip 
>>> $sip 0 $s
>>>     -                fi
>>>     -              done
>>>     -          done
>>>     -        done
>>>     -      done
>>>     -  done
>>>     -done
>>>     -
>>>     -# Allow some time for packet forwarding.
>>>     -# XXX This can be improved.
>>>     -sleep 1
>>>     -
>>>     -# Now check the packets actually received against the ones 
>>> expected.
>>>     -for i in 1 2 3; do
>>>     -    for j in 1 2 3; do
>>>     -        for k in 1 2 3; do
>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>     -                              [$i$j$k.expected])
>>>     -        done
>>>     -    done
>>>     -done
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (static
>>>     addressing)])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -ovn-nbctl lsp-add ls1 lp1
>>>     -ovn-nbctl lsp-add ls1 lp2
>>>     -ovn-nbctl lsp-add ls1 lp3
>>>     -
>>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1
>>>     2001:db8::1"
>>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2
>>>     2001:db8::2"
>>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3
>>>     2001:db8::3"
>>>     -
>>>     -ovn-nbctl create Port_Group name=pg1
>>>     -ovn-nbctl create Port_Group name=pg2
>>>     -
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>>     pg1 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>     pg1 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>     pg2 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>>     pg2 ports @p
>>>     -
>>>     -ovn-nbctl --wait=sb sync
>>>     -
>>>     -dnl Check if port group address sets were populated with ports'
>>>     addresses
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>     -         [0], [[["10.0.0.1", "10.0.0.2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>>     -         [0], [[["10.0.0.2", "10.0.0.3"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>     -         [0], [[["2001:db8::1", "2001:db8::2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>>     -         [0], [[["2001:db8::2", "2001:db8::3"]]
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-set-addresses lp1 \
>>>     -    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
>>>     -
>>>     -dnl Check if updated address got propagated to the port group
>>>     address sets
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>     -         [0], [[["10.0.0.11", "10.0.0.2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>     -         [0], [[["2001:db8::11", "2001:db8::2"]]
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic
>>>     addressing)])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl ls-add ls2
>>>     -ovn-nbctl ls-add ls3
>>>     -
>>>     -ovn-nbctl set Logical_Switch ls1 \
>>>     -    other_config:subnet=10.1.0.0/24 <http://10.1.0.0/24>
>>>     other_config:ipv6_prefix="2001:db8:1::"
>>>     -ovn-nbctl set Logical_Switch ls2 \
>>>     -    other_config:subnet=10.2.0.0/24 <http://10.2.0.0/24>
>>>     other_config:ipv6_prefix="2001:db8:2::"
>>>     -ovn-nbctl set Logical_Switch ls3 \
>>>     -    other_config:subnet=10.3.0.0/24 <http://10.3.0.0/24>
>>>     other_config:ipv6_prefix="2001:db8:3::"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 lp1
>>>     -ovn-nbctl lsp-add ls2 lp2
>>>     -ovn-nbctl lsp-add ls3 lp3
>>>     -
>>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
>>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
>>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
>>>     -
>>>     -ovn-nbctl create Port_Group name=pg1
>>>     -ovn-nbctl create Port_Group name=pg2
>>>     -
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>>     pg1 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>     pg1 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>     pg2 ports @p
>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>>     pg2 ports @p
>>>     -
>>>     -ovn-nbctl --wait=sb sync
>>>     -
>>>     -dnl Check if port group address sets were populated with ports'
>>>     addresses
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>     -         [0], [[["10.1.0.2", "10.2.0.2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>>     -         [0], [[["10.2.0.2", "10.3.0.2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>     -         [0], [[["2001:db8:1::ff:fe00:1", 
>>> "2001:db8:2::ff:fe00:2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>>     -         [0], [[["2001:db8:2::ff:fe00:2", 
>>> "2001:db8:3::ff:fe00:3"]]
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb set Logical_Switch ls1 \
>>>     -    other_config:subnet=10.11.0.0/24 <http://10.11.0.0/24>
>>>     other_config:ipv6_prefix="2001:db8:11::"
>>>     -
>>>     -dnl Check if updated address got propagated to the port group
>>>     address sets
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>     -         [0], [[["10.11.0.2", "10.2.0.2"]]
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>     -         [0], [[["2001:db8:11::ff:fe00:1", 
>>> "2001:db8:2::ff:fe00:2"]]
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ACL conjunction])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>> 10.0.0.4"
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>>>     -
>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 
>>> 10.0.0.6"
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=2
>>>     -
>>>     -ovn-nbctl create Address_Set name=set1 \
>>>     -addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
>>>     -ovn-nbctl create Address_Set name=set2 \
>>>     -addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
>>>     -ovn-nbctl acl-add ls1 to-lport 1002 \
>>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
>>>     -ovn-nbctl acl-add ls1 to-lport 1001 \
>>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
>>>     -
>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>     -#
>>>     -# This shell function causes an ip packet to be received on 
>>> INPORT.
>>>     -# The packet's content has Ethernet destination DST and source SRC
>>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>>     digits).
>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>     should
>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>     switch
>>>     -# port numbers, e.g. 11 for vif11.
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
>>>     -${dst_ip}0035111100080000
>>>     -    shift; shift; shift; shift; shift
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -    for outport; do
>>>     -        echo $packet >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -
>>>     -sip=`ip_to_hex 10 0 0 4`
>>>     -dip=`ip_to_hex 10 0 0 6`
>>>     -
>>>     -test_ip 1 f00000000001 f00000000002 $sip $dip 2
>>>     -
>>>     -cat 2.expected > expout
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [expout])
>>>     -
>>>     -# There should be total of 12 flows present with conjunction
>>>     action and 2 flows
>>>     -# with conj match. Eg.
>>>     -# table=44, priority=2002,conj_id=2,metadata=0x1
>>>     actions=resubmit(,45)
>>>     -# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6
>>>     actions=conjunction(2,2/2)
>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4
>>>     actions=conjunction(2,2/2)
>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5
>>>     actions=conjunction(2,2/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7
>>>     actions=conjunction(3,2/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9
>>>     actions=conjunction(3,2/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8
>>>     actions=conjunction(3,2/2)
>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6
>>>     actions=conjunction(2,1/2)
>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4
>>>     actions=conjunction(2,1/2)
>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5
>>>     actions=conjunction(2,1/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6
>>>     actions=conjunction(3,1/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4
>>>     actions=conjunction(3,1/2)
>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5
>>>     actions=conjunction(3,1/2)
>>>     -
>>>     -OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
>>>     -grep conjunction | wc -l`])
>>>     -OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
>>>     -grep conj_id | wc -l`])
>>>     -
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -# Set the ip address for ls1-lp2 from set2 so that the drop ACL
>>>     flow is hit.
>>>     -ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7
>>>     20.0.0.4"
>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>     10.0.0.7 20.0.0.4"
>>>     -
>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>     -
>>>     -rm -f 2.packets
>>>     -
>>>     -sip=`ip_to_hex 10 0 0 4`
>>>     -dip=`ip_to_hex 10 0 0 7`
>>>     -
>>>     -test_ip 1 f00000000001 f00000000002 $sip $dip
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/vif2-tx.pcap > 2.packets
>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- TTL exceeded])
>>>     -AT_KEYWORDS([ttl-exceeded])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>     IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv4 packet with
>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified
>>>     and TTL set to 1.
>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>     of the icmp time exceeded frame
>>>     -# generated by OVN logical router
>>>     -#
>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>     -# HV is a hypervisor number
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>> digits
>>>     -test_ip_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ipv4_dst=$6 ip_router=$7 ip_chksum=$8
>>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
>>>     -    shift 10
>>>     -
>>>     -    local ip_ttl=01
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>>
>>>     -
>>>     -    local reply_icmp_ttl=fe
>>>     -    local icmp_type_code_response=0b00
>>>     -    local icmp_data=00000000
>>>     -    local
>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>>
>>>     -    local
>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>>     IPV6_ROUTER EXP_ICMP_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv6
>>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as 
>>> specified.
>>>     -# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum
>>>     of the icmpv6 ttl exceeded
>>>     -# packet sent by OVN logical router
>>>     -test_ip6_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>>     -    shift 8
>>>     -
>>>     -    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
>>>     -    local
>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a 
>>>
>>>     -
>>>     -    local
>>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -for i in 1 2; do
>>>     -    net_add n$i
>>>     -    ovn-nbctl ls-add sw$i
>>>     -
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>>     -
>>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>>     192.168.$i.1 2001:db8:$i::11"
>>>     -
>>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>>     -        set interface vif$i \
>>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>>     -            ofport-request=$i
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2; do
>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>>     192.168.$i.254/24 2001:db8:$i::1/64
>>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>>     type=router \
>>>     -                options:router-port=lrp$i
>>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 
>>> 2001:db8:'$i'::1"'
>>>     -done
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>     1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae
>>>     f4ff
>>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>>     20010db8000100000000000000000011 20010db8000200000000000000000011
>>>     20010db8000100000000000000000001 d461
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- router port unreachable])
>>>     -AT_KEYWORDS([router-port-unreachable])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
>>>     L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv4 packet with
>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM
>>>     as specified.
>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>     of the icmp frame generated by OVN logical router
>>>     -# EXP_ICMP_CODE are code and type of the icmp frame generated by
>>>     OVN logical router
>>>     -#
>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>     -# HV is a hypervisor number
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>> digits
>>>     -test_ip_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ip_router=$6 l4_proto=$7 ip_chksum=$8
>>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10} 
>>> exp_icmp_code=${11}
>>>     -    shift 11
>>>     -
>>>     -    local ip_ttl=ff
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router} 
>>>
>>>     -
>>>     -    local reply_icmp_ttl=fe
>>>     -    local icmp_data=00000000
>>>     -    local
>>> reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
>>>     -    local
>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC
>>>     IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>>     EXP_TCP_RST_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an TCP syn segment with
>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT,
>>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>>     checksums of the tcp reset segment generated by OVN logical router
>>>     -#
>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>     -# HV is an hypervisor number
>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>>     each 4 hex digits
>>>     -test_tcp_syn_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ip_router=$6 ip_chksum=$7
>>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>>     -    shift 12
>>>     -
>>>     -    local ip_ttl=ff
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>
>>>     -
>>>     -    local tcp_rst_ttl=fe
>>>     -    local
>>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>>>     TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is a TCP syn segment with
>>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT
>>>     and TCP_CHKSUM as specified.
>>>     -# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset
>>>     segment generated by OVN logical router
>>>     -test_tcp6_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>     ipv6_router=$6
>>>     -    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
>>>     -    local exp_tcp_rst_chksum=${10}
>>>     -    shift 10
>>>     -
>>>     -    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
>>>     -    local
>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>
>>>     -
>>>     -    local
>>> reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>>     IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
>>>     -#
>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>     The packet is an IPv6
>>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO,
>>>     IPV6_LEN and DATA as specified.
>>>     -# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of
>>>     the icmp6 packet sent by OVN logical router
>>>     -test_ip6_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>     ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
>>>     -    local exp_icmp_code=${10} exp_icmp_chksum=${11}
>>>     -    shift 11
>>>     -
>>>     -    local
>>> ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
>>>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
>>>     -
>>>     -    local
>>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr} 
>>>
>>>     -    echo $reply >> vif$inport.expected
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -for i in 1 2; do
>>>     -    net_add n$i
>>>     -    ovn-nbctl ls-add sw$i
>>>     -
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>>     -
>>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>>     192.168.$i.1 2001:db8:$i::11"
>>>     -
>>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>>     -        set interface vif$i \
>>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>>     -            ofport-request=$i
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -for i in 1 2; do
>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>>     192.168.$i.254/24 2001:db8:$i::1/64
>>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>>     type=router \
>>>     -                options:router-port=lrp$i
>>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 
>>> 2001:db8:'$i'::1"'
>>>     -done
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>     1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>     1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
>>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>>     20010db8000100000000000000000011 20010db8000100000000000000000001
>>>     11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>     -
>>>     -test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>>>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
>>>     -test_ip6_packet 2 2 000000000002 00000000ff02
>>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>>     84 0004 01020304 0103 627e
>>>     -test_tcp6_packet 2 2 000000000002 00000000ff02
>>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>>     8b40 3039 0000 4486
>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ovn-controller exit])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -# Logical network:
>>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>     -# sw1 has a single port bound on hv1
>>>     -# sw2 has a single port bound on hv2
>>>     -
>>>     -ovn-nbctl lr-add ro
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl ls-add sw2
>>>     -
>>>     -sw1_ro_mac=00:00:10:00:00:01
>>>     -sw1_ro_ip=10.0.0.1
>>>     -sw2_ro_mac=00:00:20:00:00:01
>>>     -sw2_ro_ip=20.0.0.1
>>>     -sw1_p1_mac=00:00:10:00:00:02
>>>     -sw1_p1_ip=10.0.0.2
>>>     -sw2_p1_mac=00:00:20:00:00:02
>>>     -sw2_p1_ip=20.0.0.2
>>>     -
>>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>>     type=router \
>>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>>     type=router \
>>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>>     -
>>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>>     -
>>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -sleep 1
>>>     -
>>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>>     eth.dst==$sw1_ro_mac &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>>     ip4.dst==$sw2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -
>>>     -# Start by Sending the packet and make sure it makes it there as
>>>     expected
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>>     ip4.dst==$sw2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Stop ovn-controller on hv2
>>>     -as hv2 ovs-appctl -t ovn-controller exit
>>>     -
>>>     -# Now send the packet again. This time, it should not arrive.
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>>     -as hv2 start_daemon ovn-controller
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- external logical port])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -sim_add hv2
>>>     -sim_add hv3
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>>     -
>>>     -# Add a couple of external logical port
>>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
>>>     --- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 
>>> ae70::6"
>>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
>>>     -"f0:00:00:00:00:03 10.0.0.6 ae70::6"
>>>     -ovn-nbctl lsp-set-type ls1-lp_ext1 external
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
>>>     --- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 
>>> ae70::7"
>>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
>>>     -"f0:00:00:00:00:04 10.0.0.7 ae70::8"
>>>     -ovn-nbctl lsp-set-type ls1-lp_ext2 external
>>>     -
>>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>>     <http://10.0.0.0/24> \
>>>     -options="\"server_id\"=\"10.0.0.1\"
>>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>>     -
>>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
>>>     -
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
>>>     -
>>>     -# Create a logical router and connect it to ls1
>>>     -ovn-nbctl lr-add lr0
>>>     -ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
>>>     <http://10.0.0.1/24>
>>>     -ovn-nbctl lsp-add ls1 ls1-lr0
>>>     -ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
>>>     -    options:router-port=lr0-ls1 addresses=router
>>>     -
>>>     -# Create HA chassis group
>>>     -ovn-nbctl ha-chassis-group-add hagrp1
>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>>     -
>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>     ha_chassis_group name="hagrp1"`
>>>     -
>>>     -# There should be 1 HA_Chassis rows with chassis sets
>>>     -OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk
>>>     '{print $3}' \
>>>     -| grep '-' | wc -l ], [0], [1
>>>     -])
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-phys hv1-ext1 -- \
>>>     -    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/ext1-rx.pcap \
>>>     -    ofport-request=2
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-phys hv2-ext2 -- \
>>>     -    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
>>>     -    options:rxq_pcap=hv2/ext2-rx.pcap \
>>>     -    ofport-request=2
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -as hv3
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>     -ovs-vsctl -- add-port br-phys hv3-ext3 -- \
>>>     -    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
>>>     -    options:rxq_pcap=hv3/ext3-rx.pcap \
>>>     -    ofport-request=2
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>>     10.0.0.6 in hv1 and
>>>     -# hv2 as ha-chassis-group is not set and no localnet port added
>>>     to ls1.
>>>     -AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
>>>     -wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -
>>>     -hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print 
>>> $3}')
>>>     -hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print 
>>> $3}')
>>>     -hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print 
>>> $3}')
>>>     -
>>>     -# The port_binding row for ls1-lp_ext1 should have empty chassis
>>>     -chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -
>>>     -AT_CHECK([test x$chassis == x], [0], [])
>>>     -
>>>     -# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
>>>     -ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
>>>     -ha-chassis-group=$hagrp1_uuid
>>>     -
>>>     -# Get the hagrp1 uuid in SB DB.
>>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>>     ha_chassis_group \
>>>     -name="hagrp1"`
>>>     -
>>>     -# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
>>>     -OVS_WAIT_UNTIL(
>>>     -    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group 
>>> find \
>>>     -port_binding logical_port=ls1-lp_ext1`
>>>     -     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
>>>     -
>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>>     10.0.0.6 in hv1 and hv2
>>>     -# as no localnet port added to ls1 yet.
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -
>>>     -# Add the localnet port to the logical switch ls1
>>>     -ovn-nbctl lsp-add ls1 ln-public
>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>     -ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
>>>     -
>>>     -ln_public_key=$(ovn-sbctl list port_binding ln-public | grep
>>>     tunnel_key | \
>>>     -awk '{print $3}')
>>>     -
>>>     -# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of 
>>> the
>>>     -# ha chassis group.
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = "$hv1_uuid"])
>>>     -
>>>     -# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port 
>>> in hv1
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | grep
>>>     reg14=0x$ln_public_key | \
>>>     -wc -l], [0], [3
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -
>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 -
>>>     10.0.0.7 in hv1 and
>>>     -# hv2 as requested-chassis option is not set.
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], 
>>> [0], [0
>>>     -])
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl show
>>>     -
>>>     -# This shell function sends a DHCP request packet
>>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
>>>     -test_dhcp() {
>>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
>>>     -    shift; shift; shift; shift; shift;
>>>     -    if test $use_ip != 0; then
>>>     -        src_ip=$1
>>>     -        dst_ip=$2
>>>     -        shift; shift;
>>>     -    else
>>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>>     -    fi
>>>     -    local
>>> request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip} 
>>>
>>>     -    # udp header and dhcp header
>>>     -    request=${request}0044004300fc0000
>>>     -
>>> request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac} 
>>>
>>>     -    # client hardware padding
>>>     -    request=${request}00000000000000000000
>>>     -    # server hostname
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # boot file name
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # dhcp magic cookie
>>>     -    request=${request}63825363
>>>     -    # dhcp message type
>>>     -    request=${request}3501${dhcp_type}ff
>>>     -
>>>     -    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
>>>     -    # total IP length will be the IP length of the request packet
>>>     -    # (which is 272 in our case) + 8 (padding bytes) +
>>>     (expected_dhcp_opts / 2)
>>>     -    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>>     -    udp_len=`expr $ip_len - 20`
>>>     -    ip_len=$(printf "%x" $ip_len)
>>>     -    udp_len=$(printf "%x" $udp_len)
>>>     -    # $ip_len var will be in 3 digits i.e 134. So adding a '0'
>>>     before $ip_len
>>>     -    local
>>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>>
>>>     -    # udp header and dhcp header.
>>>     -    # $udp_len var will be in 3 digits. So adding a '0' before
>>>     $udp_len
>>>     -
>>> reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
>>>     -    # your ip address
>>>     -    reply=${reply}${offer_ip}
>>>     -    # next server ip address, relay agent ip address, client mac
>>>     address
>>>     -    reply=${reply}0000000000000000${src_mac}
>>>     -    # client hardware padding
>>>     -    reply=${reply}00000000000000000000
>>>     -    # server hostname
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # boot file name
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -
>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>
>>>     -    # dhcp magic cookie
>>>     -    reply=${reply}63825363
>>>     -    # dhcp message type
>>>     -    local dhcp_reply_type=02
>>>     -    if test $dhcp_type = 03; then
>>>     -        dhcp_reply_type=05
>>>     -    fi
>>>     -
>>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>>
>>>     -    echo $reply >> ext1_v4.expected
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>>     hv${inport}-ext${inport} $request
>>>     -}
>>>     -
>>>     -
>>>     -trim_zeros() {
>>>     -    sed 's/\(00\)\{1,\}$//'
>>>     -}
>>>     -
>>>     -# This shell function sends a DHCPv6 request packet
>>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>>     OUTPORT...
>>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>>     DHCPv6
>>>     -# packet should be received twice (one from ovn-controller and
>>>     the other
>>>     -# from the "ovs-ofctl monitor br-int resume"
>>>     -test_dhcpv6() {
>>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>>     -    local req_pkt_in_expected=$6
>>>     -    local
>>> request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
>>>     -    # dst ip ff02::1:2
>>>     -    request=${request}ff020000000000000000000000010002
>>>     -    # udp header and dhcpv6 header
>>>     -    request=${request}02220223002affff${msg_code}010203
>>>     -    # Client identifier
>>>     -    request=${request}0001000a00030001${src_mac}
>>>     -    # IA-NA (Identity Association for Non Temporary Address)
>>>     -    request=${request}0003000c0102030400000e1000001518
>>>     -    shift; shift; shift; shift; shift;
>>>     -
>>>     -    local server_mac=000000100001
>>>     -    local server_lla=fe80000000000000020000fffe100001
>>>     -    local reply_code=07
>>>     -    if test $msg_code = 01; then
>>>     -        reply_code=02
>>>     -    fi
>>>     -    local msg_len=54
>>>     -    if test $offer_ip = 1; then
>>>     -        msg_len=28
>>>     -    fi
>>>     -    local 
>>> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
>>>     -    reply=${reply}${server_lla}${src_lla}
>>>     -
>>>     -    # udp header and dhcpv6 header
>>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>>     -    # Client identifier
>>>     -    reply=${reply}0001000a00030001${src_mac}
>>>     -    # IA-NA
>>>     -    if test $offer_ip != 1; then
>>>     - reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
>>>     -        reply=${reply}ffffffffffffffff
>>>     -    fi
>>>     -    # Server identifier
>>>     -    reply=${reply}0002000a00030001${server_mac}
>>>     -
>>>     -    echo $reply | trim_zeros >> ext${inport}_v6.expected
>>>     -    # The inport also receives the request packet since it is
>>>     connected
>>>     -    # to the br-phys.
>>>     -    #echo $request >> ext${inport}_v6.expected
>>>     -
>>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>>     hv${inport}-ext${inport} $request
>>>     -}
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
>>>     -as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
>>>     -
>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
>>>     -as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
>>>     -
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -# Send DHCPDISCOVER.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -server_mac=ff1000000001
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>     -$expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 1 in hv1.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 0 in hv2.
>>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>     to receive
>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>     easier to test.
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -rm -f ext1_v4.expected
>>>     -rm -f ext1_v4.packets
>>>     -
>>>     -# Send DHCPv6 request
>>>     -src_mac=f00000000003
>>>     -src_lla=fe80000000000000f20000fffe000003
>>>     -offer_ip=ae700000000000000000000000000006
>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 0 in hv2.
>>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap | \
>>>     -sort > ext1_v6.packets
>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>     -# Skipping the UDP checksum
>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>     -
>>>     -rm -f ext1_v6.expected
>>>     -rm -f ext1_v6.packets
>>>     -
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -# Delete the ha-chassis hv1.
>>>     -ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = ""])
>>>     -
>>>     -# Add hv2 to the ha chassis group
>>>     -ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
>>>     -
>>>     -ovn-sbctl list ha_chassis_group
>>>     -ovn-sbctl list ha_chassis
>>>     -
>>>     -ovn-sbctl find port_binding logical_port=ls1-lp_ext1
>>>     -
>>>     -# The ls1-lp_ext1 should be bound to hv2
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = "$hv2_uuid"])
>>>     -
>>>     -# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port
>>>     in hv2
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | grep
>>>     reg14=0x$ln_public_key | \
>>>     -wc -l], [0], [3
>>>     -])
>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>>     -])
>>>     -
>>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>     -])
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>     -grep controller | grep tp_src=546 | grep \
>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should
>>>     come from
>>>     -# hv2 ovn-controller.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -server_mac=ff1000000001
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>     -$expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 1 in hv2.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>     to receive
>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>     easier to test.
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -rm -f ext1_v4.expected
>>>     -
>>>     -# Send DHCPv6 request again
>>>     -src_mac=f00000000003
>>>     -src_lla=fe80000000000000f20000fffe000003
>>>     -offer_ip=ae700000000000000000000000000006
>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap | \
>>>     -sort > ext1_v6.packets
>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>     -# Skipping the UDP checksum
>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>     -
>>>     -rm -f ext1_v6.expected
>>>     -rm -f ext1_v6.packets
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>     -reset_pcap_file br-phys hv1/br-phys
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -reset_pcap_file br-phys hv2/br-phys
>>>     -
>>>     -# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
>>>     -# response should come from the router pipeline of hv2.
>>>     -ext1_mac=f00000000003
>>>     -router_mac=a01000000001
>>>     -ext1_ip=`ip_to_hex 10 0 0 6`
>>>     -router_ip=`ip_to_hex 10 0 0 1`
>>> -arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip} 
>>>
>>>     -
>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
>>> -expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip} 
>>>
>>>     -echo $expected_response > expout
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap > ext1_arp_resp
>>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>>     -
>>>     -# Verify that the response came from hv2
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv2/br-phys_n1-tx.pcap > ext1_arp_resp
>>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>>     -
>>>     -# Now add 3 ha chassis to the ha chassis group
>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
>>>     -
>>>     -# hv1 should be master and claim ls1-lp_ext1
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = "$hv1_uuid"])
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>     -reset_pcap_file br-phys hv1/br-phys
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -reset_pcap_file br-phys hv2/br-phys
>>>     -
>>>     -as hv3
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>     -reset_pcap_file br-phys hv3/br-phys
>>>     -
>>>     -# Send DHCPDISCOVER.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -server_mac=ff1000000001
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>     -$expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 3 in hv1.
>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>     to receive
>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>     easier to test.
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -rm -f ext1_v4.expected
>>>     -rm -f ext1_v4.packets
>>>     -
>>>     -# Send DHCPv6 request
>>>     -src_mac=f00000000003
>>>     -src_lla=fe80000000000000f20000fffe000003
>>>     -offer_ip=ae700000000000000000000000000006
>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>     -
>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap | \
>>>     -sort > ext1_v6.packets
>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>     -# Skipping the UDP checksum
>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>     -
>>>     -rm -f ext1_v6.expected
>>>     -rm -f ext1_v6.packets
>>>     -as hv1 reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -# Now increase the priority of hv3 so it becomes master.
>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
>>>     -
>>>     -# hv3 should be master and claim ls1-lp_ext1
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = "$hv3_uuid"])
>>>     -
>>>     -as hv1
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>     -reset_pcap_file br-phys hv1/br-phys
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>     -reset_pcap_file br-phys hv2/br-phys
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl show
>>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>     -reset_pcap_file br-phys hv3/br-phys
>>>     -
>>>     -# Send DHCPDISCOVER.
>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>     -server_mac=ff1000000001
>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>     -$expected_dhcp_opts
>>>     -
>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 1 in hv3.
>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>     -# Skipping the IPv4 checksum.
>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>     -
>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>     to receive
>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>     easier to test.
>>>     -as hv1
>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>     -
>>>     -rm -f ext1_v4.expected
>>>     -rm -f ext1_v4.packets
>>>     -
>>>     -# Send DHCPv6 request
>>>     -src_mac=f00000000003
>>>     -src_lla=fe80000000000000f20000fffe000003
>>>     -offer_ip=ae700000000000000000000000000006
>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>     -
>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -# NXT_RESUMEs should be 2 in hv3.
>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c
>>>     NXT_RESUME`])
>>>     -
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/ext1-tx.pcap | \
>>>     -sort > ext1_v6.packets
>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>     -# Skipping the UDP checksum
>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>     -
>>>     -# disconnect hv3 from the network, hv1 should take over
>>>     -as hv3
>>>     -port=${sandbox}_br-phys
>>>     -as main ovs-vsctl del-port n1 $port
>>>     -
>>>     -# hv1 should be master and claim ls1-lp_ext1
>>>     -OVS_WAIT_UNTIL(
>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>> port_binding \
>>>     -logical_port=ls1-lp_ext1`
>>>     -    test "$chassis" = "$hv1_uuid"])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- Address Set Incremental Processing])
>>>     -AT_KEYWORDS([ovn_as_inc])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.10
>>>     -
>>>     -ovn-nbctl ls-add ls1
>>>     -for i in 1 2; do
>>>     -    ovn-nbctl lsp-add ls1 lp$i \
>>>     -        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 
>>> 192.168.1.$i"
>>>     -    as hv1 ovs-vsctl \
>>>     -        -- add-port br-int vif$i \
>>>     -        -- set Interface vif$i \
>>>     -            external-ids:iface-id=lp$i
>>>     -done
>>>     -
>>>     -for i in 1 2 3; do
>>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>>     -    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
>>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>>     -            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}'
>>>     allow-related
>>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>>     [0], [ignore])
>>>     -
>>>     -    # Update address set as1
>>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 
>>> 10.1.2.11"
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"],
>>>     [0], [ignore])
>>>     -
>>>     -    # Update address set as2
>>>     -    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 
>>> 10.1.2.13"
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>     [0], [ignore])
>>>     -
>>>     -    # Add another ACL referencing as1
>>>     -    n_flows_before=`ovs-ofctl dump-flows br-int | grep
>>>     "10.1.2.10" | wc -l`
>>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>>     -            'outport=="lp2" && ip4 && ip4.src == $as1' 
>>> allow-related
>>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>>     | wc -l`
>>>     -    AT_CHECK([test $(expr $n_flows_before \* 2) =
>>>     $n_flows_after], [0], [ignore])
>>>     -
>>>     -    # Remove an ACL
>>>     -    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
>>>     -            'outport=="lp2" && ip4 && ip4.src == $as1'
>>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>>     | wc -l`
>>>     -    AT_CHECK([test $n_flows_before = $n_flows_after], [0], 
>>> [ignore])
>>>     -
>>>     -    # Remove as1 while it is still used by an ACL, the lflows
>>>     should be reparsed and
>>>     -    # parsing should fail.
>>>     -    echo "before del as1"
>>>     -    ovn-nbctl list addr | grep as1
>>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid
>>>     -    echo "after del as1"
>>>     -    ovn-nbctl list addr | grep as1
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>>     [1], [ignore])
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>     [1], [ignore])
>>>     -
>>>     -    # Recreate as1
>>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>     [0], [ignore])
>>>     -
>>>     -    # Remove ACLs and address sets
>>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr
>>>     $as2_uuid
>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>     [1], [ignore])
>>>     -
>>>     -    ovn-nbctl --wait=hv acl-del ls1
>>>     -done
>>>     -
>>>     -# Gracefully terminate daemons
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ovn-controller restart])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>     -# sw1 has a single port bound on hv1
>>>     -# sw2 has a single port bound on hv2
>>>     -
>>>     -ovn-nbctl lr-add ro
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl ls-add sw2
>>>     -
>>>     -sw1_ro_mac=00:00:10:00:00:01
>>>     -sw1_ro_ip=10.0.0.1
>>>     -sw2_ro_mac=00:00:20:00:00:01
>>>     -sw2_ro_ip=20.0.0.1
>>>     -sw1_p1_mac=00:00:10:00:00:02
>>>     -sw1_p1_ip=10.0.0.2
>>>     -sw2_p1_mac=00:00:20:00:00:02
>>>     -sw2_p1_ip=20.0.0.2
>>>     -
>>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>>     type=router \
>>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>>     type=router \
>>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>>     -
>>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>>     -
>>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -sleep 1
>>>     -
>>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>>     eth.dst==$sw1_ro_mac &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>>     ip4.dst==$sw2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -
>>>     -# Start by Sending the packet and make sure it makes it there as
>>>     expected
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -# Expected packet has TTL decreased by 1
>>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>>     ip4.dst==$sw2_p1_ip &&
>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -# Stop ovn-controller on hv2 with --restart flag
>>>     -as hv2 ovs-appctl -t ovn-controller exit --restart
>>>     -
>>>     -# Now send the packet again. This time, it should still arrive
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -cat expected expected > expected2
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
>>>     -
>>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>>     -as hv2 start_daemon ovn-controller
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
>>>     -ovn_start
>>>     -
>>>     -# Set up a switch with some switch ports of varying address types
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl set logical_switch sw1
>>>     other_config:subnet=192.168.0.0/24 <http://192.168.0.0/24>
>>>     -
>>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>>     -ovn-nbctl lsp-add sw1 sw1-p2
>>>     -ovn-nbctl lsp-add sw1 sw1-p3
>>>     -ovn-nbctl lsp-add sw1 sw1-p4
>>>     -
>>>     -ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1
>>>     aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
>>>     -ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
>>>     -ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
>>>     -ovn-nbctl lsp-set-addresses sw1-p4 "router"
>>>     -ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
>>>     -
>>>     -ovn-nbctl list logical_switch_port
>>>     -
>>>     -# Now try to add duplicate addresses on a new port. These should
>>>     all fail
>>>     -ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     10.0.0.1"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     10.0.0.2"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     aef0::1"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     aef0::2"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     192.168.0.2"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 
>>> 192.168.0.2
>>>     -])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>     192.168.0.3"], [1], [],
>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 
>>> 192.168.0.3
>>>     -])
>>>     -
>>>     -# Now try re-setting sw1-p1. This should succeed
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01
>>>     10.0.0.1 aef0::1"])
>>>     -
>>>     -# Now create a new switch and try setting IP addresses the same
>>>     as the
>>>     -# first switch. This should succeed.
>>>     -ovn-nbctl ls-add sw2
>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>     -
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>     10.0.0.1"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>     192.168.0.2"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>     192.168.0.3"])
>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>     aef0::1"])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- router - check packet length - icmp defrag])
>>>     -AT_KEYWORDS([check packet length])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl lsp-add sw0 sw0-port1
>>>     -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
>>>     -
>>>     -ovn-nbctl lr-add lr0
>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
>>>     <http://10.0.0.1/24>
>>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>>     -
>>>     -ovn-nbctl ls-add public
>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 
>>> 172.168.0.100/24
>>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> lsp-add public
>>>     public-lr0
>>>     -ovn-nbctl lsp-set-type public-lr0 router
>>>     -ovn-nbctl lsp-set-addresses public-lr0 router
>>>     -ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
>>>     -
>>>     -# localnet port
>>>     -ovn-nbctl lsp-add public ln-public
>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>>     -
>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
>>>     -ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
>>>     <http://10.0.0.0/24>
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -reset_pcap_file() {
>>>     -     local iface=$1
>>>     -     local pcap_file=$2
>>>     -     ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=dummy-tx.pcap \
>>>     - options:rxq_pcap=dummy-rx.pcap
>>>     -     rm -f ${pcap_file}*.pcap
>>>     -     ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     - options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -     printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -test_ip_packet_larger() {
>>>     -    local icmp_pmtu_reply_expected=$1
>>>     -
>>>     -    # Send ip packet from sw0-port1 to outside
>>>     -    src_mac="505400000001" # sw-port1 mac
>>>     -    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
>>>     -    src_ip=`ip_to_hex 10 0 0 3`
>>>     -    dst_ip=`ip_to_hex 172 168 0 3`
>>>     -    # Set the packet length to 100.
>>>     -    pkt_len=0064
>>>     - packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
>>>     -    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
>>>     - 
>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>     - 
>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>     - 
>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>     - 
>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>     -    packet=${packet}${orig_packet_l3}
>>>     -
>>>     -
>>> gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064 
>>>
>>>     -
>>>     -    # If icmp_pmtu_reply_expected is 0, it means the packet is
>>>     lesser than
>>>     -    # the gateway mtu and should be delivered to the provider
>>>     bridge via the
>>>     -    # localnet port.
>>>     -    # If icmp_pmtu_reply_expected is 1, it means the packet is
>>>     larger than
>>>     -    # the gateway mtu and ovn-controller should drop the packet
>>>     and instead
>>>     -    # generate ICMPv4  Destination Unreachable message with pmtu
>>>     set to 42.
>>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>>     -        # Packet to expect at br-phys.
>>>     -        src_mac="000020201213"
>>>     -        dst_mac="00000012af11"
>>>     -        src_ip=`ip_to_hex 10 0 0 3`
>>>     -        dst_ip=`ip_to_hex 172 168 0 3`
>>>     - expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
>>>     - expected=${expected}${src_ip}${dst_ip}0304000000000000
>>>     - expected=${expected}000000000000000000000000000000000000
>>>     - expected=${expected}000000000000000000000000000000000000
>>>     - expected=${expected}000000000000000000000000000000000000
>>>     - expected=${expected}000000000000000000000000000000000000
>>>     -        echo $expected > br_phys_n1.expected
>>>     -        echo $gw_ip_garp >> br_phys_n1.expected
>>>     -    else
>>>     -        # MTU would be 100 - 18 = 82 (hex 0052)
>>>     -        mtu=0052
>>>     -        src_ip=`ip_to_hex 10 0 0 1`
>>>     -        dst_ip=`ip_to_hex 10 0 0 3`
>>>     -        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip
>>>     + payload))
>>>     -        reply_pkt_len=0080
>>>     -        ip_csum=bd91
>>>     -
>>> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
>>>     - 
>>> icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
>>>     - icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
>>>     -        icmp_reply=${icmp_reply}${orig_packet_l3}
>>>     -        echo $icmp_reply > hv1-vif1.expected
>>>     -    fi
>>>     -
>>>     -    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>     -    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>     -
>>>     -    # Send packet from sw0-port1 to outside
>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>     -
>>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>>     -        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap],
>>>     [br_phys_n1.expected])
>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" hv1/vif1-tx.pcap > pkts
>>>     -        # hv1/vif1-tx.pcap can receive the GARP packet generated
>>>     by ovn-controller
>>>     -        # for the gateway router port. So ignore this packet.
>>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>>     -        AT_CHECK([cat packets], [0], [])
>>>     -    else
>>>     -        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" hv1/br-phys_n1-tx.pcap  > \
>>>     -        pkts
>>>     -        # hv1/br-phys_n1-tx.pcap can receive the GARP packet
>>>     generated by ovn-controller
>>>     -        # for the gateway router port. So ignore this packet.
>>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>>     -        AT_CHECK([cat packets], [0], [])
>>>     -    fi
>>>     -}
>>>     -
>>>     -ovn-nbctl show
>>>     -ovn-sbctl show
>>>     -
>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
>>>     -| grep "check_pkt_larger" | wc -l], [0], [[0
>>>     -]])
>>>     -dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep
>>>     _uuid | \
>>>     -awk '{print $3}')
>>>     -ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
>>>     -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
>>>     -
>>>     -# Set the gateway mtu to 100. If the packet length is > 100,
>>>     ovn-controller
>>>     -# should send icmp host not reachable with pmtu set to 100.
>>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>>     options:gateway_mtu=100
>>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>>     -OVS_WAIT_UNTIL([
>>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>>     "check_pkt_larger(100)" | \
>>>     -    wc -l` -eq 1
>>>     -])
>>>     -
>>>     -icmp_reply_expected=1
>>>     -test_ip_packet_larger $icmp_reply_expected
>>>     -
>>>     -# Set the gateway mtu to 500.
>>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>>     options:gateway_mtu=500
>>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>>     -OVS_WAIT_UNTIL([
>>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>>     "check_pkt_larger(500)" | \
>>>     -    wc -l` -eq 1
>>>     -])
>>>     -
>>>     -# Now the packet should be sent via the localnet port to br-phys.
>>>     -icmp_reply_expected=0
>>>     -test_ip_packet_larger $icmp_reply_expected
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IP packet buffering])
>>>     -AT_KEYWORDS([ip-buffering])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# One LR lr0 that has switches sw0 (192.168.1.0/24
>>>     <http://192.168.1.0/24>) and
>>>     -# sw1 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>     -#
>>>     -# Physical network:
>>>     -# Tw0 hypervisors hv[12].
>>>     -# hv1 hosts vif sw0-p0.
>>>     -# hv1 hosts vif sw1-p0.
>>>     -
>>>     -send_icmp_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>     ipv4_dst=$6 ip_chksum=$7 data=$8
>>>     -    shift 8
>>>     -
>>>     -    local ip_ttl=ff
>>>     -    local ip_len=001c
>>>     -    local
>>> packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data} 
>>>
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>>> $packet
>>>     -}
>>>     -
>>>     -send_icmp6_packet() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>>     -    shift 8
>>>     -
>>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>>     -    local 
>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>>> $packet
>>>     -}
>>>     -
>>>     -get_arp_req() {
>>>     -    local eth_src=$1 spa=$2 tpa=$3
>>>     -    local
>>> request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa} 
>>>
>>>     -    echo $request
>>>     -}
>>>     -
>>>     -send_arp_reply() {
>>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
>>>     -    local
>>> request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa} 
>>>
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>     $request
>>>     -}
>>>     -
>>>     -send_na() {
>>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 
>>> dst_ip=$6
>>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>>     -    local
>>> request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src} 
>>>
>>>     -
>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>     $request
>>>     -}
>>>     -
>>>     -get_nd() {
>>>     -    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
>>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>>     -
>>> request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src} 
>>>
>>>     -
>>>     -    echo $request
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl ls-add sw1
>>>     -
>>>     -ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24> 2001:0:0:0:0:0:0:1/64
>>>     -ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
>>>     -    type=router options:router-port=sw0 \
>>>     -    -- lsp-set-addresses rp-sw0 router
>>>     -
>>>     -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64
>>>     -ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
>>>     -    type=router options:router-port=sw1 \
>>>     -    -- lsp-set-addresses rp-sw1 router
>>>     -
>>>     -ovn-nbctl lsp-add sw0 sw0-p0 \
>>>     -    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2
>>>     2001::2"
>>>     -
>>>     -ovn-nbctl lsp-add sw1 sw1-p0 \
>>>     -    -- lsp-set-addresses sw1-p0 unknown
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -ip_to_hex() {
>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -src_mac=f00000010203
>>>     -src_ip=$(ip_to_hex 192 168 1 2)
>>>     -src_ip6=20010000000000000000000000000002
>>>     -
>>>     -router_mac0=000001010203
>>>     -router_mac1=000002010203
>>>     -router_ip=$(ip_to_hex 172 16 1 1)
>>>     -router_ip6=20020000000000000000000000000001
>>>     -
>>>     -dst_mac=001122334455
>>>     -dst_ip=$(ip_to_hex 172 16 1 10)
>>>     -dst_ip6=20020000000000000000000000000010
>>>     -
>>>     -data=0800bee4391a0001
>>>     -
>>>     -send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 
>>> $data
>>>     -send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
>>>     -echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
>>>     -echo
>>> "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}" 
>>>
>>>     >> expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -nd_ip=ff0200000000000000000001ff000010
>>>     -ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
>>>     -
>>>     -send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
>>>     -echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
>>>     -echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >>
>>>     expected
>>>     -send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- neighbor update on same HV])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# A public switch (pub) with a localnet port connected to two LRs
>>>     (lr0 and lr1)
>>>     -# each with a distributed gateway port.
>>>     -# Two VMs: lp0 on sw0 connected to lr0
>>>     -#          lp1 on sw1 connected to lr1
>>>     -#
>>>     -# This test adds a floating IP to each VM so when they are bound
>>>     to the same
>>>     -# hypervisor, it checks that the GARP sent by ovn-controller
>>>     causes the
>>>     -# MAC_Binding entries to be updated properly on each logical 
>>> router.
>>>     -# It will also capture packets on the physical interface to make
>>>     sure that the
>>>     -# GARPs have been sent out to the external network as well.
>>>     -
>>>     -# Create logical switches
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl ls-add pub
>>>     -
>>>     -# Created localnet port on public switch
>>>     -ovn-nbctl lsp-add pub ln-pub
>>>     -ovn-nbctl lsp-set-type ln-pub localnet
>>>     -ovn-nbctl lsp-set-addresses ln-pub unknown
>>>     -ovn-nbctl lsp-set-options ln-pub network_name=phys
>>>     -
>>>     -# Create logical routers and connect them to public switch
>>>     -ovn-nbctl create Logical_Router name=lr0
>>>     -ovn-nbctl create Logical_Router name=lr1
>>>     -
>>>     -ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
>>>     <http://172.24.4.220/24>
>>>     -ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
>>>     -    type=router options:router-port=lr0-pub
>>>     options:nat-addresses="router" addresses="router"
>>>     -ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
>>>     <http://172.24.4.221/24>
>>>     -ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
>>>     -    type=router options:router-port=lr1-pub
>>>     options:nat-addresses="router" addresses="router"
>>>     -
>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
>>>     -ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
>>>     -
>>>     -# Connect sw0 and sw1 to lr0 and lr1
>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>>>     <http://10.0.0.254/24>
>>>     -ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0
>>>     type=router \
>>>     -    options:router-port=lr0-sw0 addresses="router"
>>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
>>>     <http://20.0.0.254/24>
>>>     -ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1
>>>     type=router \
>>>     -    options:router-port=lr1-sw1 addresses="router"
>>>     -
>>>     -
>>>     -# Add SNAT rules
>>>     -ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
>>>     <http://10.0.0.0/24>
>>>     -ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
>>>     <http://20.0.0.0/24>
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 172.24.4.1
>>>     -ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -
>>>     -ovs-vsctl add-port br-int vif0 -- set Interface vif0
>>>     external-ids:iface-id=lp0
>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>     external-ids:iface-id=lp1
>>>     -
>>>     -ovn-nbctl lsp-add sw0 lp0
>>>     -ovn-nbctl lsp-add sw1 lp1
>>>     -ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
>>>     -ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
>>>     -
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>     -
>>>     -# Create two floating IPs, one for each VIF
>>>     -ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
>>>     -ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
>>>     -
>>>     -# Check that the MAC_Binding entries have been properly created
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>     logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>     logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
>>>     -
>>>     -# Check that the GARPs went also to the external physical network
>>>     -# Wait until at least 4 packets have arrived and copy them to a
>>>     separate file as
>>>     -# more GARPs are expected in the capture in order to avoid race
>>>     conditions.
>>>     -OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>     <http://ovs-pcap.in>" hv1/br-phys-tx.pcap | wc -l` -gt 4])
>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>     hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
>>>     -
>>>     -# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
>>>     -echo
>>> "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464" 
>>>
>>>     > expout
>>>     -# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
>>>     -echo
>>> "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc" 
>>>
>>>     >> expout
>>>     -# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
>>>     -echo
>>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8" 
>>>
>>>     >> expout
>>>     -# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
>>>     -echo
>>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd" 
>>>
>>>     >> expout
>>>     -AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
>>>     -#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
>>>     -
>>>     -OVN_CLEANUP([hv1])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ipam to non-ipam])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>     -ovn-nbctl ls-add sw0
>>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>>     subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>>     -
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>>     dynamic_addresses], [0],
>>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>>     -])
>>>     -
>>>     -ovn-nbctl --wait=sb lsp-set-addresses p0 router
>>>     -
>>>     -ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
>>>     -
>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>>     dynamic_addresses], [0], [[[]]
>>>     -])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- ipam router ports])
>>>     -ovn_start
>>>     -
>>>     -ovn-nbctl ls-add sw
>>>     -ovn-nbctl set logical_switch sw
>>>     other-config:subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>>     -
>>>     -for i in 2 3 4; do
>>>     -    ovn-nbctl lr-add ro$i
>>>     -    ovn-nbctl lsp-add sw swp$i
>>>     -    ovn-nbctl --wait=sb lsp-set-addresses swp$i
>>>     "02:00:00:00:00:0$i dynamic"
>>>     -    cidr=$(ovn-nbctl get logical_switch_port swp$i
>>>     dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
>>>     -    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 --
>>>     set logical_switch_port swp$i type=router
>>>     options:router-port=rop$i addresses=router;
>>>     -    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i
>>>     networks], [0], [[["192.168.1.$i/24"]]
>>>     -])
>>>     -done
>>>     -
>>>     -ovn-nbctl list logical_switch_port
>>>     -ovn-nbctl list logical_router_port
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- test transport zones])
>>>     -ovn_start
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2 3 4 5; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.$i.1
>>>     -done
>>>     -
>>>     -dnl Wait for the changes to be propagated
>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -dnl Assert that each Chassis has a tunnel formed to every other
>>>     Chassis
>>>     -as hv1
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv2
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv3
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv4
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv5
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -]])
>>>     -
>>>     -dnl Let's now add some Chassis to different transport zones
>>>     -dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
>>>     -dnl   should have tunnels formed between the other two Chassis
>>>     (hv2 and hv3)
>>>     -dnl
>>>     -dnl * hv2: Will be part of one transport zone: tz1. It should
>>>     have a tunnel
>>>     -dnl   to hv1 but not to hv3
>>>     -dnl
>>>     -dnl * hv3: Will be part of one transport zone: tz2. It should
>>>     have a tunnel
>>>     -dnl   to hv1 but not to hv2
>>>     -dnl
>>>     -dnl * hv4 and hv5: Will not have any TZ set so they will keep the
>>>     tunnels
>>>     -dnl   between themselves and remove the tunnels to other Chassis
>>>     which now
>>>     -dnl   belongs to some TZs
>>>     -dnl
>>>     -as hv1
>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
>>>     -
>>>     -as hv2
>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
>>>     -
>>>     -as hv3
>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
>>>     -
>>>     -dnl Wait for the changes to be propagated
>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -as hv1
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -]])
>>>     -
>>>     -as hv2
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -]])
>>>     -
>>>     -as hv3
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -]])
>>>     -
>>>     -as hv4
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv5
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv4-0
>>>     -]])
>>>     -
>>>     -dnl Removing the transport zones should make all Chassis to create
>>>     -dnl tunnels between every other Chassis again
>>>     -for i in 1 2 3; do
>>>     -    as hv$i
>>>     -    ovs-vsctl remove open . external-ids ovn-transport-zones
>>>     -done
>>>     -
>>>     -dnl Wait for the changes to be propagated
>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>     -
>>>     -as hv1
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv2
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv3
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv4-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv4
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv5-0
>>>     -]])
>>>     -
>>>     -as hv5
>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>     type="geneve" | awk NF | sort], [0],
>>>     -[[ovn-hv1-0
>>>     -ovn-hv2-0
>>>     -ovn-hv3-0
>>>     -ovn-hv4-0
>>>     -]])
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis
>>>     mac])
>>>     -ovn_start
>>>     -
>>>     -
>>>     -# In this test cases we create 2 switches, all connected to same
>>>     -# physical network (through br-phys on each HV). Each switch has
>>>     -# 1 VIF. Each HV has 1 VIF port. The first digit
>>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>>     -# lp23 means VIF 3 on hv2.
>>>     -#
>>>     -# Each switch's VLAN tag and their logical switch ports are:
>>>     -#   - ls1:
>>>     -#       - tagged with VLAN 101
>>>     -#       - ports: lp11
>>>     -#   - ls2:
>>>     -#       - tagged with VLAN 201
>>>     -#       - ports: lp22
>>>     -#
>>>     -# Note: a localnet port is created for each switch to connect to
>>>     -# physical network.
>>>     -
>>>     -for i in 1 2; do
>>>     -    ls_name=ls$i
>>>     -    ovn-nbctl ls-add $ls_name
>>>     -    ln_port_name=ln$i
>>>     -    if test $i -eq 1; then
>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>>     -    elif test $i -eq 2; then
>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
>>>     -    fi
>>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>>     -done
>>>     -
>>>     -# lsp_to_ls LSP
>>>     -#
>>>     -# Prints the name of the logical switch that contains LSP.
>>>     -lsp_to_ls () {
>>>     -    case $1 in dnl (
>>>     -        lp?[[11]]) echo ls1 ;; dnl (
>>>     -        lp?[[12]]) echo ls2 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -vif_to_ls () {
>>>     -    case $1 in dnl (
>>>     -        vif?[[11]]) echo ls1 ;; dnl (
>>>     -        vif?[[12]]) echo ls2 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -hv_to_num () {
>>>     -    case $1 in dnl (
>>>     -        hv1) echo 1 ;; dnl (
>>>     -        hv2) echo 2 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -vif_to_num () {
>>>     -    case $1 in dnl (
>>>     -        vif22) echo 22 ;; dnl (
>>>     -        vif21) echo 21 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -vif_to_hv () {
>>>     -    case $1 in dnl (
>>>     -        vif[[1]]?) echo hv1 ;; dnl (
>>>     -        vif[[2]]?) echo hv2 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -vif_to_lrp () {
>>>     -    echo router-to-`vif_to_ls $1`
>>>     -}
>>>     -
>>>     -hv_to_chassis_mac () {
>>>     -     case $1 in dnl (
>>>     -        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
>>>     -        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
>>>     -        *) AT_FAIL_IF([:]) ;;
>>>     -    esac
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -       printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -net_add n1
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovs-vsctl set open .
>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>     -    ovs-vsctl set open .
>>> external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    ovs-vsctl add-port br-int vif$i$i -- \
>>>     -        set Interface vif$i$i external-ids:iface-id=lp$i$i \
>>>     - options:tx_pcap=hv$i/vif$i$i-tx.pcap \
>>>     - options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
>>>     -                              ofport-request=$i$i
>>>     -
>>>     -    lsp_name=lp$i$i
>>>     -    ls_name=$(lsp_to_ls $lsp_name)
>>>     -
>>>     -    ovn-nbctl lsp-add $ls_name $lsp_name
>>>     -    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i
>>>     192.168.$i.$i"
>>>     -    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
>>>     -
>>>     -    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
>>>     -
>>>     -done
>>>     -
>>>     -ovn-nbctl lr-add router
>>>     -ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03
>>>     192.168.1.3/24
>>>     -ovn-nbctl <http://192.168.1.3/24-ovn-nbctl> lrp-add router
>>>     router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 
>>> <http://192.168.2.3/24>
>>>     -
>>>     -ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port
>>>     ls1-to-router type=router options:router-port=router-to-ls1 --
>>>     lsp-set-addresses ls1-to-router router
>>>     -ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port
>>>     ls2-to-router type=router options:router-port=router-to-ls2 --
>>>     lsp-set-addresses ls2-to-router router
>>>     -
>>>     -ovn-nbctl --wait=sb sync
>>>     -#ovn-sbctl dump-flows
>>>     -
>>>     -ovn-nbctl show
>>>     -ovn-sbctl show
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -test_ip() {
>>>     -    # This packet has bad checksums but logical L3 routing
>>>     doesn't check.
>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>     -    local
>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -    shift; shift; shift; shift; shift
>>>     -    hv=`vif_to_hv $inport`
>>>     -    hv_num=`hv_to_num $hv`
>>>     -    chassis_mac=`hv_to_chassis_mac $hv`
>>>     -    as $hv ovs-appctl netdev-dummy/receive $inport $packet
>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>> $packet
>>>     -    in_ls=`vif_to_ls $inport`
>>>     -    in_lrp=`vif_to_lrp $inport`
>>>     -    for outport; do
>>>     -        out_ls=`vif_to_ls $outport`
>>>     -        if test $in_ls = $out_ls; then
>>>     -            # Ports on the same logical switch receive exactly
>>>     the same packet.
>>>     -            echo $packet
>>>     -        else
>>>     -            # Routing decrements TTL and updates source and 
>>> dest MAC
>>>     -            # (and checksum).
>>>     -            outport_num=`vif_to_num $outport`
>>>     -            out_lrp=`vif_to_lrp $outport`
>>>     -            echo
>>> f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>
>>>     -        fi >> $outport.expected
>>>     -    done
>>>     -}
>>>     -
>>>     -# Dump a bunch of info helpful for debugging if there's a failure.
>>>     -
>>>     -echo "------ OVN dump ------"
>>>     -ovn-nbctl show
>>>     -ovn-sbctl show
>>>     -
>>>     -echo "------ hv1 dump ------"
>>>     -as hv1 ovs-vsctl show
>>>     -as hv1 ovs-vsctl list Open_Vswitch
>>>     -
>>>     -echo "------ hv2 dump ------"
>>>     -as hv2 ovs-vsctl show
>>>     -as hv2 ovs-vsctl list Open_Vswitch
>>>     -
>>>     -echo "Send traffic"
>>>     -sip=`ip_to_hex 192 168 1 1`
>>>     -dip=`ip_to_hex 192 168 2 2`
>>>     -test_ip vif11 f00000000011  000001010203 $sip $dip vif22
>>>     -
>>>     -echo "----------- Post Traffic hv1 dump -----------"
>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -as hv1 ovs-appctl fdb/show br-phys
>>>     -
>>>     -echo "----------- Post Traffic hv2 dump -----------"
>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>     -as hv2 ovs-appctl fdb/show br-phys
>>>     -
>>>     -OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
>>>     -
>>>     -OVN_CLEANUP([hv1],[hv2])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -# Run ovn-nbctl in daemon mode, change to a backup database and
>>>     verify that
>>>     -# an insert operation is not allowed.
>>>     -AT_SETUP([ovn -- can't write to a backup database server 
>>> instance])
>>>     -ovn_start
>>>     -on_exit 'kill $(cat ovn-nbctl.pid)'
>>>     -export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
>>>     -
>>>     -AT_CHECK([ovn-nbctl ls-add sw0])
>>>     -as ovn-nb
>>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>>     grep active | wc -l], [0], [1
>>>     -])
>>>     -ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server
>>>     tcp:192.0.2.2:6641 <http://192.0.2.2:6641>
>>>     -ovs-appctl -t ovsdb-server 
>>> ovsdb-server/connect-active-ovsdb-server
>>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>>     grep -c backup], [0], [1
>>>     -])
>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
>>>     -[ovn-nbctl: transaction error: {"details":"insert operation not
>>>     allowed when database server is in read only mode","error":"not
>>>     allowed"}
>>>     -])
>>>     -
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- controller event])
>>>     -AT_KEYWORDS([ovn_controller_event])
>>>     -ovn_start
>>>     -
>>>     -# Create hypervisors hv[12].
>>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>>     -# Add all of the vifs to a single logical switch sw0.
>>>     -
>>>     -net_add n1
>>>     -ovn-nbctl ls-add sw0
>>>     -for i in 1 2; do
>>>     -    sim_add hv$i
>>>     -    as hv$i
>>>     -    ovs-vsctl add-br br-phys
>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>     -
>>>     -    for j in 1 2; do
>>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>>     192.168.1.$i$j"
>>>     -
>>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>>     -                set interface vif$i$j \
>>>     -                external-ids:iface-id=sw0-p$i$j \
>>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>     -                ofport-request=$i$j
>>>     -    done
>>>     -done
>>>     -
>>>     -ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
>>>     -ovn-nbctl lb-add lb0 192.168.1.100:80 <http://192.168.1.100:80> ""
>>>     -ovn-nbctl ls-lb-add sw0 lb0
>>>     -uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer
>>>     name=lb0)
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>>     -ovn-sbctl lflow-list
>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>     -
>>>     -packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 &&
>>>     eth.dst==00:00:00:00:00:21 &&
>>>     -       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 &&
>>>     ip4.dst==192.168.1.100 &&
>>>     -       tcp && tcp.src==10000 && tcp.dst==80"
>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>     -
>>>     -ovn-sbctl list controller_event
>>>     -uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_type], 
>>> [0], [dnl
>>>     -empty_lb_backends
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip],
>>>     [0], [dnl
>>>     -"192.168.1.100:80 <http://192.168.1.100:80>"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid
>>>     event_info:protocol], [0], [dnl
>>>     -tcp
>>>     -])
>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid
>>>     event_info:load_balancer], [0], [dnl
>>>     -"$uuid_lb"
>>>     -])
>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], [dnl
>>>     -1
>>>     -])
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- IGMP snoop/querier])
>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>     -ovn_start
>>>     -
>>>     -# Logical network:
>>>     -# Two independent logical switches (sw1 and sw2).
>>>     -# sw1:
>>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>     -#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
>>>     -#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
>>>     -# sw2:
>>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>     -#   - 1 port bound on hv1 (sw2-p1)
>>>     -#   - 1 port bound on hv2 (sw2-p2)
>>>     -#   - IGMP Querier from 20.0.0.254
>>>     -
>>>     -reset_pcap_file() {
>>>     -    local iface=$1
>>>     -    local pcap_file=$2
>>>     -    ovs-vsctl -- set Interface $iface 
>>> options:tx_pcap=dummy-tx.pcap \
>>>     -options:rxq_pcap=dummy-rx.pcap
>>>     -    rm -f ${pcap_file}*.pcap
>>>     -    ovs-vsctl -- set Interface $iface
>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>     -}
>>>     -
>>>     -ip_to_hex() {
>>>     -     printf "%02x%02x%02x%02x" "$@"
>>>     -}
>>>     -
>>>     -#
>>>     -# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP 
>>> REC_TYPE
>>>     -#                     IGMP_CSUM OUTFILE
>>>     -#
>>>     -# This shell function causes an IGMPv3 report to be received on
>>>     INPORT of HV.
>>>     -# The packet's content has Ethernet destination 01:00:5E:00:00:22
>>>     and source
>>>     -# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
>>>     -# GROUP is the IP multicast group to be joined/to leave (based on
>>>     REC_TYPE).
>>>     -# REC_TYPE == 04: join GROUP
>>>     -# REC_TYPE == 03: leave GROUP
>>>     -# The packet hexdump is also stored in OUTFILE.
>>>     -#
>>>     -send_igmp_v3_report() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 
>>> group=$6
>>>     -    local rec_type=$7 igmp_chksum=$8 outfile=$9
>>>     -
>>>     -    local eth_dst=01005e000016
>>>     -    local ip_dst=$(ip_to_hex 224 0 0 22)
>>>     -    local ip_ttl=01
>>>     -    local ip_ra_opt=94040000
>>>     -
>>>     -    local igmp_type=2200
>>>     -    local num_rec=00000001
>>>     -    local aux_dlen=00
>>>     -    local num_src=0000
>>>     -
>>>     -    local eth=${eth_dst}${eth_src}0800
>>>     -    local
>>> ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt} 
>>>
>>>     -    local
>>> igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group} 
>>>
>>>     -    local packet=${eth}${ip}${igmp}
>>>     -
>>>     -    echo ${packet} >> ${outfile}
>>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>>     -}
>>>     -
>>>     -#
>>>     -# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
>>>     -#
>>>     -# This shell function builds an IGMPv3 general query from ETH_SRC
>>>     and IP_SRC
>>>     -# and stores the hexdump of the packet in OUTFILE.
>>>     -#
>>>     -store_igmp_v3_query() {
>>>     -    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
>>>     -
>>>     -    local eth_dst=01005e000001
>>>     -    local ip_dst=$(ip_to_hex 224 0 0 1)
>>>     -    local ip_ttl=01
>>>     -    local igmp_type=11
>>>     -    local max_resp=0a
>>>     -    local igmp_chksum=eeeb
>>>     -    local addr=00000000
>>>     -
>>>     -    local eth=${eth_dst}${eth_src}0800
>>>     -    local
>>> ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
>>>     -    local 
>>> igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
>>>     -    local packet=${eth}${ip}${igmp}
>>>     -
>>>     -    echo ${packet} >> ${outfile}
>>>     -}
>>>     -
>>>     -#
>>>     -# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST
>>>     IP_LEN
>>>     -#    IP_PROTO DATA OUTFILE
>>>     -#
>>>     -# This shell function causes an IP multicast packet to be
>>>     received on INPORT
>>>     -# of HV.
>>>     -# The hexdump of the packet is stored in OUTFILE.
>>>     -#
>>>     -send_ip_multicast_pkt() {
>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 
>>> ip_dst=$6
>>>     -    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} outfile=${11}
>>>     -
>>>     -    local ip_ttl=20
>>>     -
>>>     -    local eth=${eth_dst}${eth_src}0800
>>>     -    local
>>> ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst}
>>>     -    local packet=${eth}${ip}${data}
>>>     -
>>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>>     -    echo ${packet} >> ${outfile}
>>>     -}
>>>     -
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl ls-add sw2
>>>     -
>>>     -ovn-nbctl lsp-add sw1 sw1-p11
>>>     -ovn-nbctl lsp-add sw1 sw1-p12
>>>     -ovn-nbctl lsp-add sw1 sw1-p21
>>>     -ovn-nbctl lsp-add sw1 sw1-p22
>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>     -ovn-nbctl lsp-add sw2 sw2-p2
>>>     -
>>>     -net_add n1
>>>     -sim_add hv1
>>>     -as hv1
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>     -    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>     -    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -sim_add hv2
>>>     -as hv2
>>>     -ovs-vsctl add-br br-phys
>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv2-vif2 -- \
>>>     -    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
>>>     -    options:tx_pcap=hv2/vif2-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif2-rx.pcap \
>>>     -    ofport-request=1
>>>     -ovs-vsctl -- add-port br-int hv2-vif3 -- \
>>>     -    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
>>>     -    options:tx_pcap=hv2/vif3-tx.pcap \
>>>     -    options:rxq_pcap=hv2/vif3-rx.pcap \
>>>     -    ofport-request=1
>>>     -
>>>     -OVN_POPULATE_ARP
>>>     -
>>>     -# Enable IGMP snooping on sw1.
>>>     -ovn-nbctl set Logical_Switch sw1 
>>> other_config:mcast_querier="false"
>>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>>     -
>>>     -# No IGMP query should be generated by sw1 
>>> (mcast_querier="false").
>>>     -truncate -s 0 expected
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
>>>     -
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p11.
>>>     -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 IGMP Join for 239.0.1.68 on sw1-p21.
>>>     -send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0
>>>     2) f9f9 \
>>>     -    $(ip_to_hex 239 0 1 68) 04 e9b9 \
>>>     -    /dev/null
>>>     -
>>>     -# Check that the IGMP Group is learned on both hv.
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    test "${total_entries}" = "2"
>>>     -])
>>>     -
>>>     -# Send traffic and make sure it gets forwarded only on the two
>>>     ports that
>>>     -# joined.
>>>     -truncate -s 0 expected
>>>     -truncate -s 0 expected_empty
>>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>>     -    000000000001 01005e000144 \
>>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>>     -    e518e518000a3b3a0000 \
>>>     -    expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>>     -
>>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
>>>     -send_igmp_v3_report hv1-vif1 hv1 \
>>>     -    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
>>>     -    $(ip_to_hex 239 0 1 68) 03 eab9 \
>>>     -    /dev/null
>>>     -
>>>     -# Check IGMP_Group table on both HV.
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    test "${total_entries}" = "1"
>>>     -])
>>>     -
>>>     -# Send traffic traffic and make sure it gets forwarded only on
>>>     the port that
>>>     -# joined.
>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>     -as hv2 reset_pcap_file hv2-vif1 hv2/vif1
>>>     -truncate -s 0 expected
>>>     -truncate -s 0 expected_empty
>>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>>     -    000000000001 01005e000144 \
>>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>>     -    e518e518000a3b3a0000 \
>>>     -    expected
>>>     -
>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>>     -
>>>     -# Flush IGMP groups.
>>>     -ovn-sbctl ip-multicast-flush sw1
>>>     -ovn-nbctl --wait=hv -t 3 sync
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    test "${total_entries}" = "0"
>>>     -])
>>>     -
>>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>>     to minimum.
>>>     -ovn-nbctl set Logical_Switch sw2 \
>>>     -    other_config:mcast_snoop="true" \
>>>     -    other_config:mcast_querier="true" \
>>>     -    other_config:mcast_query_interval=1 \
>>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>>     -
>>>     -# Wait for 1 query interval (1 sec) and check that two queries
>>>     are generated.
>>>     -truncate -s 0 expected
>>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>>     expected
>>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>>     expected
>>>     -
>>>     -sleep 1
>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
>>>     -
>>>     -OVN_CLEANUP([hv1], [hv2])
>>>     -AT_CLEANUP
>>>     diff --git a/tests/system-ovn.at <http://system-ovn.at>
>>>     b/tests/system-ovn.at <http://system-ovn.at>
>>>     deleted file mode 100644
>>>     index f88ad31..0000000
>>>     --- a/tests/system-ovn.at <http://system-ovn.at>
>>>     +++ /dev/null
>>>     @@ -1,1667 +0,0 @@
>>>     -AT_BANNER([system-ovn])
>>>     -
>>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and
>>>     DNAT])
>>>     -AT_KEYWORDS([ovnnat])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>> "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>     -# to it.  R2 is a gateway router on which we add NAT rules.
>>>     -#
>>>     -#    foo -- R1 -- join - R2 -- alice
>>>     -#           |
>>>     -#    bar ----
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Static routes.
>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>     -"192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>     -
>>>     -# Add a DNAT rule.
>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>     logical_ip=192.168.1.2 \
>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>     -
>>>     -# Add a SNAT rule
>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>     logical_ip=192.168.2.2 \
>>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>>     -
>>>     -# wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>     'nat(src=30.0.0.1)'])
>>>     -
>>>     -# 'alice1' should be able to ping 'foo1' directly.
>>>     -NS_CHECK_EXEC([alice1], [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
>>>     -])
>>>     -
>>>     -# North-South DNAT: 'alice1' should also be able to ping 'foo1'
>>>     via 30.0.0.2
>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# Check conntrack entries.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.2) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>>     traffic
>>>     -# from 30.0.0.1
>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# Add static routes to handle east-west NAT.
>>>     -ovn-nbctl lr-route-add R1 30.0.0.0/24 <http://30.0.0.0/24> 
>>> 20.0.0.2
>>>     -
>>>     -# wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -
>>>     -# Flush conntrack entries for easier output parsing of next test.
>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>     -
>>>     -# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' 
>>> receives it.
>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# As we have a static route that sends all packets with 
>>> destination
>>>     -# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to
>>>     192.168.1.2
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1,
>>>     the source is
>>>     -# SNATted and 'foo1' receives it.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy 
>>> SNAT])
>>>     -AT_KEYWORDS([ovnnat])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>> "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) connected
>>>     -# to it.  R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it.
>>>     -# R2 is a gateway router on which we add NAT rules.
>>>     -#
>>>     -#    foo -- R1 -- join - R2 -- alice
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Static routes.
>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Add a SNAT rule
>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>     logical_ip=192.168.1.2 \
>>>     -    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
>>>     -
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>     'nat(src=172.16.1.1)'])
>>>     -
>>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>>     traffic
>>>     -# from 172.16.1.1
>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.1) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
>>>     -AT_KEYWORDS([ovnnat])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>     LS "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it. Note how both alice and
>>>     -# bob have the same subnet behind it.  We are trying to simulate
>>>     external
>>>     -# network via those 2 switches. In real world the switch ports of
>>>     these
>>>     -# switches will have addresses set as "unknown" to make them
>>>     learning switches.
>>>     -# Or those switches will be "localnet" ones.
>>>     -#
>>>     -#    foo -- R1 -- join - R2 -- alice
>>>     -#           |          |
>>>     -#    bar ----          - R3 --- bob
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add bob
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect bob to R3
>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>     <http://172.16.1.2/24>
>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>     -    type=router options:router-port=bob
>>>     addresses=\"00:00:03:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Connect R3 to join
>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>     <http://20.0.0.3/24>
>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>> r3-join \
>>>     -    type=router options:router-port=R3_join
>>>     addresses='"00:00:04:01:02:05"'
>>>     -
>>>     -# Install static routes with source ip address as the policy for
>>>     routing.
>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>     go via R3.
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>     <http://192.168.1.0/24> 20.0.0.2
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>     <http://192.168.2.0/24> 20.0.0.3
>>>     -
>>>     -# Static routes.
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>>     -ovn-nbctl set logical_router R2 
>>> options:dnat_force_snat_ip=20.0.0.2
>>>     -ovn-nbctl set logical_router R3 
>>> options:dnat_force_snat_ip=20.0.0.3
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>     -"192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>     -
>>>     -# Logical port 'bob1' in switch 'bob'.
>>>     -ADD_NAMESPACES(bob1)
>>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>>     -         "172.16.1.2")
>>>     -ovn-nbctl lsp-add bob bob1 \
>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>     -
>>>     -# Router R2
>>>     -# Add a DNAT rule.
>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>     logical_ip=192.168.1.2 \
>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>     -
>>>     -# Add a SNAT rule
>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>     logical_ip=192.168.1.2 \
>>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>>     -
>>>     -# Router R3
>>>     -# Add a DNAT rule.
>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>     logical_ip=192.168.1.2 \
>>>     -    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
>>>     -
>>>     -# Add a SNAT rule
>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>     logical_ip=192.168.2.2 \
>>>     -    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
>>>     -
>>>     -# wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>     'nat(src=30.0.0.4)'])
>>>     -
>>>     -# North-South DNAT: 'alice1' should be able to ping 'foo1' via
>>>     30.0.0.2
>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# Check conntrack entries.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.3) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# But foo1 should receive traffic from 20.0.0.2
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# North-South DNAT: 'bob1' should be able to ping 'foo1' via 
>>> 30.0.0.3
>>>     -NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# Check conntrack entries.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.4) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# But foo1 should receive traffic from 20.0.0.3
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.3) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives 
>>> traffic
>>>     -# from 30.0.0.4
>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.4) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>>     traffic
>>>     -# from 30.0.0.1
>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- load-balancing])
>>>     -AT_KEYWORDS([ovnlb])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# 2 logical switches "foo" (192.168.1.0/24
>>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>>     <http://172.16.1.0/24>)
>>>     -# connected to a router R1.
>>>     -# foo has foo1 to act as a client.
>>>     -# bar has bar1, bar2, bar3 to act as servers.
>>>     -#
>>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Create logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:0f:01:02:03", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
>>>     -
>>>     -ADD_NAMESPACES(bar2)
>>>     -ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24
>>>     <http://172.16.1.3/24>", "f0:00:0f:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add bar bar2 \
>>>     --- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
>>>     -
>>>     -ADD_NAMESPACES(bar3)
>>>     -ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24
>>>     <http://172.16.1.4/24>", "f0:00:0f:01:02:05", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add bar bar3 \
>>>     --- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
>>>     -
>>>     -# Config OVN load-balancer with a VIP.
>>>     -uuid=`ovn-nbctl  create load_balancer
>>>     vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
>>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>>     -
>>>     -# Create another load-balancer with another VIP.
>>>     -uuid=`ovn-nbctl create load_balancer
>>>     vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
>>>     -ovn-nbctl add logical_switch foo load_balancer $uuid
>>>     -
>>>     -# Config OVN load-balancer with another VIP (this time with 
>>> ports).
>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>     <http://30.0.0.2:8000>"'='"172.16.1.2:80
>>>     <http://172.16.1.2:80>,172.16.1.3:80
>>>     <http://172.16.1.3:80>,172.16.1.4:80 <http://172.16.1.4:80>"'
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>     -grep 'nat(dst=172.16.1.4:80)'])
>>>     -
>>>     -# Start webservers in 'bar1', 'bar2' and 'bar3'.
>>>     -OVS_START_L7([bar1], [http])
>>>     -OVS_START_L7([bar2], [http])
>>>     -OVS_START_L7([bar3], [http])
>>>     -
>>>     -dnl Should work with the virtual IP 30.0.0.1 address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Should work with the virtual IP 30.0.0.3 address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>     wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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"])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- load-balancing - same subnet.])
>>>     -AT_KEYWORDS([ovnlb])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# 1 logical switch "foo" (192.168.1.0/24 <http://192.168.1.0/24>)
>>>     connected to router R1.
>>>     -# foo has foo1, foo2, foo3, foo4 as logical ports.
>>>     -#
>>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>>     Router is needed for default
>>>     -# gateway. We will test load-balancing with foo1 as a client and
>>>     foo2, foo3 and
>>>     -# foo4 as servers.
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl ls-add foo
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch
>>>     'foo'.
>>>     -ADD_NAMESPACES(foo1, foo2, foo3, foo4)
>>>     -for i in `seq 1 4`; do
>>>     -    j=`expr $i + 1`
>>>     -    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24",
>>>     "f0:00:00:01:02:0$j", \
>>>     -             "192.168.1.1")
>>>     -    ovn-nbctl lsp-add foo foo$i \
>>>     -        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 
>>> 192.168.1.$j"
>>>     -done
>>>     -
>>>     -# Config OVN load-balancer with a VIP.
>>>     -uuid=`ovn-nbctl  create load_balancer
>>>     vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
>>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>>     -
>>>     -# Config OVN load-balancer with another VIP (this time with 
>>> ports).
>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>     <http://30.0.0.2:8000>"'='"192.168.1.3:80
>>>     <http://192.168.1.3:80>,192.168.1.4:80
>>>     <http://192.168.1.4:80>,192.168.1.5:80 <http://192.168.1.5:80>"'
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>     -grep 'nat(dst=192.168.1.5:80)'])
>>>     -
>>>     -# Start webservers in 'foo2', 'foo3' and 'foo4'.
>>>     -OVS_START_L7([foo2], [http])
>>>     -OVS_START_L7([foo3], [http])
>>>     -OVS_START_L7([foo4], [http])
>>>     -
>>>     -dnl Should work with the virtual IP address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>     wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) 
>>> | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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"])
>>>     -AT_CLEANUP
>>>     -
>>>     -AT_SETUP([ovn -- load balancing in gateway router])
>>>     -AT_KEYWORDS([ovnlb])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>> "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>     -# to it.  R2 is a gateway router on which we add load-balancing
>>>     rules.
>>>     -#
>>>     -#    foo -- R1 -- join - R2 -- alice
>>>     -#           |
>>>     -#    bar ----
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Static routes.
>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>     20.0.0.2
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>     -"192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>     -
>>>     -# Config OVN load-balancer with a VIP.
>>>     -uuid=`ovn-nbctl  create load_balancer
>>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>>     -
>>>     -# Config OVN load-balancer with another VIP (this time with 
>>> ports).
>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>     <http://30.0.0.2:8000>"'='"192.168.1.2:80
>>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>>     -
>>>     -# Add SNAT rule to make sure that Load-balancing still works with
>>>     a SNAT rule.
>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>     logical_ip=192.168.2.2 \
>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>     -
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>     -grep 'nat(dst=192.168.2.2:80)'])
>>>     -
>>>     -# Start webservers in 'foo1', 'bar1'.
>>>     -OVS_START_L7([foo1], [http])
>>>     -OVS_START_L7([bar1], [http])
>>>     -
>>>     -dnl Should work with the virtual IP address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000
>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>     wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- multiple gateway routers, load-balancing])
>>>     -AT_KEYWORDS([ovnlb])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>     LS "join"
>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>     connected to it. Note how both alice and
>>>     -# bob have the same subnet behind it.  We are trying to simulate
>>>     external
>>>     -# network via those 2 switches. In real world the switch ports of
>>>     these
>>>     -# switches will have addresses set as "unknown" to make them
>>>     learning switches.
>>>     -# Or those switches will be "localnet" ones.
>>>     -#
>>>     -#    foo -- R1 -- join - R2 -- alice
>>>     -#           |          |
>>>     -#    bar ----          - R3 --- bob
>>>     -
>>>     -ovn-nbctl create Logical_Router name=R1
>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -ovn-nbctl ls-add bob
>>>     -ovn-nbctl ls-add join
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo
>>>     addresses=\"00:00:01:01:02:03\"
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar
>>>     addresses=\"00:00:01:01:02:04\"
>>>     -
>>>     -# Connect alice to R2
>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24>
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice
>>>     addresses=\"00:00:02:01:02:03\"
>>>     -
>>>     -# Connect bob to R3
>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>     <http://172.16.1.2/24>
>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>     -    type=router options:router-port=bob
>>>     addresses=\"00:00:03:01:02:03\"
>>>     -
>>>     -# Connect R1 to join
>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>     <http://20.0.0.1/24>
>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>> r1-join \
>>>     -    type=router options:router-port=R1_join
>>>     addresses='"00:00:04:01:02:03"'
>>>     -
>>>     -# Connect R2 to join
>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>     <http://20.0.0.2/24>
>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>> r2-join \
>>>     -    type=router options:router-port=R2_join
>>>     addresses='"00:00:04:01:02:04"'
>>>     -
>>>     -# Connect R3 to join
>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>     <http://20.0.0.3/24>
>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>> r3-join \
>>>     -    type=router options:router-port=R3_join
>>>     addresses='"00:00:04:01:02:05"'
>>>     -
>>>     -# Install static routes with source ip address as the policy for
>>>     routing.
>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>     go via R3.
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>     <http://192.168.1.0/24> 20.0.0.2
>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>     <http://192.168.2.0/24> 20.0.0.3
>>>     -
>>>     -# Static routes.
>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>     20.0.0.1
>>>     -
>>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>>     -ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
>>>     -ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>     -"192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>     -
>>>     -# Logical port 'bob1' in switch 'bob'.
>>>     -ADD_NAMESPACES(bob1)
>>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>>     -         "172.16.1.2")
>>>     -ovn-nbctl lsp-add bob bob1 \
>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>     -
>>>     -# Config OVN load-balancer with a VIP.
>>>     -uuid=`ovn-nbctl  create load_balancer
>>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>>     -ovn-nbctl set logical_router R3 load_balancer=$uuid
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>     -grep 'nat(dst=192.168.2.2)'])
>>>     -
>>>     -# Start webservers in 'foo1', 'bar1'.
>>>     -OVS_START_L7([foo1], [http])
>>>     -OVS_START_L7([bar1], [http])
>>>     -
>>>     -dnl Should work with the virtual IP address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Force SNAT should have worked.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- load balancing in router with gateway router 
>>> port])
>>>     -AT_KEYWORDS([ovnlb])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>     <http://192.168.2.0/24>),
>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>     it.  The port between R1 and
>>>     -# alice is the router gateway port where the R1 LB rules are 
>>> applied.
>>>     -#
>>>     -#    foo -- R1 -- bar
>>>     -#           |
>>>     -#    alice ----
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24> \
>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar \
>>>     -    -- lsp-set-addresses rp-bar router
>>>     -
>>>     -# Connect alice to R1
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'foo2' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo2)
>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo2 \
>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>     -         "192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>     -
>>>     -# Config OVN load-balancer with a VIP.
>>>     -uuid=`ovn-nbctl  create load_balancer
>>>     vips:172.16.1.10="192.168.1.2,192.168.2.2"`
>>>     -ovn-nbctl set logical_router R1 load_balancer=$uuid
>>>     -
>>>     -# Config OVN load-balancer with another VIP (this time with 
>>> ports).
>>>     -ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000
>>>     <http://172.16.1.11:8000>"'='"192.168.1.2:80
>>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>>     -
>>>     -# Wait for ovn-controller to catch up.
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>     -grep 'nat(dst=192.168.2.2:80)'])
>>>     -
>>>     -# Start webservers in 'foo1', 'bar1'.
>>>     -OVS_START_L7([foo1], [http])
>>>     -OVS_START_L7([bar1], [http])
>>>     -
>>>     -dnl Should work with the virtual IP address through NAT
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1
>>>     --retry-connrefused -v -o wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.10) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>     -for i in `seq 1 20`; do
>>>     -    echo Request $i
>>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000
>>>     <http://172.16.1.11:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>     wget$i.log])
>>>     -done
>>>     -
>>>     -dnl Each server should have at least one connection.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.11) |
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
>>>     -AT_KEYWORDS([ovnnat])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>     <http://192.168.2.0/24>),
>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>     it.  The port between R1 and
>>>     -# alice is the router gateway port where the R1 NAT rules are
>>>     applied.
>>>     -#
>>>     -#    foo -- R1 -- alice
>>>     -#           |
>>>     -#    bar ----
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24> \
>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar \
>>>     -    -- lsp-set-addresses rp-bar router
>>>     -
>>>     -# Connect alice to R1
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'foo2' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo2)
>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo2 \
>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>     -         "192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>     -
>>>     -# Add DNAT rules
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>>     192.168.1.3 foo2 00:00:02:02:03:05])
>>>     -
>>>     -# Add a SNAT rule
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>>     <http://192.168.0.0/16>])
>>>     -
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>     'nat(src=172.16.1.1)'])
>>>     -
>>>     -# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that DNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.3) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives
>>>     traffic
>>>     -# from 172.16.1.4
>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.1) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>     -
>>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>>     traffic
>>>     -# from 172.16.1.1
>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>> command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.1) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
>>>     -AT_KEYWORDS([ovnnat])
>>>     -
>>>     -CHECK_CONNTRACK()
>>>     -CHECK_CONNTRACK_NAT()
>>>     -ovn_start
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>     <http://192.168.2.0/24>),
>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>     it.  The port between R1 and
>>>     -# alice is the router gateway port where the R1 NAT rules are
>>>     applied.
>>>     -#
>>>     -#    foo -- R1 -- alice
>>>     -#           |
>>>     -#    bar ----
>>>     -
>>>     -ovn-nbctl lr-add R1
>>>     -
>>>     -ovn-nbctl ls-add foo
>>>     -ovn-nbctl ls-add bar
>>>     -ovn-nbctl ls-add alice
>>>     -
>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>     <http://192.168.1.1/24>
>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>     <http://192.168.2.1/24>
>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>     <http://172.16.1.1/24> \
>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>     -
>>>     -# Connect foo to R1
>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>     -    type=router options:router-port=foo \
>>>     -    -- lsp-set-addresses rp-foo router
>>>     -
>>>     -# Connect bar to R1
>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>     -    type=router options:router-port=bar \
>>>     -    -- lsp-set-addresses rp-bar router
>>>     -
>>>     -# Connect alice to R1
>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>     rp-alice \
>>>     -    type=router options:router-port=alice \
>>>     -    -- lsp-set-addresses rp-alice router
>>>     -
>>>     -# Logical port 'foo1' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo1)
>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo1 \
>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>     -
>>>     -# Logical port 'foo2' in switch 'foo'.
>>>     -ADD_NAMESPACES(foo2)
>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>     -         "192.168.1.1")
>>>     -ovn-nbctl lsp-add foo foo2 \
>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>     -
>>>     -# Logical port 'bar1' in switch 'bar'.
>>>     -ADD_NAMESPACES(bar1)
>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>     -         "192.168.2.1")
>>>     -ovn-nbctl lsp-add bar bar1 \
>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>     -
>>>     -# Logical port 'alice1' in switch 'alice'.
>>>     -ADD_NAMESPACES(alice1)
>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>     -         "172.16.1.1")
>>>     -ovn-nbctl lsp-add alice alice1 \
>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>     -
>>>     -# Add DNAT rules
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>>     192.168.2.2 bar1 00:00:02:02:03:05])
>>>     -
>>>     -# Add a SNAT rule
>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>>     <http://192.168.0.0/16>])
>>>     -
>>>     -ovn-nbctl --wait=hv sync
>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>     'nat(src=172.16.1.1)'])
>>>     -
>>>     -echo "------ hv dump ------"
>>>     -ovs-ofctl show br-int
>>>     -ovs-ofctl dump-flows br-int
>>>     -echo "---------------------"
>>>     -
>>>     -# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>     FORMAT_CT(192.168.2.2) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>     FORMAT_CT(192.168.2.2) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>     FORMAT_CT(192.168.2.2) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>     -])
>>>     -
>>>     -# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# Check conntrack entries.  First SNAT of 'foo1' address happens.
>>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.4) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>     -
>>>     -# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>     FORMAT_PING], \
>>>     -[0], [dnl
>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>     -])
>>>     -
>>>     -# Check conntrack entries.  First SNAT of 'foo2' address happens.
>>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>> FORMAT_CT(172.16.1.1) | \
>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     -
>>>     -AT_SETUP([ovn -- 2 LSs IGMP])
>>>     -AT_KEYWORDS([ovnigmp])
>>>     -
>>>     -ovn_start
>>>     -
>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>     -ADD_BR([br-int])
>>>     -
>>>     -# Set external-ids in br-int needed for ovn-controller
>>>     -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.0.0.1 \
>>>     -        -- set bridge br-int fail-mode=secure
>>>     other-config:disable-in-band=true
>>>     -
>>>     -# Start ovn-controller
>>>     -start_daemon ovn-controller
>>>     -
>>>     -# Logical network:
>>>     -# Two independent logical switches (sw1 and sw2).
>>>     -# sw1:
>>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>     -#   - 2 ports (sw1-p1 - sw1-p2)
>>>     -# sw2:
>>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>     -#   - 2 port (sw2-p1 - sw2-p2)
>>>     -#   - IGMP Querier from 20.0.0.254
>>>     -
>>>     -ovn-nbctl ls-add sw1
>>>     -ovn-nbctl ls-add sw2
>>>     -
>>>     -for i in `seq 1 2`
>>>     -do
>>>     -    ADD_NAMESPACES(sw1-p$i)
>>>     -    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24",
>>>     "00:00:00:00:01:0$i", \
>>>     -            "10.0.0.254")
>>>     -    ovn-nbctl lsp-add sw1 sw1-p$i \
>>>     -        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 
>>> 10.0.0.$i"
>>>     -done
>>>     -
>>>     -for i in `seq 1 2`
>>>     -do
>>>     -    ADD_NAMESPACES(sw2-p$i)
>>>     -    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24",
>>>     "00:00:00:00:02:0$i", \
>>>     -            "20.0.0.254")
>>>     -    ovn-nbctl lsp-add sw2 sw2-p$i \
>>>     -        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 
>>> 20.0.0.$i"
>>>     -done
>>>     -
>>>     -# Enable IGMP snooping on sw1.
>>>     -ovn-nbctl set Logical_Switch sw1 
>>> other_config:mcast_querier="false"
>>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>>     -
>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p1.
>>>     -NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32
>>>     <http://239.0.1.68/32> autojoin], [0])
>>>     -
>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p2
>>>     -NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32
>>>     <http://239.0.1.68/32> autojoin], [0])
>>>     -
>>>     -# Check that the IGMP Group is learned.
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>>     ":" | wc -w`
>>>     -    test "${total_entries}" = "1"
>>>     -    test "${ports}" = "2"
>>>     -])
>>>     -
>>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
>>>     -NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32
>>>     <http://239.0.1.68/32>], [0])
>>>     -
>>>     -# Check that only one port is left in the group.
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>>     ":" | wc -w`
>>>     -    test "${total_entries}" = "1"
>>>     -    test "${ports}" = "1"
>>>     -])
>>>     -
>>>     -# Flush IGMP groups.
>>>     -ovn-sbctl ip-multicast-flush sw1
>>>     -ovn-nbctl --wait=hv -t 3 sync
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>     | wc -l`
>>>     -    test "${total_entries}" = "0"
>>>     -])
>>>     -
>>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>>     to minimum.
>>>     -ovn-nbctl set Logical_Switch sw2 \
>>>     -    other_config:mcast_snoop="true" \
>>>     -    other_config:mcast_querier="true" \
>>>     -    other_config:mcast_query_interval=1 \
>>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>>     -
>>>     -# Check that queries are generated.
>>>     -NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp >
>>>     sw2-p1.pcap &])
>>>     -
>>>     -OVS_WAIT_UNTIL([
>>>     -    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
>>>     -    test "${total_queries}" = "2"
>>>     -])
>>>     -
>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>     -
>>>     -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
>>>     diff --git a/tests/test-ovn.c b/tests/test-ovn.c
>>>     deleted file mode 100644
>>>     index 0b9e824..0000000
>>>     --- a/tests/test-ovn.c
>>>     +++ /dev/null
>>>     @@ -1,1584 +0,0 @@
>>>     -/*
>>>     - * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
>>>     - *
>>>     - * Licensed under the Apache License, Version 2.0 (the "License");
>>>     - * you may not use this file except in compliance with the 
>>> License.
>>>     - * You may obtain a copy of the License at:
>>>     - *
>>>     - * http://www.apache.org/licenses/LICENSE-2.0
>>>     - *
>>>     - * Unless required by applicable law or agreed to in writing,
>>>     software
>>>     - * distributed under the License is distributed on an "AS IS" 
>>> BASIS,
>>>     - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
>>>     or implied.
>>>     - * See the License for the specific language governing
>>>     permissions and
>>>     - * limitations under the License.
>>>     - */
>>>     -
>>>     -#include <config.h>
>>>     -#include <errno.h>
>>>     -#include <getopt.h>
>>>     -#include <sys/wait.h>
>>>     -
>>>     -#include "command-line.h"
>>>     -#include "dp-packet.h"
>>>     -#include "fatal-signal.h"
>>>     -#include "flow.h"
>>>     -#include "openvswitch/dynamic-string.h"
>>>     -#include "openvswitch/match.h"
>>>     -#include "openvswitch/ofp-actions.h"
>>>     -#include "openvswitch/ofpbuf.h"
>>>     -#include "openvswitch/vlog.h"
>>>     -#include "ovn/actions.h"
>>>     -#include "ovn/expr.h"
>>>     -#include "ovn/lex.h"
>>>     -#include "ovn/logical-fields.h"
>>>     -#include "ovn/lib/ovn-l7.h"
>>>     -#include "ovn/lib/extend-table.h"
>>>     -#include "ovs-thread.h"
>>>     -#include "ovstest.h"
>>>     -#include "openvswitch/shash.h"
>>>     -#include "simap.h"
>>>     -#include "util.h"
>>>     -
>>>     -/* --relops: Bitmap of the relational operators to test, in
>>>     exhaustive test. */
>>>     -static unsigned int test_relops;
>>>     -
>>>     -/* --nvars: Number of numeric variables to test, in exhaustive
>>>     test. */
>>>     -static int test_nvars = 2;
>>>     -
>>>     -/* --svars: Number of string variables to test, in exhaustive
>>>     test. */
>>>     -static int test_svars = 2;
>>>     -
>>>     -/* --bits: Number of bits per variable, in exhaustive test. */
>>>     -static int test_bits = 3;
>>>     -
>>>     -/* --operation: The operation to test, in exhaustive test. */
>>>     -static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW }
>>>     operation
>>>     -    = OP_FLOW;
>>>     -
>>>     -/* --parallel: Number of parallel processes to use in test. */
>>>     -static int test_parallel = 1;
>>>     -
>>>     -/* -m, --more: Message verbosity */
>>>     -static int verbosity;
>>>     -
>>>     -static void
>>>     -compare_token(const struct lex_token *a, const struct lex_token 
>>> *b)
>>>     -{
>>>     -    if (a->type != b->type) {
>>>     -        fprintf(stderr, "type differs: %d -> %d\n", a->type,
>>>     b->type);
>>>     -        return;
>>>     -    }
>>>     -
>>>     -    if (!((a->s && b->s && !strcmp(a->s, b->s))
>>>     -          || (!a->s && !b->s))) {
>>>     -        fprintf(stderr, "string differs: %s -> %s\n",
>>>     -                a->s ? a->s : "(null)",
>>>     -                b->s ? b->s : "(null)");
>>>     -        return;
>>>     -    }
>>>     -
>>>     -    if (a->type == LEX_T_INTEGER || a->type ==
>>>     LEX_T_MASKED_INTEGER) {
>>>     -        if (memcmp(&a->value, &b->value, sizeof a->value)) {
>>>     -            fprintf(stderr, "value differs\n");
>>>     -            return;
>>>     -        }
>>>     -
>>>     -        if (a->type == LEX_T_MASKED_INTEGER
>>>     -            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
>>>     -            fprintf(stderr, "mask differs\n");
>>>     -            return;
>>>     -        }
>>>     -
>>>     -        if (a->format != b->format
>>>     -            && !(a->format == LEX_F_HEXADECIMAL
>>>     -                 && b->format == LEX_F_DECIMAL
>>>     -                 && a->value.integer == 0)) {
>>>     -            fprintf(stderr, "format differs: %d -> %d\n",
>>>     -                    a->format, b->format);
>>>     -        }
>>>     -    }
>>>     -}
>>>     -
>>>     -static void
>>>     -test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    struct ds input;
>>>     -    struct ds output;
>>>     -
>>>     -    ds_init(&input);
>>>     -    ds_init(&output);
>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>     -        struct lexer lexer;
>>>     -
>>>     -        lexer_init(&lexer, ds_cstr(&input));
>>>     -        ds_clear(&output);
>>>     -        while (lexer_get(&lexer) != LEX_T_END) {
>>>     -            size_t len = output.length;
>>>     -            lex_token_format(&lexer.token, &output);
>>>     -
>>>     -            /* Check that the formatted version can really be
>>>     parsed back
>>>     -             * losslessly. */
>>>     -            if (lexer.token.type != LEX_T_ERROR) {
>>>     -                const char *s = ds_cstr(&output) + len;
>>>     -                struct lexer l2;
>>>     -
>>>     -                lexer_init(&l2, s);
>>>     -                lexer_get(&l2);
>>>     -                compare_token(&lexer.token, &l2.token);
>>>     -                lexer_destroy(&l2);
>>>     -            }
>>>     -            ds_put_char(&output, ' ');
>>>     -        }
>>>     -        lexer_destroy(&lexer);
>>>     -
>>>     -        ds_chomp(&output, ' ');
>>>     -        puts(ds_cstr(&output));
>>>     -    }
>>>     -    ds_destroy(&input);
>>>     -    ds_destroy(&output);
>>>     -}
>>>     -
>>>     -static void
>>>     -create_symtab(struct shash *symtab)
>>>     -{
>>>     -    ovn_init_symtab(symtab);
>>>     -
>>>     -    /* For negative testing. */
>>>     -    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0,
>>>     "xyzzy", false);
>>>     -    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
>>>     -                          "self_recurse != 0", false);
>>>     -    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
>>>     -                          "mutual_recurse_2 != 0", false);
>>>     -    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
>>>     -                          "mutual_recurse_1 != 0", false);
>>>     -    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
>>>     -}
>>>     -
>>>     -static void
>>>     -create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
>>>     -                struct hmap *nd_ra_opts,
>>>     -                struct controller_event_options *event_opts)
>>>     -{
>>>     -    hmap_init(dhcp_opts);
>>>     -    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
>>>     -    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
>>>     -    dhcp_opt_add(dhcp_opts, "classless_static_route", 121,
>>>     "static_routes");
>>>     -    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
>>>     -    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
>>>     -    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
>>>     -    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
>>>     -    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
>>>     -    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
>>>     -    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
>>>     -    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
>>>     -    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
>>>     -    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
>>>     -    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
>>>     -
>>>     -    /* DHCPv6 options. */
>>>     -    hmap_init(dhcpv6_opts);
>>>     -    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
>>>     -    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
>>>     -    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
>>>     -    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
>>>     -
>>>     -    /* IPv6 ND RA options. */
>>>     -    hmap_init(nd_ra_opts);
>>>     -    nd_ra_opts_init(nd_ra_opts);
>>>     -
>>>     -    /* OVN controller events options. */
>>>     -    controller_event_opts_init(event_opts);
>>>     -}
>>>     -
>>>     -static void
>>>     -create_addr_sets(struct shash *addr_sets)
>>>     -{
>>>     -    shash_init(addr_sets);
>>>     -
>>>     -    static const char *const addrs1[] = {
>>>     -        "10.0.0.1", "10.0.0.2", "10.0.0.3",
>>>     -    };
>>>     -    static const char *const addrs2[] = {
>>>     -        "::1", "::2", "::3",
>>>     -    };
>>>     -    static const char *const addrs3[] = {
>>>     -        "00:00:00:00:00:01", "00:00:00:00:00:02",
>>>     "00:00:00:00:00:03",
>>>     -    };
>>>     -    static const char *const addrs4[] = { NULL };
>>>     -
>>>     -    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
>>>     -    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
>>>     -    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
>>>     -    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
>>>     -}
>>>     -
>>>     -static void
>>>     -create_port_groups(struct shash *port_groups)
>>>     -{
>>>     -    shash_init(port_groups);
>>>     -
>>>     -    static const char *const pg1[] = {
>>>     -        "lsp1", "lsp2", "lsp3",
>>>     -    };
>>>     -    static const char *const pg2[] = { NULL };
>>>     -
>>>     -    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
>>>     -    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
>>>     -}
>>>     -
>>>     -static bool
>>>     -lookup_port_cb(const void *ports_, const char *port_name,
>>>     unsigned int *portp)
>>>     -{
>>>     -    const struct simap *ports = ports_;
>>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>>     -    if (!node) {
>>>     -        return false;
>>>     -    }
>>>     -    *portp = node->data;
>>>     -    return true;
>>>     -}
>>>     -
>>>     -static bool
>>>     -is_chassis_resident_cb(const void *ports_, const char *port_name)
>>>     -{
>>>     -    const struct simap *ports = ports_;
>>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>>     -    if (node) {
>>>     -        return true;
>>>     -    }
>>>     -    return false;
>>>     -}
>>>     -
>>>     -static void
>>>     -test_parse_expr__(int steps)
>>>     -{
>>>     -    struct shash symtab;
>>>     -    struct shash addr_sets;
>>>     -    struct shash port_groups;
>>>     -    struct simap ports;
>>>     -    struct ds input;
>>>     -
>>>     -    create_symtab(&symtab);
>>>     -    create_addr_sets(&addr_sets);
>>>     -    create_port_groups(&port_groups);
>>>     -
>>>     -    simap_init(&ports);
>>>     -    simap_put(&ports, "eth0", 5);
>>>     -    simap_put(&ports, "eth1", 6);
>>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>>     -    simap_put(&ports, "lsp1", 0x11);
>>>     -    simap_put(&ports, "lsp2", 0x12);
>>>     -    simap_put(&ports, "lsp3", 0x13);
>>>     -
>>>     -    ds_init(&input);
>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>     -        struct expr *expr;
>>>     -        char *error;
>>>     -
>>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab,
>>>     &addr_sets,
>>>     -                                 &port_groups, NULL, &error);
>>>     -        if (!error && steps > 0) {
>>>     -            expr = expr_annotate(expr, &symtab, &error);
>>>     -        }
>>>     -        if (!error) {
>>>     -            if (steps > 1) {
>>>     -                expr = expr_simplify(expr,
>>>     is_chassis_resident_cb, &ports);
>>>     -            }
>>>     -            if (steps > 2) {
>>>     -                expr = expr_normalize(expr);
>>>     -                ovs_assert(expr_is_normalized(expr));
>>>     -            }
>>>     -        }
>>>     -        if (!error) {
>>>     -            if (steps > 3) {
>>>     -                struct hmap matches;
>>>     -
>>>     -                expr_to_matches(expr, lookup_port_cb, &ports,
>>>     &matches);
>>>     -                expr_matches_print(&matches, stdout);
>>>     -                expr_matches_destroy(&matches);
>>>     -            } else {
>>>     -                struct ds output = DS_EMPTY_INITIALIZER;
>>>     -                expr_format(expr, &output);
>>>     -                puts(ds_cstr(&output));
>>>     -                ds_destroy(&output);
>>>     -            }
>>>     -        } else {
>>>     -            puts(error);
>>>     -            free(error);
>>>     -        }
>>>     -        expr_destroy(expr);
>>>     -    }
>>>     -    ds_destroy(&input);
>>>     -
>>>     -    simap_destroy(&ports);
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -    expr_const_sets_destroy(&addr_sets);
>>>     -    shash_destroy(&addr_sets);
>>>     -    expr_const_sets_destroy(&port_groups);
>>>     -    shash_destroy(&port_groups);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    test_parse_expr__(0);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    test_parse_expr__(1);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    test_parse_expr__(2);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    test_parse_expr__(3);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    test_parse_expr__(4);
>>>     -}
>>>     -
>>>     -/* Print the symbol table. */
>>>     -
>>>     -static void
>>>     -test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    struct shash symtab;
>>>     -    create_symtab(&symtab);
>>>     -
>>>     -    const struct shash_node **nodes = shash_sort(&symtab);
>>>     -    for (size_t i = 0; i < shash_count(&symtab); i++) {
>>>     -        const struct expr_symbol *symbol = nodes[i]->data;
>>>     -        struct ds s = DS_EMPTY_INITIALIZER;
>>>     -        expr_symbol_format(symbol, &s);
>>>     -        puts(ds_cstr(&s));
>>>     -        ds_destroy(&s);
>>>     -    }
>>>     -
>>>     -    free(nodes);
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -}
>>>     -
>>>     -/* Evaluate an expression. */
>>>     -
>>>     -static bool
>>>     -lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
>>>     -               unsigned int *portp)
>>>     -{
>>>     -    *portp = atoi(port_name);
>>>     -    return true;
>>>     -}
>>>     -
>>>     -static void
>>>     -test_evaluate_expr(struct ovs_cmdl_context *ctx)
>>>     -{
>>>     -    struct shash symtab;
>>>     -    struct ds input;
>>>     -
>>>     -    ovn_init_symtab(&symtab);
>>>     -
>>>     -    struct flow uflow;
>>>     -    char *error = expr_parse_microflow(ctx->argv[1], &symtab,
>>>     NULL, NULL,
>>>     -                                       lookup_atoi_cb, NULL, 
>>> &uflow);
>>>     -    if (error) {
>>>     -        ovs_fatal(0, "%s", error);
>>>     -    }
>>>     -
>>>     -    ds_init(&input);
>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>     -        struct expr *expr;
>>>     -
>>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL,
>>>     NULL, NULL,
>>>     -                                 &error);
>>>     -        if (!error) {
>>>     -            expr = expr_annotate(expr, &symtab, &error);
>>>     -        }
>>>     -        if (!error) {
>>>     -            printf("%d\n", expr_evaluate(expr, &uflow,
>>>     lookup_atoi_cb, NULL));
>>>     -        } else {
>>>     -            puts(error);
>>>     -            free(error);
>>>     -        }
>>>     -        expr_destroy(expr);
>>>     -    }
>>>     -    ds_destroy(&input);
>>>     -
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -}
>>>     -
>>>     -/* Compositions.
>>>     - *
>>>     - * The "compositions" of a positive integer N are all of the ways
>>>     that one can
>>>     - * add up positive integers to sum to N.  For example, the
>>>     compositions of 3
>>>     - * are 3, 2+1, 1+2, and 1+1+1.
>>>     - *
>>>     - * We use compositions to find all the ways to break up N terms
>>>     of a Boolean
>>>     - * expression into subexpressions.  Suppose we want to generate
>>>     all expressions
>>>     - * with 3 terms.  The compositions of 3 (ignoring 3 itself)
>>>     provide the
>>>     - * possibilities (x && x) || x, x || (x && x), and x || x || x.
>>>     (Of course one
>>>     - * can exchange && for || in each case.)  One must recursively
>>>     compose the
>>>     - * sub-expressions whose values are 3 or greater; that is what
>>>     the "tree shape"
>>>     - * concept later covers.
>>>     - *
>>>     - * To iterate through all compositions of, e.g., 5:
>>>     - *
>>>     - *     unsigned int state;
>>>     - *     int s[5];
>>>     - *     int n;
>>>     - *
>>>     - *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n 
>>> > 0;
>>>     - *          n = next_composition(&state, s, n)) {
>>>     - *          // Do something with composition 's' with 'n' 
>>> elements.
>>>     - *     }
>>>     - *
>>>     - * Algorithm from D. E. Knuth, _The Art of Computer Programming,
>>>     Vol. 4A:
>>>     - * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to
>>>     exercise
>>>     - * 12(a).
>>>     - */
>>>     -
>>>     -/* Begins iteration through the compositions of 'n'. Initializes
>>>     's' to the
>>>     - * number of elements in the first composition of 'n' and returns
>>>     that number
>>>     - * of elements.  The first composition in fact is always 'n'
>>>     itself, so the
>>>     - * return value will be 1.
>>>     - *
>>>     - * Initializes '*state' to some internal state information.  The
>>>     caller must
>>>     - * maintain this state (and 's') for use by next_composition().
>>>     - *
>>>     - * 's' must have room for at least 'n' elements. */
>>>     -static int
>>>     -first_composition(int n, unsigned int *state, int s[])
>>>     -{
>>>     -    *state = 0;
>>>     -    s[0] = n;
>>>     -    return 1;
>>>     -}
>>>     -
>>>     -/* Advances 's', with 'sn' elements, to the next composition and
>>>     returns the
>>>     - * number of elements in this new composition, or 0 if no
>>>     compositions are
>>>     - * left.  'state' is the same internal state passed to
>>>     first_composition(). */
>>>     -static int
>>>     -next_composition(unsigned int *state, int s[], int sn)
>>>     -{
>>>     -    int j = sn - 1;
>>>     -    if (++*state & 1) {
>>>     -        if (s[j] > 1) {
>>>     -            s[j]--;
>>>     -            s[j + 1] = 1;
>>>     -            j++;
>>>     -        } else {
>>>     -            j--;
>>>     -            s[j]++;
>>>     -        }
>>>     -    } else {
>>>     -        if (s[j - 1] > 1) {
>>>     -            s[j - 1]--;
>>>     -            s[j + 1] = s[j];
>>>     -            s[j] = 1;
>>>     -            j++;
>>>     -        } else {
>>>     -            j--;
>>>     -            if (!j) {
>>>     -                return 0;
>>>     -            }
>>>     -            s[j] = s[j + 1];
>>>     -            s[j - 1]++;
>>>     -        }
>>>     -    }
>>>     -    return j + 1;
>>>     -}
>>>     -
>>>     -static void
>>>     -test_composition(struct ovs_cmdl_context *ctx)
>>>     -{
>>>     -    int n = atoi(ctx->argv[1]);
>>>     -    unsigned int state;
>>>     -    int s[50];
>>>     -
>>>     -    for (int sn = first_composition(n, &state, s); sn;
>>>     -         sn = next_composition(&state, s, sn)) {
>>>     -        for (int i = 0; i < sn; i++) {
>>>     -            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
>>>     -        }
>>>     -    }
>>>     -}
>>>     -
>>>     -/* Tree shapes.
>>>     - *
>>>     - * This code generates all possible Boolean expressions with a
>>>     specified number
>>>     - * of terms N (equivalent to the number of external nodes in a 
>>> tree).
>>>     - *
>>>     - * See test_tree_shape() for a simple example. */
>>>     -
>>>     -/* An array of these structures describes the shape of a tree.
>>>     - *
>>>     - * A single element of struct tree_shape describes a single node
>>>     in the tree.
>>>     - * The node has 'sn' direct children.  From left to right, for i
>>>     in 0...sn-1,
>>>     - * s[i] is 1 if the child is a leaf node, otherwise the child is
>>>     a subtree and
>>>     - * s[i] is the number of leaf nodes within that subtree. In the
>>>     latter case,
>>>     - * the subtree is described by another struct tree_shape within
>>>     the enclosing
>>>     - * array.  The tree_shapes are ordered in the array in in-order.
>>>     - */
>>>     -struct tree_shape {
>>>     -    unsigned int state;
>>>     -    int s[50];
>>>     -    int sn;
>>>     -};
>>>     -
>>>     -static int
>>>     -init_tree_shape__(struct tree_shape ts[], int n)
>>>     -{
>>>     -    if (n <= 2) {
>>>     -        return 0;
>>>     -    }
>>>     -
>>>     -    int n_tses = 1;
>>>     -    /* Skip the first composition intentionally. */
>>>     -    ts->sn = first_composition(n, &ts->state, ts->s);
>>>     -    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
>>>     -    for (int i = 0; i < ts->sn; i++) {
>>>     -        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
>>>     -    }
>>>     -    return n_tses;
>>>     -}
>>>     -
>>>     -/* Initializes 'ts[]' as the first in the set of all of possible
>>>     shapes of
>>>     - * trees with 'n' leaves.  Returns the number of "struct
>>>     tree_shape"s in the
>>>     - * first tree shape. */
>>>     -static int
>>>     -init_tree_shape(struct tree_shape ts[], int n)
>>>     -{
>>>     -    switch (n) {
>>>     -    case 1:
>>>     -        ts->sn = 1;
>>>     -        ts->s[0] = 1;
>>>     -        return 1;
>>>     -    case 2:
>>>     -        ts->sn = 2;
>>>     -        ts->s[0] = 1;
>>>     -        ts->s[1] = 1;
>>>     -        return 1;
>>>     -    default:
>>>     -        return init_tree_shape__(ts, n);
>>>     -    }
>>>     -}
>>>     -
>>>     -/* Advances 'ts', which currently has 'n_tses' elements, to the
>>>     next possible
>>>     - * tree shape with the number of leaves passed to
>>>     init_tree_shape().  Returns
>>>     - * the number of "struct tree_shape"s in the next shape, or 0 if
>>>     all tree
>>>     - * shapes have been visited. */
>>>     -static int
>>>     -next_tree_shape(struct tree_shape ts[], int n_tses)
>>>     -{
>>>     -    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1]
>>>     == 1) {
>>>     -        return 0;
>>>     -    }
>>>     -    while (n_tses > 0) {
>>>     -        struct tree_shape *p = &ts[n_tses - 1];
>>>     -        p->sn = p->sn > 1 ? next_composition(&p->state, p->s,
>>>     p->sn) : 0;
>>>     -        if (p->sn) {
>>>     -            for (int i = 0; i < p->sn; i++) {
>>>     -                n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
>>>     -            }
>>>     -            break;
>>>     -        }
>>>     -        n_tses--;
>>>     -    }
>>>     -    return n_tses;
>>>     -}
>>>     -
>>>     -static void
>>>     -print_tree_shape(const struct tree_shape ts[], int n_tses)
>>>     -{
>>>     -    for (int i = 0; i < n_tses; i++) {
>>>     -        if (i) {
>>>     -            printf(", ");
>>>     -        }
>>>     -        for (int j = 0; j < ts[i].sn; j++) {
>>>     -            int k = ts[i].s[j];
>>>     -            if (k > 9) {
>>>     -                printf("(%d)", k);
>>>     -            } else {
>>>     -                printf("%d", k);
>>>     -            }
>>>     -        }
>>>     -    }
>>>     -}
>>>     -
>>>     -static void
>>>     -test_tree_shape(struct ovs_cmdl_context *ctx)
>>>     -{
>>>     -    int n = atoi(ctx->argv[1]);
>>>     -    struct tree_shape ts[50];
>>>     -    int n_tses;
>>>     -
>>>     -    for (n_tses = init_tree_shape(ts, n); n_tses;
>>>     -         n_tses = next_tree_shape(ts, n_tses)) {
>>>     -        print_tree_shape(ts, n_tses);
>>>     -        putchar('\n');
>>>     -    }
>>>     -}
>>>     -
>>>     -/* Iteration through all possible terminal expressions (e.g.
>>>     EXPR_T_CMP and
>>>     - * EXPR_T_BOOLEAN expressions).
>>>     - *
>>>     - * Given a tree shape, this allows the code to try all possible
>>>     ways to plug in
>>>     - * terms.
>>>     - *
>>>     - * Example use:
>>>     - *
>>>     - *     struct expr terminal;
>>>     - *     const struct expr_symbol *vars = ...;
>>>     - *     int n_vars = ...;
>>>     - *     int n_bits = ...;
>>>     - *
>>>     - *     init_terminal(&terminal, vars[0]);
>>>     - *     do {
>>>     - *         // Something with 'terminal'.
>>>     - *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
>>>     - */
>>>     -
>>>     -/* Sets 'expr' to the first possible terminal expression. 'var'
>>>     should be the
>>>     - * first variable in the ones to be tested. */
>>>     -static void
>>>     -init_terminal(struct expr *expr, int phase,
>>>     -              const struct expr_symbol *nvars[], int n_nvars,
>>>     -              const struct expr_symbol *svars[], int n_svars)
>>>     -{
>>>     -    if (phase < 1 && n_nvars) {
>>>     -        expr->type = EXPR_T_CMP;
>>>     -        expr->cmp.symbol = nvars[0];
>>>     -        expr->cmp.relop = rightmost_1bit_idx(test_relops);
>>>     -        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
>>>     -        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
>>>     -        expr->cmp.value.integer = htonll(0);
>>>     -        expr->cmp.mask.integer = htonll(0);
>>>     -        return;
>>>     -    }
>>>     -
>>>     -    if (phase < 2 && n_svars) {
>>>     -        expr->type = EXPR_T_CMP;
>>>     -        expr->cmp.symbol = svars[0];
>>>     -        expr->cmp.relop = EXPR_R_EQ;
>>>     -        expr->cmp.string = xstrdup("0");
>>>     -        return;
>>>     -    }
>>>     -
>>>     -    expr->type = EXPR_T_BOOLEAN;
>>>     -    expr->boolean = false;
>>>     -}
>>>     -
>>>     -/* Returns 'x' with the rightmost contiguous string of 1s changed
>>>     to 0s,
>>>     - * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's
>>>     Delight_, 2nd
>>>     - * ed., section 2-1. */
>>>     -static unsigned int
>>>     -turn_off_rightmost_1s(unsigned int x)
>>>     -{
>>>     -    return ((x & -x) + x) & x;
>>>     -}
>>>     -
>>>     -static const struct expr_symbol *
>>>     -next_var(const struct expr_symbol *symbol,
>>>     -         const struct expr_symbol *vars[], int n_vars)
>>>     -{
>>>     -    for (int i = 0; i < n_vars; i++) {
>>>     -        if (symbol == vars[i]) {
>>>     -            return i + 1 >= n_vars ? NULL : vars[i + 1];
>>>     -        }
>>>     -    }
>>>     -    OVS_NOT_REACHED();
>>>     -}
>>>     -
>>>     -static enum expr_relop
>>>     -next_relop(enum expr_relop relop)
>>>     -{
>>>     -    unsigned int remaining_relops = test_relops & ~((1u << (relop
>>>     + 1)) - 1);
>>>     -    return (remaining_relops
>>>     -            ? rightmost_1bit_idx(remaining_relops)
>>>     -            : rightmost_1bit_idx(test_relops));
>>>     -}
>>>     -
>>>     -/* Advances 'expr' to the next possible terminal expression
>>>     within the 'n_vars'
>>>     - * variables of 'n_bits' bits each in 'vars[]'. */
>>>     -static bool
>>>     -next_terminal(struct expr *expr,
>>>     -              const struct expr_symbol *nvars[], int n_nvars, int
>>>     n_bits,
>>>     -              const struct expr_symbol *svars[], int n_svars)
>>>     -{
>>>     -    if (expr->type == EXPR_T_BOOLEAN) {
>>>     -        if (expr->boolean) {
>>>     -            return false;
>>>     -        } else {
>>>     -            expr->boolean = true;
>>>     -            return true;
>>>     -        }
>>>     -    }
>>>     -
>>>     -    if (!expr->cmp.symbol->width) {
>>>     -        int next_value = atoi(expr->cmp.string) + 1;
>>>     -        free(expr->cmp.string);
>>>     -        if (next_value > 1) {
>>>     -            expr->cmp.symbol = next_var(expr->cmp.symbol, svars,
>>>     n_svars);
>>>     -            if (!expr->cmp.symbol) {
>>>     -                init_terminal(expr, 2, nvars, n_nvars, svars,
>>>     n_svars);
>>>     -                return true;
>>>     -            }
>>>     -            next_value = 0;
>>>     -        }
>>>     -        expr->cmp.string = xasprintf("%d", next_value);
>>>     -        return true;
>>>     -    }
>>>     -
>>>     -    unsigned int next;
>>>     -
>>>     -    next = (ntohll(expr->cmp.value.integer)
>>>     -            + (ntohll(expr->cmp.mask.integer) << n_bits));
>>>     -    for (;;) {
>>>     -        next++;
>>>     -        unsigned m = next >> n_bits;
>>>     -        unsigned v = next & ((1u << n_bits) - 1);
>>>     -        if (next >= (1u << (2 * n_bits))) {
>>>     -            enum expr_relop old_relop = expr->cmp.relop;
>>>     -            expr->cmp.relop = next_relop(old_relop);
>>>     -            if (expr->cmp.relop <= old_relop) {
>>>     -                expr->cmp.symbol = next_var(expr->cmp.symbol,
>>>     nvars, n_nvars);
>>>     -                if (!expr->cmp.symbol) {
>>>     -                    init_terminal(expr, 1, nvars, n_nvars, svars,
>>>     n_svars);
>>>     -                    return true;
>>>     -                }
>>>     -            }
>>>     -            next = UINT_MAX;
>>>     -        } else if (v & ~m) {
>>>     -            /* Skip: 1-bits in value correspond to 0-bits in 
>>> mask. */
>>>     -        } else if ((!m || turn_off_rightmost_1s(m))
>>>     -                   && (expr->cmp.relop != EXPR_R_EQ &&
>>>     -                       expr->cmp.relop != EXPR_R_NE)) {
>>>     -            /* Skip: can't have discontiguous or all-0 mask for >
>>>     >= < <=. */
>>>     -        } else {
>>>     -            expr->cmp.value.integer = htonll(v);
>>>     -            expr->cmp.mask.integer = htonll(m);
>>>     -            return true;
>>>     -        }
>>>     -    }
>>>     -}
>>>     -
>>>     -static struct expr *
>>>     -make_terminal(struct expr ***terminalp)
>>>     -{
>>>     -    struct expr *e = expr_create_boolean(true);
>>>     -    **terminalp = e;
>>>     -    (*terminalp)++;
>>>     -    return e;
>>>     -}
>>>     -
>>>     -static struct expr *
>>>     -build_simple_tree(enum expr_type type, int n, struct expr
>>>     ***terminalp)
>>>     -{
>>>     -    if (n == 2) {
>>>     -        struct expr *e = expr_create_andor(type);
>>>     -        for (int i = 0; i < 2; i++) {
>>>     -            struct expr *sub = make_terminal(terminalp);
>>>     -            ovs_list_push_back(&e->andor, &sub->node);
>>>     -        }
>>>     -        return e;
>>>     -    } else if (n == 1) {
>>>     -        return make_terminal(terminalp);
>>>     -    } else {
>>>     -        OVS_NOT_REACHED();
>>>     -    }
>>>     -}
>>>     -
>>>     -static struct expr *
>>>     -build_tree_shape(enum expr_type type, const struct tree_shape 
>>> **tsp,
>>>     -                 struct expr ***terminalp)
>>>     -{
>>>     -    const struct tree_shape *ts = *tsp;
>>>     -    (*tsp)++;
>>>     -
>>>     -    struct expr *e = expr_create_andor(type);
>>>     -    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : 
>>> EXPR_T_AND;
>>>     -    for (int i = 0; i < ts->sn; i++) {
>>>     -        struct expr *sub = (ts->s[i] > 2
>>>     -                            ? build_tree_shape(t, tsp, terminalp)
>>>     -                            : build_simple_tree(t, ts->s[i],
>>>     terminalp));
>>>     -        ovs_list_push_back(&e->andor, &sub->node);
>>>     -    }
>>>     -    return e;
>>>     -}
>>>     -
>>>     -struct test_rule {
>>>     -    struct cls_rule cr;
>>>     -};
>>>     -
>>>     -static void
>>>     -free_rule(struct test_rule *test_rule)
>>>     -{
>>>     -    cls_rule_destroy(&test_rule->cr);
>>>     -    free(test_rule);
>>>     -}
>>>     -
>>>     -static bool
>>>     -tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
>>>     -                                  const char *port_name 
>>> OVS_UNUSED)
>>>     -{
>>>     -    return true;
>>>     -}
>>>     -
>>>     -static int
>>>     -test_tree_shape_exhaustively(struct expr *expr, struct shash 
>>> *symtab,
>>>     -                             struct expr *terminals[], int
>>>     n_terminals,
>>>     -                             const struct expr_symbol *nvars[],
>>>     int n_nvars,
>>>     -                             int n_bits,
>>>     -                             const struct expr_symbol *svars[],
>>>     int n_svars)
>>>     -{
>>>     -    int n_tested = 0;
>>>     -
>>>     -    const unsigned int var_mask = (1u << n_bits) - 1;
>>>     -    for (int i = 0; i < n_terminals; i++) {
>>>     -        init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>>     n_svars);
>>>     -    }
>>>     -
>>>     -    struct ds s = DS_EMPTY_INITIALIZER;
>>>     -    struct flow f;
>>>     -    memset(&f, 0, sizeof f);
>>>     -    for (;;) {
>>>     -        for (int i = n_terminals - 1; ; i--) {
>>>     -            if (!i) {
>>>     -                ds_destroy(&s);
>>>     -                return n_tested;
>>>     -            }
>>>     -            if (next_terminal(terminals[i], nvars, n_nvars, 
>>> n_bits,
>>>     -                              svars, n_svars)) {
>>>     -                break;
>>>  ��  -            }
>>>     -            init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>>     n_svars);
>>>     -        }
>>>     -        ovs_assert(expr_honors_invariants(expr));
>>>     -
>>>     -        n_tested++;
>>>     -
>>>     -        struct expr *modified;
>>>     -        if (operation == OP_CONVERT) {
>>>     -            ds_clear(&s);
>>>     -            expr_format(expr, &s);
>>>     -
>>>     -            char *error;
>>>     -            modified = expr_parse_string(ds_cstr(&s), symtab, 
>>> NULL,
>>>     -                                         NULL, NULL, &error);
>>>     -            if (error) {
>>>     -                fprintf(stderr, "%s fails to parse (%s)\n",
>>>     -                        ds_cstr(&s), error);
>>>     -                exit(EXIT_FAILURE);
>>>     -            }
>>>     -        } else if (operation >= OP_SIMPLIFY) {
>>>     -            modified = expr_simplify(expr_clone(expr),
>>>     -  tree_shape_is_chassis_resident_cb,
>>>     -                                     NULL);
>>>     -            ovs_assert(expr_honors_invariants(modified));
>>>     -
>>>     -            if (operation >= OP_NORMALIZE) {
>>>     -                modified = expr_normalize(modified);
>>>     - ovs_assert(expr_honors_invariants(modified));
>>>     -                ovs_assert(expr_is_normalized(modified));
>>>     -            }
>>>     -        }
>>>     -
>>>     -        struct hmap matches;
>>>     -        struct classifier cls;
>>>     -        if (operation >= OP_FLOW) {
>>>     -            struct expr_match *m;
>>>     -            struct test_rule *test_rule;
>>>     -
>>>     -            expr_to_matches(modified, lookup_atoi_cb, NULL,
>>>     &matches);
>>>     -
>>>     -            classifier_init(&cls, NULL);
>>>     -            HMAP_FOR_EACH (m, hmap_node, &matches) {
>>>     -                test_rule = xmalloc(sizeof *test_rule);
>>>     -                cls_rule_init(&test_rule->cr, &m->match, 0);
>>>     -                classifier_insert(&cls, &test_rule->cr,
>>>     OVS_VERSION_MIN,
>>>     -                                  m->conjunctions, m->n);
>>>     -            }
>>>     -        }
>>>     -        for (int subst = 0; subst < 1 << (n_bits * n_nvars +
>>>     n_svars);
>>>     -             subst++) {
>>>     -            for (int i = 0; i < n_nvars; i++) {
>>>     -                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
>>>     -            }
>>>     -            for (int i = 0; i < n_svars; i++) {
>>>     -                f.regs[n_nvars + i] = ((subst >> (n_nvars *
>>>     n_bits + i))
>>>     -                                       & 1);
>>>     -            }
>>>     -
>>>     -            bool expected = expr_evaluate(expr, &f,
>>>     lookup_atoi_cb, NULL);
>>>     -            bool actual = expr_evaluate(modified, &f,
>>>     lookup_atoi_cb, NULL);
>>>     -            if (actual != expected) {
>>>     -                struct ds expr_s, modified_s;
>>>     -
>>>     -                ds_init(&expr_s);
>>>     -                expr_format(expr, &expr_s);
>>>     -
>>>     -                ds_init(&modified_s);
>>>     -                expr_format(modified, &modified_s);
>>>     -
>>>     -                fprintf(stderr,
>>>     -                        "%s evaluates to %d, but %s evaluates to
>>>     %d, for",
>>>     -                        ds_cstr(&expr_s), expected,
>>>     -                        ds_cstr(&modified_s), actual);
>>>     -                for (int i = 0; i < n_nvars; i++) {
>>>     -                    if (i > 0) {
>>>     -                        fputs(",", stderr);
>>>     -                    }
>>>     -                    fprintf(stderr, " n%d = 0x%x", i,
>>>     -                            (subst >> (n_bits * i)) & var_mask);
>>>     -                }
>>>     -                for (int i = 0; i < n_svars; i++) {
>>>     -                    fprintf(stderr, ", s%d = \"%d\"", i,
>>>     -                            (subst >> (n_bits * n_nvars + i)) & 
>>> 1);
>>>     -                }
>>>     -                putc('\n', stderr);
>>>     -                exit(EXIT_FAILURE);
>>>     -            }
>>>     -
>>>     -            if (operation >= OP_FLOW) {
>>>     -                bool found = classifier_lookup(&cls, 
>>> OVS_VERSION_MIN,
>>>     -                                               &f, NULL) != NULL;
>>>     -                if (expected != found) {
>>>     -                    struct ds expr_s, modified_s;
>>>     -
>>>     -                    ds_init(&expr_s);
>>>     -                    expr_format(expr, &expr_s);
>>>     -
>>>     -                    ds_init(&modified_s);
>>>     -                    expr_format(modified, &modified_s);
>>>     -
>>>     -                    fprintf(stderr,
>>>     -                            "%s and %s evaluate to %d, for",
>>>     -                            ds_cstr(&expr_s),
>>>     ds_cstr(&modified_s), expected);
>>>     -                    for (int i = 0; i < n_nvars; i++) {
>>>     -                        if (i > 0) {
>>>     -                            fputs(",", stderr);
>>>     -                        }
>>>     -                        fprintf(stderr, " n%d = 0x%x", i,
>>>     -                                (subst >> (n_bits * i)) & 
>>> var_mask);
>>>     -                    }
>>>     -                    for (int i = 0; i < n_svars; i++) {
>>>     -                        fprintf(stderr, ", s%d = \"%d\"", i,
>>>     -                                (subst >> (n_bits * n_nvars + i))
>>>     & 1);
>>>     -                    }
>>>     -                    fputs(".\n", stderr);
>>>     -
>>>     -                    fprintf(stderr, "Converted to classifier:\n");
>>>     -                    expr_matches_print(&matches, stderr);
>>>     -                    fprintf(stderr,
>>>     -                            "However, %s flow was found in the
>>>     classifier.\n",
>>>     -                            found ? "a" : "no");
>>>     -                    exit(EXIT_FAILURE);
>>>     -                }
>>>     -            }
>>>     -        }
>>>     -        if (operation >= OP_FLOW) {
>>>     -            struct test_rule *test_rule;
>>>     -
>>>     -            CLS_FOR_EACH (test_rule, cr, &cls) {
>>>     -                classifier_remove_assert(&cls, &test_rule->cr);
>>>     -                ovsrcu_postpone(free_rule, test_rule);
>>>     -            }
>>>     -            classifier_destroy(&cls);
>>>     -            ovsrcu_quiesce();
>>>     -
>>>     -            expr_matches_destroy(&matches);
>>>     -        }
>>>     -        expr_destroy(modified);
>>>     -    }
>>>     -}
>>>     -
>>>     -#ifndef _WIN32
>>>     -static void
>>>     -wait_pid(pid_t *pids, int *n)
>>>     -{
>>>     -    int status;
>>>     -    pid_t pid;
>>>     -
>>>     -    pid = waitpid(-1, &status, 0);
>>>     -    if (pid < 0) {
>>>     -        ovs_fatal(errno, "waitpid failed");
>>>     -    } else if (WIFEXITED(status)) {
>>>     -        if (WEXITSTATUS(status)) {
>>>     -            exit(WEXITSTATUS(status));
>>>     -        }
>>>     -    } else if (WIFSIGNALED(status)) {
>>>     -        raise(WTERMSIG(status));
>>>     -        exit(1);
>>>     -    } else {
>>>     -        OVS_NOT_REACHED();
>>>     -    }
>>>     -
>>>     -    for (int i = 0; i < *n; i++) {
>>>     -        if (pids[i] == pid) {
>>>     -            pids[i] = pids[--*n];
>>>     -            return;
>>>     -        }
>>>     -    }
>>>     -    ovs_fatal(0, "waitpid returned unknown child");
>>>     -}
>>>     -#endif
>>>     -
>>>     -static void
>>>     -test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    int n_terminals = atoi(ctx->argv[1]);
>>>     -    struct tree_shape ts[50];
>>>     -    int n_tses;
>>>     -
>>>     -    struct shash symtab;
>>>     -    const struct expr_symbol *nvars[4];
>>>     -    const struct expr_symbol *svars[4];
>>>     -
>>>     -    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
>>>     -    ovs_assert(test_svars <= ARRAY_SIZE(svars));
>>>     -    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
>>>     -
>>>     -    shash_init(&symtab);
>>>     -    for (int i = 0; i < test_nvars; i++) {
>>>     -        char *name = xasprintf("n%d", i);
>>>     -        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0
>>>     + i, NULL,
>>>     -                                         false);
>>>     -        free(name);
>>>     -    }
>>>     -    for (int i = 0; i < test_svars; i++) {
>>>     -        char *name = xasprintf("s%d", i);
>>>     -        svars[i] = expr_symtab_add_string(&symtab, name,
>>>     -                                          MFF_REG0 + test_nvars +
>>>     i, NULL);
>>>     -        free(name);
>>>     -    }
>>>     -
>>>     -#ifndef _WIN32
>>>     -    pid_t *children = xmalloc(test_parallel * sizeof *children);
>>>     -    int n_children = 0;
>>>     -#endif
>>>     -
>>>     -    int n_tested = 0;
>>>     -    for (int i = 0; i < 2; i++) {
>>>     -        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
>>>     -
>>>     -        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
>>>     -             n_tses = next_tree_shape(ts, n_tses)) {
>>>     -            const struct tree_shape *tsp = ts;
>>>     -            struct expr *terminals[50];
>>>     -            struct expr **terminalp = terminals;
>>>     -            struct expr *expr = build_tree_shape(base_type, &tsp,
>>>     &terminalp);
>>>     -            ovs_assert(terminalp == &terminals[n_terminals]);
>>>     -
>>>     -            if (verbosity > 0) {
>>>     -                print_tree_shape(ts, n_tses);
>>>     -                printf(": ");
>>>     -                struct ds s = DS_EMPTY_INITIALIZER;
>>>     -                expr_format(expr, &s);
>>>     -                puts(ds_cstr(&s));
>>>     -                ds_destroy(&s);
>>>     -            }
>>>     -
>>>     -#ifndef _WIN32
>>>     -            if (test_parallel > 1) {
>>>     -                pid_t pid = xfork();
>>>     -                if (!pid) {
>>>     -                    test_tree_shape_exhaustively(expr, &symtab,
>>>     -  terminals,
>>>     n_terminals,
>>>     -                                                 nvars,
>>>     test_nvars, test_bits,
>>>     -                                                 svars, 
>>> test_svars);
>>>     -                    expr_destroy(expr);
>>>     -                    exit(0);
>>>     -                } else {
>>>     -                    if (n_children >= test_parallel) {
>>>     -                        wait_pid(children, &n_children);
>>>     -                    }
>>>     -                    children[n_children++] = pid;
>>>     -                }
>>>     -            } else
>>>     -#endif
>>>     -            {
>>>     -                n_tested += test_tree_shape_exhaustively(
>>>     -                    expr, &symtab, terminals, n_terminals,
>>>     -                    nvars, test_nvars, test_bits,
>>>     -                    svars, test_svars);
>>>     -            }
>>>     -            expr_destroy(expr);
>>>     -        }
>>>     -    }
>>>     -#ifndef _WIN32
>>>     -    while (n_children > 0) {
>>>     -        wait_pid(children, &n_children);
>>>     -    }
>>>     -    free(children);
>>>     -#endif
>>>     -
>>>     -    printf("Tested ");
>>>     -    switch (operation) {
>>>     -    case OP_CONVERT:
>>>     -        printf("converting");
>>>     -        break;
>>>     -    case OP_SIMPLIFY:
>>>     -        printf("simplifying");
>>>     -        break;
>>>     -    case OP_NORMALIZE:
>>>     -        printf("normalizing");
>>>     -        break;
>>>     -    case OP_FLOW:
>>>     -        printf("converting to flows");
>>>     -        break;
>>>     -    }
>>>     -    if (n_tested) {
>>>     -        printf(" %d expressions of %d terminals", n_tested,
>>>     n_terminals);
>>>     -    } else {
>>>     -        printf(" all %d-terminal expressions", n_terminals);
>>>     -    }
>>>     -    if (test_nvars || test_svars) {
>>>     -        printf(" with");
>>>     -        if (test_nvars) {
>>>     -            printf(" %d numeric vars (each %d bits) in terms of
>>>     operators",
>>>     -                   test_nvars, test_bits);
>>>     -            for (unsigned int relops = test_relops; relops;
>>>     -                 relops = zero_rightmost_1bit(relops)) {
>>>     -                enum expr_relop r = rightmost_1bit_idx(relops);
>>>     -                printf(" %s", expr_relop_to_string(r));
>>>     -            }
>>>     -        }
>>>     -        if (test_nvars && test_svars) {
>>>     -            printf (" and");
>>>     -        }
>>>     -        if (test_svars) {
>>>     -            printf(" %d string vars", test_svars);
>>>     -        }
>>>     -    } else {
>>>     -        printf(" in terms of Boolean constants only");
>>>     -    }
>>>     -    printf(".\n");
>>>     -
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    struct shash symtab;
>>>     -    struct ds input;
>>>     -
>>>     -    create_symtab(&symtab);
>>>     -
>>>     -    ds_init(&input);
>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>     -        struct flow uflow;
>>>     -        char *error = expr_parse_microflow(ds_cstr(&input),
>>>     &symtab, NULL,
>>>     -                                           NULL, lookup_atoi_cb,
>>>     NULL, &uflow);
>>>     -        if (error) {
>>>     -            puts(error);
>>>     -            free(error);
>>>     -            continue;
>>>     -        }
>>>     -
>>>     -        uint64_t packet_stub[128 / 8];
>>>     -        struct dp_packet packet;
>>>     -        dp_packet_use_stub(&packet, packet_stub, sizeof 
>>> packet_stub);
>>>     -        flow_compose(&packet, &uflow, NULL, 64);
>>>     -
>>>     -        struct ds output = DS_EMPTY_INITIALIZER;
>>>     -        const uint8_t *buf = dp_packet_data(&packet);
>>>     -        for (int i = 0; i < dp_packet_size(&packet); i++) {
>>>     -            uint8_t val = buf[i];
>>>     -            ds_put_format(&output, "%02"PRIx8, val);
>>>     -        }
>>>     -        puts(ds_cstr(&output));
>>>     -        ds_destroy(&output);
>>>     -
>>>     -        dp_packet_uninit(&packet);
>>>     -    }
>>>     -    ds_destroy(&input);
>>>     -
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -}
>>>     -
>>>     -/* Actions. */
>>>     -
>>>     -static void
>>>     -test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>     -{
>>>     -    struct shash symtab;
>>>     -    struct hmap dhcp_opts;
>>>     -    struct hmap dhcpv6_opts;
>>>     -    struct hmap nd_ra_opts;
>>>     -    struct controller_event_options event_opts;
>>>     -    struct simap ports;
>>>     -    struct ds input;
>>>     -    bool ok = true;
>>>     -
>>>     -    create_symtab(&symtab);
>>>     -    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
>>>     &event_opts);
>>>     -
>>>     -    /* Initialize group ids. */
>>>     -    struct ovn_extend_table group_table;
>>>     -    ovn_extend_table_init(&group_table);
>>>     -
>>>     -    /* Initialize meter ids for QoS. */
>>>     -    struct ovn_extend_table meter_table;
>>>     -    ovn_extend_table_init(&meter_table);
>>>     -
>>>     -    simap_init(&ports);
>>>     -    simap_put(&ports, "eth0", 5);
>>>     -    simap_put(&ports, "eth1", 6);
>>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>>     -
>>>     -    ds_init(&input);
>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>     -        struct ofpbuf ovnacts;
>>>     -        struct expr *prereqs;
>>>     -        char *error;
>>>     -
>>>     -        puts(ds_cstr(&input));
>>>     -
>>>     -        ofpbuf_init(&ovnacts, 0);
>>>     -
>>>     -        const struct ovnact_parse_params pp = {
>>>     -            .symtab = &symtab,
>>>     -            .dhcp_opts = &dhcp_opts,
>>>     -            .dhcpv6_opts = &dhcpv6_opts,
>>>     -            .nd_ra_opts = &nd_ra_opts,
>>>     -            .controller_event_opts = &event_opts,
>>>     -            .n_tables = 24,
>>>     -            .cur_ltable = 10,
>>>     -        };
>>>     -        error = ovnacts_parse_string(ds_cstr(&input), &pp,
>>>     &ovnacts, &prereqs);
>>>     -        if (!error) {
>>>     -            /* Convert the parsed representation back to a string
>>>     and print it,
>>>     -             * if it's different from the input. */
>>>     -            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
>>>     -            ovnacts_format(ovnacts.data, ovnacts.size, 
>>> &ovnacts_s);
>>>     -            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
>>>     -                printf("    formats as %s\n", 
>>> ds_cstr(&ovnacts_s));
>>>     -            }
>>>     -
>>>     -            /* Encode the actions into OpenFlow and print. */
>>>     -            const struct ovnact_encode_params ep = {
>>>     -                .lookup_port = lookup_port_cb,
>>>     -                .aux = &ports,
>>>     -                .is_switch = true,
>>>     -                .group_table = &group_table,
>>>     -                .meter_table = &meter_table,
>>>     -
>>>     -                .pipeline = OVNACT_P_INGRESS,
>>>     -                .ingress_ptable = 8,
>>>     -                .egress_ptable = 40,
>>>     -                .output_ptable = 64,
>>>     -                .mac_bind_ptable = 65,
>>>     -            };
>>>     -            struct ofpbuf ofpacts;
>>>     -            ofpbuf_init(&ofpacts, 0);
>>>     -            ovnacts_encode(ovnacts.data, ovnacts.size, &ep,
>>>     &ofpacts);
>>>     -            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
>>>     -            struct ofpact_format_params fp = { .s = &ofpacts_s };
>>>     -            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
>>>     -            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
>>>     -            ds_destroy(&ofpacts_s);
>>>     -            ofpbuf_uninit(&ofpacts);
>>>     -
>>>     -            /* Print prerequisites if any. */
>>>     -            if (prereqs) {
>>>     -                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
>>>     -                expr_format(prereqs, &prereqs_s);
>>>     -                printf("    has prereqs %s\n", 
>>> ds_cstr(&prereqs_s));
>>>     -                ds_destroy(&prereqs_s);
>>>     -            }
>>>     -
>>>     -            /* Now re-parse and re-format the string to verify
>>>     that it's
>>>     -             * round-trippable. */
>>>     -            struct ofpbuf ovnacts2;
>>>     -            struct expr *prereqs2;
>>>     -            ofpbuf_init(&ovnacts2, 0);
>>>     -            error = ovnacts_parse_string(ds_cstr(&ovnacts_s),
>>>     &pp, &ovnacts2,
>>>     -                                         &prereqs2);
>>>     -            if (!error) {
>>>     -                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
>>>     -                ovnacts_format(ovnacts2.data, ovnacts2.size,
>>>     &ovnacts2_s);
>>>     -                if (strcmp(ds_cstr(&ovnacts_s),
>>>     ds_cstr(&ovnacts2_s))) {
>>>     -                    printf("    bad reformat: %s\n",
>>>     ds_cstr(&ovnacts2_s));
>>>     -                    ok = false;
>>>     -                }
>>>     -                ds_destroy(&ovnacts2_s);
>>>     -            } else {
>>>     -                printf("    reparse error: %s\n", error);
>>>     -                free(error);
>>>     -                ok = false;
>>>     -            }
>>>     -            expr_destroy(prereqs2);
>>>     -
>>>     -            ovnacts_free(ovnacts2.data, ovnacts2.size);
>>>     -            ofpbuf_uninit(&ovnacts2);
>>>     -            ds_destroy(&ovnacts_s);
>>>     -        } else {
>>>     -            printf("    %s\n", error);
>>>     -            free(error);
>>>     -        }
>>>     -
>>>     -        expr_destroy(prereqs);
>>>     -        ovnacts_free(ovnacts.data, ovnacts.size);
>>>     -        ofpbuf_uninit(&ovnacts);
>>>     -    }
>>>     -    ds_destroy(&input);
>>>     -
>>>     -    simap_destroy(&ports);
>>>     -    expr_symtab_destroy(&symtab);
>>>     -    shash_destroy(&symtab);
>>>     -    dhcp_opts_destroy(&dhcp_opts);
>>>     -    dhcp_opts_destroy(&dhcpv6_opts);
>>>     -    nd_ra_opts_destroy(&nd_ra_opts);
>>>     -    controller_event_opts_destroy(&event_opts);
>>>     -    ovn_extend_table_destroy(&group_table);
>>>     -    ovn_extend_table_destroy(&meter_table);
>>>     -    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
>>>     -}
>>>     -
>>>     -static unsigned int
>>>     -parse_relops(const char *s)
>>>     -{
>>>     -    unsigned int relops = 0;
>>>     -    struct lexer lexer;
>>>     -
>>>     -    lexer_init(&lexer, s);
>>>     -    lexer_get(&lexer);
>>>     -    do {
>>>     -        enum expr_relop relop;
>>>     -
>>>     -        if (expr_relop_from_token(lexer.token.type, &relop)) {
>>>     -            relops |= 1u << relop;
>>>     -            lexer_get(&lexer);
>>>     -        } else {
>>>     -            ovs_fatal(0, "%s: relational operator expected at
>>>     `%.*s'",
>>>     -                      s, (int) (lexer.input - lexer.start),
>>>     lexer.start);
>>>     -        }
>>>     -        lexer_match(&lexer, LEX_T_COMMA);
>>>     -    } while (lexer.token.type != LEX_T_END);
>>>     -    lexer_destroy(&lexer);
>>>     -
>>>     -    return relops;
>>>     -}
>>>     -
>>>     -static void
>>>     -usage(void)
>>>     -{
>>>     -    printf("\
>>>     -%s: OVN test utility\n\
>>>     -usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
>>>     -\n\
>>>     -lex\n\
>>>     -  Lexically analyzes OVN input from stdin and print them back on
>>>     stdout.\n\
>>>     -\n\
>>>     -parse-expr\n\
>>>     -annotate-expr\n\
>>>     -simplify-expr\n\
>>>     -normalize-expr\n\
>>>     -expr-to-flows\n\
>>>     -  Parses OVN expressions from stdin and prints them back on
>>>     stdout after\n\
>>>     -  differing degrees of analysis.  Available fields are based on
>>>     packet\n\
>>>     -  headers.\n\
>>>     -\n\
>>>     -expr-to-packets\n\
>>>     -  Parses OVN expressions from stdin and prints out matching
>>>     packets in\n\
>>>     -  hexadecimal on stdout.\n\
>>>     -\n\
>>>     -evaluate-expr MICROFLOW\n\
>>>     -  Parses OVN expressions from stdin and evaluates them against
>>>     the flow\n\
>>>     -  specified in MICROFLOW, which must be an expression that
>>>     constrains\n\
>>>     -  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with
>>>     source\n\
>>>     -  port 80, and prints the results on stdout, either 1 for true or
>>>     0 for\n\
>>>     -  false.  Use quoted integers, e.g. \"123\", for string fields.\n\
>>>     -\n\
>>>     -  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type
>>>     == 0x800\"\n\
>>>     -  evaluates to true, \"udp\" evaluates to false, and \"udp ||
>>>     tcp\"\n\
>>>     -  evaluates to true.\n\
>>>     -\n\
>>>     -composition N\n\
>>>     -  Prints all the compositions of N on stdout.\n\
>>>     -\n\
>>>     -tree-shape N\n\
>>>     -  Prints all the tree shapes with N terminals on stdout.\n\
>>>     -\n\
>>>     -exhaustive N\n\
>>>     -  Tests that all possible Boolean expressions with N terminals
>>>     are properly\n\
>>>     -  simplified, normalized, and converted to flows. Available
>>>     options:\n\
>>>     -   Overall options:\n\
>>>     -    --operation=OPERATION  Operation to test, one of: convert,
>>>     simplify,\n\
>>>     -        normalize, flow.  Default: flow.  'normalize' includes
>>>     'simplify',\n\
>>>     -        'flow' includes 'simplify' and 'normalize'.\n\
>>>     -    --parallel=N  Number of processes to use in parallel, default
>>>     1.\n\
>>>     -   Numeric vars:\n\
>>>     -    --nvars=N  Number of numeric vars to test, in range 0...4,
>>>     default 2.\n\
>>>     -    --bits=N  Number of bits per variable, in range 1...3,
>>>     default 3.\n\
>>>     -    --relops=OPERATORS   Test only the specified Boolean
>>>     operators.\n\
>>>     -                         OPERATORS may include == != < <= > >=,
>>>     space or\n\
>>>     -                         comma separated.  Default is all
>>>     operators.\n\
>>>     -   String vars:\n\
>>>     -    --svars=N  Number of string vars to test, in range 0...4,
>>>     default 2.\n\
>>>     -\n\
>>>     -parse-actions\n\
>>>     -  Parses OVN actions from stdin and prints the equivalent
>>>     OpenFlow actions\n\
>>>     -  on stdout.\n\
>>>     -",
>>>     -           program_name, program_name);
>>>     -    exit(EXIT_SUCCESS);
>>>     -}
>>>     -
>>>     -static void
>>>     -test_ovn_main(int argc, char *argv[])
>>>     -{
>>>     -    enum {
>>>     -        OPT_RELOPS = UCHAR_MAX + 1,
>>>     -        OPT_NVARS,
>>>     -        OPT_SVARS,
>>>     -        OPT_BITS,
>>>     -        OPT_OPERATION,
>>>     -        OPT_PARALLEL
>>>     -    };
>>>     -    static const struct option long_options[] = {
>>>     -        {"relops", required_argument, NULL, OPT_RELOPS},
>>>     -        {"nvars", required_argument, NULL, OPT_NVARS},
>>>     -        {"svars", required_argument, NULL, OPT_SVARS},
>>>     -        {"bits", required_argument, NULL, OPT_BITS},
>>>     -        {"operation", required_argument, NULL, OPT_OPERATION},
>>>     -        {"parallel", required_argument, NULL, OPT_PARALLEL},
>>>     -        {"more", no_argument, NULL, 'm'},
>>>     -        {"help", no_argument, NULL, 'h'},
>>>     -        {NULL, 0, NULL, 0},
>>>     -    };
>>>     -    char *short_options =
>>>     ovs_cmdl_long_options_to_short_options(long_options);
>>>     -
>>>     -    set_program_name(argv[0]);
>>>     -
>>>     -    test_relops = parse_relops("== != < <= > >=");
>>>     -    for (;;) {
>>>     -        int option_index = 0;
>>>     -        int c = getopt_long (argc, argv, short_options, 
>>> long_options,
>>>     -                             &option_index);
>>>     -
>>>     -        if (c == -1) {
>>>     -            break;
>>>     -        }
>>>     -        switch (c) {
>>>     -        case OPT_RELOPS:
>>>     -            test_relops = parse_relops(optarg);
>>>     -            break;
>>>     -
>>>     -        case OPT_NVARS:
>>>     -            test_nvars = atoi(optarg);
>>>     -            if (test_nvars < 0 || test_nvars > 4) {
>>>     -                ovs_fatal(0, "number of numeric variables must 
>>> be "
>>>     -                          "between 0 and 4");
>>>     -            }
>>>     -            break;
>>>     -
>>>     -        case OPT_SVARS:
>>>     -            test_svars = atoi(optarg);
>>>     -            if (test_svars < 0 || test_svars > 4) {
>>>     -                ovs_fatal(0, "number of string variables must be "
>>>     -                          "between 0 and 4");
>>>     -            }
>>>     -            break;
>>>     -
>>>     -        case OPT_BITS:
>>>     -            test_bits = atoi(optarg);
>>>     -            if (test_bits < 1 || test_bits > 3) {
>>>     -                ovs_fatal(0, "number of bits must be between 1
>>>     and 3");
>>>     -            }
>>>     -            break;
>>>     -
>>>     -        case OPT_OPERATION:
>>>     -            if (!strcmp(optarg, "convert")) {
>>>     -                operation = OP_CONVERT;
>>>     -            } else if (!strcmp(optarg, "simplify")) {
>>>     -                operation = OP_SIMPLIFY;
>>>     -            } else if (!strcmp(optarg, "normalize")) {
>>>     -                operation = OP_NORMALIZE;
>>>     -            } else if (!strcmp(optarg, "flow")) {
>>>     -                operation = OP_FLOW;
>>>     -            } else {
>>>     -                ovs_fatal(0, "%s: unknown operation", optarg);
>>>     -            }
>>>     -            break;
>>>     -
>>>     -        case OPT_PARALLEL:
>>>     -            test_parallel = atoi(optarg);
>>>     -            break;
>>>     -
>>>     -        case 'm':
>>>     -            verbosity++;
>>>     -            break;
>>>     -
>>>     -        case 'h':
>>>     -            usage();
>>>     -            /* fall through */
>>>     -
>>>     -        case '?':
>>>     -            exit(1);
>>>     -
>>>     -        default:
>>>     -            abort();
>>>     -        }
>>>     -    }
>>>     -    free(short_options);
>>>     -
>>>     -    static const struct ovs_cmdl_command commands[] = {
>>>     -        /* Lexer. */
>>>     -        {"lex", NULL, 0, 0, test_lex, OVS_RO},
>>>     -
>>>     -        /* Symbol table. */
>>>     -        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
>>>     -
>>>     -        /* Expressions. */
>>>     -        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
>>>     -        {"annotate-expr", NULL, 0, 0, test_annotate_expr, OVS_RO},
>>>     -        {"simplify-expr", NULL, 0, 0, test_simplify_expr, OVS_RO},
>>>     -        {"normalize-expr", NULL, 0, 0, test_normalize_expr, 
>>> OVS_RO},
>>>     -        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, OVS_RO},
>>>     -        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, OVS_RO},
>>>     -        {"composition", NULL, 1, 1, test_composition, OVS_RO},
>>>     -        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
>>>     -        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
>>>     -        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets,
>>>     OVS_RO},
>>>     -
>>>     -        /* Actions. */
>>>     -        {"parse-actions", NULL, 0, 0, test_parse_actions, OVS_RO},
>>>     -
>>>     -        {NULL, NULL, 0, 0, NULL, OVS_RO},
>>>     -    };
>>>     -    struct ovs_cmdl_context ctx;
>>>     -    ctx.argc = argc - optind;
>>>     -    ctx.argv = argv + optind;
>>>     -    ovs_cmdl_run_command(&ctx, commands);
>>>     -}
>>>     -
>>>     -OVSTEST_REGISTER("test-ovn", test_ovn_main);
>>>     diff --git a/tests/testsuite.at <http://testsuite.at>
>>>     b/tests/testsuite.at <http://testsuite.at>
>>>     index 4d5e816..e759123 100644
>>>     --- a/tests/testsuite.at <http://testsuite.at>
>>>     +++ b/tests/testsuite.at <http://testsuite.at>
>>>     @@ -19,7 +19,6 @@ m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
>>>      m4_include([tests/ovs-macros.at <http://ovs-macros.at>])
>>>      m4_include([tests/ovsdb-macros.at <http://ovsdb-macros.at>])
>>>      m4_include([tests/ofproto-macros.at <http://ofproto-macros.at>])
>>>     -m4_include([tests/ovn-macros.at <http://ovn-macros.at>])
>>>
>>>      m4_include([tests/completion.at <http://completion.at>])
>>>      m4_include([tests/checkpatch.at <http://checkpatch.at>])
>>>     @@ -74,13 +73,6 @@ m4_include([tests/rstp.at <http://rstp.at>])
>>>      m4_include([tests/vlog.at <http://vlog.at>])
>>>      m4_include([tests/vtep-ctl.at <http://vtep-ctl.at>])
>>>      m4_include([tests/auto-attach.at <http://auto-attach.at>])
>>>     -m4_include([tests/ovn.at <http://ovn.at>])
>>>     -m4_include([tests/ovn-northd.at <http://ovn-northd.at>])
>>>     -m4_include([tests/ovn-nbctl.at <http://ovn-nbctl.at>])
>>>     -m4_include([tests/ovn-sbctl.at <http://ovn-sbctl.at>])
>>>     -m4_include([tests/ovn-controller.at <http://ovn-controller.at>])
>>>     -m4_include([tests/ovn-controller-vtep.at
>>>     <http://ovn-controller-vtep.at>])
>>>      m4_include([tests/mcast-snooping.at <http://mcast-snooping.at>])
>>>      m4_include([tests/packet-type-aware.at
>>>     <http://packet-type-aware.at>])
>>>      m4_include([tests/nsh.at <http://nsh.at>])
>>>     -m4_include([tests/ovn-performance.at <http://ovn-performance.at>])
>>>     --     1.8.3.1
>>>
>>>     _______________________________________________
>>>     dev mailing list
>>>     dev@openvswitch.org <mailto:dev@openvswitch.org>
>>>     https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Gregory Rose Sept. 9, 2019, 4:30 p.m. UTC | #5
On 9/7/2019 10:18 PM, Gregory Rose wrote:
>
> On 9/6/2019 12:10 PM, Mark Michelson wrote:
>> On 9/5/19 5:30 PM, Gregory Rose wrote:
>>>
>>> On 9/5/2019 12:00 PM, Numan Siddique wrote:
>>>>
>>>> [snip]
>>>> Hi Greg,
>>>>
>>>> This seems reasonable to me. Mark has already submitted a patch to 
>>>> delete
>>>> the OVN folder. But we may have to keep ovn-nbctl/ovn-sbctl utilities
>>>> and OVN schema files for ovsdb-server RAFT tests.
>>>>
>>>> Until that patch is merged, this seems fine to me.
>>>
>>> I should have a look at Mark's patch - this work probably needs 
>>> integration
>>> with that.
>>
>> FYI, I've just submitted a new version of that patch[1]. The version 
>> keeps the ovn-nbctl and ovn-sbctl utilities for the ovsdb-clustering 
>> tests. However, all other OVN tests have been removed. Like Numan was
>> suggesting, this may be a problem that requires fixing in the OVN repo.
>>
>> [1] http://patchwork.ozlabs.org/patch/1159033/
>
> Yep, I saw that.  There's a lot of overlap between my RFC and your 
> patch - I'll review and test your patch
> and then integrate with that.  Then we can work from there.

In fact, your patch fully supersedes my patch.  There's no need for this 
RFC patch or followup.

Thanks!

- Greg

>
> Thanks!
>
> - Greg
>
>>
>>>
>>>>
>>>> Can you please provide the steps you use to run the system tests ?
>>>> I will try to run in the new ovn repo and see if we see failures 
>>>> there.
>>>> I tried sometime back and all the tests fail for me. Probably I wasn't
>>>> running as expected.
>>>
>>> Build OVS using the '--with-linux=/lib/modules/$(uname -r)/build 
>>> --enable-Werror'
>>> to get the kernel datapath and then in the directory where you built 
>>> OVS run this
>>> command:
>>>
>>> 'sudo make check-kmod'
>>>
>>> To only run the ovn tests:
>>>
>>> 'sudo make check-kmod TESTSUITEFLAGS="-k ovn"'
>>>
>>> Thanks!
>>>
>>> - Greg
>>>
>>>>     ---
>>>>      tests/automake.mk <http://automake.mk>         | 23 +-
>>>>      tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at> |
>>>>      467 --
>>>>      tests/ovn-controller.at <http://ovn-controller.at>     |   294 -
>>>>      tests/ovn-macros.at <http://ovn-macros.at> |  180 -
>>>>      tests/ovn-nbctl.at <http://ovn-nbctl.at>        | 1660 -----
>>>>      tests/ovn-northd.at <http://ovn-northd.at> |  900 ---
>>>>      tests/ovn-performance.at <http://ovn-performance.at>    |  
>>>>  424 --
>>>>      tests/ovn-sbctl.at <http://ovn-sbctl.at>        |  150 -
>>>>      tests/ovn.at <http://ovn.at>        | 14702
>>>>     -----------------------------------------
>>>>      tests/system-ovn.at <http://system-ovn.at> | 1667 -----
>>>>      tests/test-ovn.c             |  1584 -----
>>>>      tests/testsuite.at <http://testsuite.at>        |    8 -
>>>>      12 files changed, 4 insertions(+), 22055 deletions(-)
>>>>      delete mode 100644 tests/ovn-controller-vtep.at
>>>>     <http://ovn-controller-vtep.at>
>>>>      delete mode 100644 tests/ovn-controller.at 
>>>> <http://ovn-controller.at>
>>>>      delete mode 100644 tests/ovn-macros.at <http://ovn-macros.at>
>>>>      delete mode 100644 tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>>      delete mode 100644 tests/ovn-northd.at <http://ovn-northd.at>
>>>>      delete mode 100644 tests/ovn-performance.at
>>>>     <http://ovn-performance.at>
>>>>      delete mode 100644 tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>>      delete mode 100644 tests/ovn.at <http://ovn.at>
>>>>      delete mode 100644 tests/system-ovn.at <http://system-ovn.at>
>>>>      delete mode 100644 tests/test-ovn.c
>>>>
>>>>     diff --git a/tests/automake.mk <http://automake.mk>
>>>>     b/tests/automake.mk <http://automake.mk>
>>>>     index d6ab517..decca46 100644
>>>>     --- a/tests/automake.mk <http://automake.mk>
>>>>     +++ b/tests/automake.mk <http://automake.mk>
>>>>     @@ -23,8 +23,7 @@ EXTRA_DIST += \
>>>>      COMMON_MACROS_AT = \
>>>>             tests/ovsdb-macros.at <http://ovsdb-macros.at> \
>>>>             tests/ovs-macros.at <http://ovs-macros.at> \
>>>>     -       tests/ofproto-macros.at <http://ofproto-macros.at> \
>>>>     -       tests/ovn-macros.at <http://ovn-macros.at>
>>>>     +       tests/ofproto-macros.at <http://ofproto-macros.at>
>>>>
>>>>      TESTSUITE_AT = \
>>>>             tests/testsuite.at <http://testsuite.at> \
>>>>     @@ -104,16 +103,9 @@ TESTSUITE_AT = \
>>>>             tests/vlog.at <http://vlog.at> \
>>>>             tests/vtep-ctl.at <http://vtep-ctl.at> \
>>>>             tests/auto-attach.at <http://auto-attach.at> \
>>>>     -       tests/ovn.at <http://ovn.at> \
>>>>     -       tests/ovn-northd.at <http://ovn-northd.at> \
>>>>     -       tests/ovn-nbctl.at <http://ovn-nbctl.at> \
>>>>     -       tests/ovn-sbctl.at <http://ovn-sbctl.at> \
>>>>     -       tests/ovn-controller.at <http://ovn-controller.at> \
>>>>     -       tests/ovn-controller-vtep.at 
>>>> <http://ovn-controller-vtep.at> \
>>>>             tests/mcast-snooping.at <http://mcast-snooping.at> \
>>>>             tests/packet-type-aware.at <http://packet-type-aware.at> \
>>>>     -       tests/nsh.at <http://nsh.at> \
>>>>     -       tests/ovn-performance.at <http://ovn-performance.at>
>>>>     +       tests/nsh.at <http://nsh.at>
>>>>
>>>>      EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
>>>>      FUZZ_REGRESSION_TESTS = \
>>>>     @@ -158,7 +150,6 @@ SYSTEM_KMOD_TESTSUITE_AT = \
>>>>
>>>>      SYSTEM_USERSPACE_TESTSUITE_AT = \
>>>>             tests/system-userspace-testsuite.at
>>>>     <http://system-userspace-testsuite.at> \
>>>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>>>             tests/system-userspace-macros.at
>>>>     <http://system-userspace-macros.at> \
>>>>             tests/system-userspace-packet-type-aware.at
>>>>     <http://system-userspace-packet-type-aware.at>
>>>>
>>>>     @@ -169,7 +160,6 @@ SYSTEM_AFXDP_TESTSUITE_AT = \
>>>>
>>>>      SYSTEM_TESTSUITE_AT = \
>>>>             tests/system-common-macros.at
>>>>     <http://system-common-macros.at> \
>>>>     -       tests/system-ovn.at <http://system-ovn.at> \
>>>>             tests/system-layer3-tunnels.at
>>>>     <http://system-layer3-tunnels.at> \
>>>>             tests/system-traffic.at <http://system-traffic.at> \
>>>>             tests/system-interface.at <http://system-interface.at>
>>>>     @@ -197,7 +187,7 @@ SYSTEM_DPDK_TESTSUITE =
>>>>     $(srcdir)/tests/system-dpdk-testsuite
>>>>      OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
>>>>      DISTCLEANFILES += tests/atconfig tests/atlocal
>>>>
>>>>     -AUTOTEST_PATH =
>>>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller 
>>>>
>>>>     +AUTOTEST_PATH =
>>>> utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR) 
>>>>
>>>>
>>>>      check-local:
>>>>             set $(SHELL) '$(TESTSUITE)' -C tests
>>>>     AUTOTEST_PATH=$(AUTOTEST_PATH); \
>>>>     @@ -238,10 +228,6 @@ check-lcov: all $(check_DATA) clean-lcov
>>>>      # valgrind support
>>>>
>>>>      valgrind_wrappers = \
>>>>     -       tests/valgrind/ovn-controller \
>>>>     -       tests/valgrind/ovn-nbctl \
>>>>     -       tests/valgrind/ovn-northd \
>>>>     -       tests/valgrind/ovn-sbctl \
>>>>             tests/valgrind/ovs-appctl \
>>>>             tests/valgrind/ovs-ofctl \
>>>>             tests/valgrind/ovs-vsctl \
>>>>     @@ -446,7 +432,6 @@ tests_ovstest_SOURCES = \
>>>>             tests/test-netflow.c \
>>>>             tests/test-odp.c \
>>>>             tests/test-ofpbuf.c \
>>>>     -       tests/test-ovn.c \
>>>>             tests/test-packets.c \
>>>>             tests/test-random.c \
>>>>             tests/test-rcu.c \
>>>>     @@ -474,7 +459,7 @@ tests_ovstest_SOURCES += \
>>>>             tests/test-netlink-conntrack.c
>>>>      endif
>>>>
>>>>     -tests_ovstest_LDADD = lib/libopenvswitch.la
>>>>     <http://libopenvswitch.la> ovn/lib/libovn.la <http://libovn.la>
>>>>     +tests_ovstest_LDADD = lib/libopenvswitch.la
>>>>     <http://libopenvswitch.la>
>>>>
>>>>      noinst_PROGRAMS += tests/test-stream
>>>>      tests_test_stream_SOURCES = tests/test-stream.c
>>>>     diff --git a/tests/ovn-controller-vtep.at
>>>>     <http://ovn-controller-vtep.at> b/tests/ovn-controller-vtep.at
>>>>     <http://ovn-controller-vtep.at>
>>>>     deleted file mode 100644
>>>>     index a3fe8cb..0000000
>>>>     --- a/tests/ovn-controller-vtep.at <http://ovn-controller-vtep.at>
>>>>     +++ /dev/null
>>>>     @@ -1,467 +0,0 @@
>>>>     -AT_BANNER([ovn_controller_vtep])
>>>>     -
>>>>     -# OVN_CONTROLLER_VTEP_START
>>>>     -#
>>>>     -# Starts the test with a setup with vtep device.  Each test case
>>>>     must first
>>>>     -# call this macro.
>>>>     -#
>>>>     -# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two
>>>>     physical ports
>>>>     -# 'p0', 'p1'.
>>>>     -#
>>>>     -# Configures ovn-nb with a logical switch 'br-test'.
>>>>     -#
>>>>     -#
>>>>     -m4_define([OVN_CONTROLLER_VTEP_START],
>>>>     -  [
>>>>     -   AT_KEYWORDS([ovn])
>>>>     -   # this will cause skip when 'make check' using Windows setup.
>>>>     -   AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -
>>>>     -   dnl Create databases (ovn-nb, ovn-sb, vtep).
>>>>     -   AT_CHECK([ovsdb-tool create vswitchd.db
>>>>     $abs_top_srcdir/vswitchd/vswitch.ovsschema])
>>>>     -   for daemon in ovn-nb ovn-sb vtep; do
>>>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>>>     -   done
>>>>     -
>>>>     -   dnl Start ovsdb-server.
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>>>     --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db
>>>>     vtep.db], [0], [], [stderr])
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>>     --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log
>>>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>>>     [stderr])
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>>     --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log
>>>>     --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db],
>>>>     [0], [], [stderr])
>>>>     -   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid`
>>>>     `cat ovsdb-sb-server.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d
>>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>>     -
>>>>     -   dnl Start ovs-vswitchd.
>>>>     -   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system
>>>>     --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif],
>>>>     [0], [], [stderr])
>>>>     -   AT_CAPTURE_FILE([ovs-vswitchd.log])
>>>>     -   on_exit "kill `cat ovs-vswitchd.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/ovs_numa|INFO|Discovered /d
>>>>     -/vlog|INFO|opened log file/d
>>>>     -/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
>>>>     -/reconnect|INFO|/d
>>>>     -/ofproto|INFO|using datapath ID/d
>>>>     -/netlink_socket|INFO|netlink: could not enable listening to all
>>>>     nsid/d
>>>>     -/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
>>>>     -   AT_CHECK([ovs-vsctl -- add-br br-vtep \
>>>>     -              -- set bridge br-vtep datapath-type=dummy
>>>>     other-config:datapath-id=fedcba9876543210
>>>>     other-config:hwaddr=aa:55:aa:55:00:00
>>>> protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] 
>>>>
>>>>     fail-mode=secure \
>>>>     -              -- add-port br-vtep p0 -- set Interface p0
>>>>     type=dummy ofport_request=1 \
>>>>     -              -- add-port br-vtep p1 -- set Interface p1
>>>>     type=dummy ofport_request=2])
>>>>     -
>>>>     -   dnl Start ovs-vtep.
>>>>     -   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch
>>>>     br-vtep tunnel_ips=1.2.3.4])
>>>>     -   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log
>>>>     --pidfile=ovs-vtep.pid --detach --no-chdir br-vtep \], [0], [],
>>>>     [stderr])
>>>>     -   on_exit "kill `cat ovs-vtep.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d']])
>>>>     -   # waits until ovs-vtep starts up.
>>>>     -   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep 
>>>> Physical_Port`"])
>>>>     -
>>>>     -   dnl Start ovn-northd.
>>>>     -   AT_CHECK([ovn-nbctl ls-add br-test])
>>>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile
>>>>     --log-file], [0], [], [stderr])
>>>>     -   on_exit "kill `cat ovn-northd.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d']])
>>>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>>>     -
>>>>     -   dnl Start ovn-controllger-vtep.
>>>>     -   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile
>>>>     --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock
>>>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>>>     -   AT_CAPTURE_FILE([ovn-controller-vtep.log])
>>>>     -   on_exit "kill `cat ovn-controller-vtep.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d
>>>>     -/reconnect|INFO|/d']])
>>>>     -])
>>>>     -
>>>>     -# OVN_CONTROLLER_VTEP_STOP
>>>>     -#
>>>>     -# So many exits... Yeah, we started a lot daemons~
>>>>     -#
>>>>     -m4_define([OVN_CONTROLLER_VTEP_STOP],
>>>>     -  [AT_CHECK([check_logs "$1"])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
>>>>     -
>>>>     -# Adds logical port for a vtep gateway chassis in ovn-nb 
>>>> database.
>>>>     -#
>>>>     -# $1: logical switch name in ovn-nb database
>>>>     -# $2: logical port name
>>>>     -# $3: physical vtep gateway name
>>>>     -# $4: logical switch name on vtep gateway chassis
>>>>     -m4_define([OVN_NB_ADD_VTEP_PORT], [
>>>>     -AT_CHECK([ovn-nbctl lsp-add $1 $2])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3
>>>>     vtep-logical-switch=$4])
>>>>     -])
>>>>     -
>>>>     -##############################################
>>>>     -
>>>>     -# tests chassis related updates.
>>>>     -AT_SETUP([ovn-controller-vtep - chassis])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# verifies the initial ovn-sb db configuration.
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
>>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>>     -Chassis br-vtep
>>>>     -    Encap vxlan
>>>>     -        ip: "1.2.3.4"
>>>>     -        options: {csum="false"}
>>>>     -])
>>>>     -
>>>>     -# deletes the chassis via ovn-sbctl and check that it is 
>>>> readded back
>>>>     -# with the log.
>>>>     -AT_CHECK([ovn-sbctl chassis-del br-vtep])
>>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>>     ovn-controller-vtep.log], [0], [dnl
>>>>     -|WARN|Chassis for VTEP physical switch (br-vtep) disappears,
>>>>     maybe deleted by ovn-sbctl, adding it back
>>>>     -])
>>>>     -
>>>>     -# changes the tunnel_ip on physical switch, watches the update of
>>>>     chassis's
>>>>     -# encap.
>>>>     -AT_CHECK([vtep-ctl set Physical_Switch br-vtep 
>>>> tunnel_ips=1.2.3.5])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr
>>>>     -d ' '], [0], [dnl
>>>>     -"1.2.3.5"
>>>>     -])
>>>>     -
>>>>     -# adds vlan_bindings to physical ports.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1
>>>>     300 lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>>>     lswitch0`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>>     -[[lswitch0]]
>>>>     -])
>>>>     -
>>>>     -# adds another logical switch and new vlan_bindings.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300
>>>>     lswitch1])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep --
>>>>     lswitch1`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -[[lswitch0,lswitch1]]
>>>>     -])
>>>>     -
>>>>     -# unbinds one port from lswitch0, nothing should change.
>>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list
>>>>     physical_port p0 | grep -- '200='`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>>     -[[lswitch0,lswitch1]]
>>>>     -])
>>>>     -
>>>>     -# unbinds all ports from lswitch0.
>>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep
>>>>     p1 300])
>>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>>     br-vtep_lswitch0`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>>     | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
>>>>     -[[lswitch1]]
>>>>     -])
>>>>     -
>>>>     -# unbinds all ports from lswitch1.
>>>>     -AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
>>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>>     br-vtep_lswitch1`"])
>>>>     -AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis
>>>>     | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -[[]]
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch
>>>>     (br-vtep) disappears/d])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -# Tests binding updates.
>>>>     -AT_SETUP([ovn-controller-vtep - binding 1])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
>>>>     -# adds logical switch port in ovn-nb database, and sets the type
>>>>     and options.
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>>     [lswitch0])
>>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>>     chassis!='[[]]'
>>>>     -# should see one binding, associated to chassis of 'br-vtep'.
>>>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>>>     cut -d ':' -f2 | tr -d ' ')
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -${chassis_uuid}
>>>>     -])
>>>>     -
>>>>     -# adds another logical switch 'lswitch1' and vlan_bindings.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>>>     lswitch1])
>>>>     -# adds logical switch port in ovn-nb database for lswitch1.
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep],
>>>>     [lswitch1])
>>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1
>>>>     chassis!='[[]]'
>>>>     -# This is allowed, but not recommended, to have two vlan_bindings
>>>>     (to different vtep logical switches)
>>>>     -# from one vtep gateway physical port in one ovn-nb logical 
>>>> swithch.
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>>>     -
>>>>     -${chassis_uuid}
>>>>     -${chassis_uuid}
>>>>     -])
>>>>     -
>>>>     -# adds another logical switch port in ovn-nb database for 
>>>> lswitch0.
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup],
>>>>     [br-vtep], [lswitch0])
>>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding
>>>>     br-vtep_lswitch0_dup chassis!='[[]]'
>>>>     -# it is not allowed to have more than one ovn-nb logical port for
>>>>     the same
>>>>     -# vtep logical switch on a vtep gateway chassis, so should still
>>>>     see only
>>>>     -# two port_binding entries bound.
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>>     | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
>>>>     -
>>>>     -
>>>>     -[[]]
>>>>     -${chassis_uuid}
>>>>     -${chassis_uuid}
>>>>     -])
>>>>     -# confirms the warning log.
>>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>>     ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g'
>>>>     | uniq], [0], [dnl
>>>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>>>     been associated with logical port (), ignore logical port ()
>>>>     -])
>>>>     -
>>>>     -# deletes physical ports from vtep.
>>>>     -AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
>>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep --
>>>>     br-vtep_lswitch`"])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
>>>>     -# should see empty chassis column in both binding entries.
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>>     | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
>>>>     -
>>>>     -
>>>>     -[[]]
>>>>     -[[]]
>>>>     -[[]]
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>>>     logical port/d])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -# Tests corner case: Binding the vtep logical switch from two
>>>>     different
>>>>     -# datapath.
>>>>     -AT_SETUP([ovn-controller-vtep - binding 2])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# adds logical switch 'lswitch0' and vlan_bindings.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0])
>>>>     -# adds logical switch port in ovn-nb database, and sets the type
>>>>     and options.
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>>     [lswitch0])
>>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>>     chassis!='[[]]'
>>>>     -
>>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>>>     p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
>>>>     -# adds a conflicting logical port (both br-vtep_lswitch0 and
>>>>     br-vtep-void_lswitch0
>>>>     -# are bound to the same logical switch, but they are on different
>>>>     datapath).
>>>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0],
>>>>     [br-vtep-void], [lswitch0])
>>>>     -ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
>>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>>     -# confirms the warning log.
>>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>>     ovn-controller-vtep.log | sed
>>>>     's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key
>>>>     [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
>>>>     -|WARN|logical switch (), on vtep gateway chassis () has already
>>>>     been associated with logical datapath (), ignore logical port ()
>>>>     which belongs to logical datapath ()
>>>>     -])
>>>>     -
>>>>     -# then deletes 'br-void' and 'br-vtep-void', should see
>>>>     'br-vtep_lswitch0'
>>>>     -# bound correctly.
>>>>     -AT_CHECK([ovn-nbctl ls-del br-void])
>>>>     -# adds another vtep pswitch 'br-vtep-void' in vtep database.
>>>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep
>>>>     br-vtep-void_lswitch0`"])
>>>>     -chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep |
>>>>     cut -d ':' -f2 | tr -d ' ')
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding
>>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -${chassis_uuid}
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been associated with
>>>>     logical datapath/d])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -# Tests vtep module vtep logical switch tunnel key update.
>>>>     -AT_SETUP([ovn-controller-vtep - vtep-lswitch])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# creates the logical switch in vtep and adds the corresponding
>>>>     logical
>>>>     -# port to 'br-test'.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0])
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>>     [lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep --
>>>>     br-vtep_lswitch0`"])
>>>>     -
>>>>     -# retrieves the expected tunnel key.
>>>>     -datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding
>>>>     br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
>>>>     -tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding
>>>>     ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>>>     Logical_Switch | grep 0`"])
>>>>     -# checks the vtep logical switch tunnel key configuration.
>>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -${tunnel_key}
>>>>     -])
>>>>     -
>>>>     -# creates a second physical switch in vtep database, and binds
>>>>     its p0 vlan-100
>>>>     -# to the same logical switch 'lswitch0'.
>>>>     -AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void
>>>>     p0 -- bind-ls br-vtep-void p0 100 lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis
>>>>     | grep -- br-vtep-void`"])
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0],
>>>>     [br-vtep-void], [lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep --
>>>>     br-vtep-void_lswitch0`"])
>>>>     -
>>>>     -# checks the vtep logical switch tunnel key configuration.
>>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -${tunnel_key}
>>>>     -])
>>>>     -
>>>>     -# now, deletes br-vtep-void.
>>>>     -AT_CHECK([vtep-ctl del-ps br-vtep-void])
>>>>     -OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis
>>>>     | grep -- br-vtep-void`"])
>>>>     -# checks the vtep logical switch tunnel key configuration.
>>>>     -AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list
>>>>     Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -${tunnel_key}
>>>>     -])
>>>>     -
>>>>     -# changes the ovn-nb logical port type so that it is no longer
>>>>     -# vtep port.
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list
>>>>     Logical_Switch | grep 1`"])
>>>>     -# now should see the tunnel key reset.
>>>>     -AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut
>>>>     -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -0
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -# Tests vtep module 'Ucast_Macs_Remote's.
>>>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 1])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# creates a simple logical network with the vtep device and a
>>>>     fake hv chassis
>>>>     -# 'ch0'.
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>>     -
>>>>     -# creates the logical switch in vtep and adds the corresponding
>>>>     logical
>>>>     -# port to 'br-test'.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0])
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>>     [lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
>>>>     br-vtep_lswitch0`"])
>>>>     -
>>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>>     -# adds fake hv chassis 'ch1'.
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>>>     -
>>>>     -# checks Ucast_Macs_Remote creation.
>>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>>     _uuid`"])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' '], [0], [dnl
>>>>     -"f0:ab:cd:ef:01:02"
>>>>     -])
>>>>     -
>>>>     -# checks physical locator creation.
>>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep
>>>>     _uuid`"])
>>>>     -AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut
>>>>     -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
>>>>     -"1.2.3.5"
>>>>     -])
>>>>     -
>>>>     -# checks tunnel creation by ovs-vtep.
>>>>     -OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
>>>>     -AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 |
>>>>     cut -d ':' -f2 | tr -d ' '], [0], [dnl
>>>>     -{remote_ip="1.2.3.5"}
>>>>     -])
>>>>     -
>>>>     -# adds another mac to logical switch port.
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02
>>>>     f0:ab:cd:ef:01:03])
>>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>>     03`"])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>>     -
>>>>     -"f0:ab:cd:ef:01:02"
>>>>     -"f0:ab:cd:ef:01:03"
>>>>     -])
>>>>     -
>>>>     -# removes one mac to logical switch port.
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>>>     Ucast_Macs_Remote | grep 02`"])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>>     -"f0:ab:cd:ef:01:03"
>>>>     -])
>>>>     -
>>>>     -# migrates mac to logical switch port vif1 on 'br-void'.
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>>>     -OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list
>>>>     Ucast_Macs_Remote | grep 03`"])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
>>>>     -AT_SETUP([ovn-controller-vtep - vtep-macs 2])
>>>>     -OVN_CONTROLLER_VTEP_START
>>>>     -
>>>>     -# creates a simple logical network with the vtep device and a
>>>>     fake hv chassis
>>>>     -# 'ch0'.
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>>     -
>>>>     -# creates another vif in the same logical switch with 
>>>> duplicate mac.
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>>>     -
>>>>     -# creates the logical switch in vtep and adds the corresponding
>>>>     logical
>>>>     -# port to 'br-test'.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100
>>>>     lswitch0])
>>>>     -OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep],
>>>>     [lswitch0])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
>>>>     br-vtep_lswitch0`"])
>>>>     -
>>>>     -# checks Ucast_Macs_Remote creation.  Should still only be one
>>>>     entry, since duplicate
>>>>     -# mac in the same logical switch is not allowed.
>>>>     -OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep
>>>>     _uuid`"])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' '], [0], [dnl
>>>>     -"f0:ab:cd:ef:01:02"
>>>>     -])
>>>>     -# confirms the warning log.
>>>>     -OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
>>>>     -AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p'
>>>>     ovn-controller-vtep.log | sed
>>>>     's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
>>>>     -|WARN|MAC address () has already been known to be on logical port
>>>>     () in the same logical datapath, so just ignore this logical 
>>>> port ()
>>>>     -])
>>>>     -
>>>>     -# deletes vif1.
>>>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>>>     -
>>>>     -# adds another lswitch 'br-void' in ovn-nb database.
>>>>     -AT_CHECK([ovn-nbctl ls-add br-void])
>>>>     -# adds fake hv chassis 'ch1' and vif1 with same mac address as 
>>>> vif0.
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-void vif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep 
>>>> vif1`"])
>>>>     -
>>>>     -# creates another logical switch in vtep and adds the
>>>>     corresponding logical
>>>>     -# port to 'br-void'.
>>>>     -AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200
>>>>     lswitch1])
>>>>     -OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep],
>>>>     [lswitch1])
>>>>     -OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep
>>>>     br-void_lswitch1`"])
>>>>     -
>>>>     -# checks Ucast_Macs_Remote creation.  Should see two entries
>>>>     since it is allowed
>>>>     -# to have duplicate macs in different logical switches.
>>>>     -OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list
>>>>     Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
>>>>     -AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d
>>>>     ':' -f2- | tr -d ' ' | sort], [0], [dnl
>>>>     -
>>>>     -"f0:ab:cd:ef:01:02"
>>>>     -"f0:ab:cd:ef:01:02"
>>>>     -])
>>>>     -
>>>>     -OVN_CONTROLLER_VTEP_STOP([/has already been known to be on
>>>>     logical port/d])
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn-controller.at <http://ovn-controller.at>
>>>>     b/tests/ovn-controller.at <http://ovn-controller.at>
>>>>     deleted file mode 100644
>>>>     index 343c2ab..0000000
>>>>     --- a/tests/ovn-controller.at <http://ovn-controller.at>
>>>>     +++ /dev/null
>>>>     @@ -1,294 +0,0 @@
>>>>     -AT_BANNER([ovn-controller])
>>>>     -
>>>>     -AT_SETUP([ovn-controller - ovn-bridge-mappings])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_init_db ovn-sb
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0 \
>>>>     -    -- add-br br-eth1 \
>>>>     -    -- add-br br-eth2
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -# Waits until the OVS database contains exactly the specified
>>>>     patch ports.
>>>>     -# Each argument should be of the form BRIDGE PORT PEER.
>>>>     -check_patches () {
>>>>     -    # Generate code to check that the set of patch ports is
>>>>     exactly as
>>>>     -    # specified.
>>>>     -    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name
>>>>     find Interface type=patch | sort' > query
>>>>     -    for patch
>>>>     -    do
>>>>     -        echo $patch
>>>>     -    done | cut -d' ' -f 2 | sort > expout
>>>>     -
>>>>     -    # Generate code to verify that the configuration of each 
>>>> patch
>>>>     -    # port is correct.
>>>>     -    for patch
>>>>     -    do
>>>>     -        set $patch; bridge=$1 port=$2 peer=$3
>>>>     -        echo >>query "ovs-vsctl iface-to-br $port -- get
>>>>     Interface $port type options"
>>>>     -        echo >>expout "$bridge
>>>>     -patch
>>>>     -{peer=$peer}"
>>>>     -    done
>>>>     -
>>>>     -    # Run the query until we get the expected result (or until a
>>>>     timeout).
>>>>     -    #
>>>>     -    # (We use sed to drop all "s from output because ovs-vsctl
>>>>     quotes some
>>>>     -    # of the port names but not others.)
>>>>     -    AT_CAPTURE_FILE([query])
>>>>     -    AT_CAPTURE_FILE([expout])
>>>>     -    AT_CAPTURE_FILE([stdout])
>>>>     -    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
>>>>     -                    diff -u stdout expout >/dev/null])
>>>>     -}
>>>>     -
>>>>     -# Make sure that the configured bridge mappings in the
>>>>     Open_vSwitch db
>>>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>>>     -check_bridge_mappings () {
>>>>     -    local_mappings=$1
>>>>     -    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>>>     -    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get
>>>>     Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e
>>>>     's/\"//g')])
>>>>     -}
>>>>     -
>>>>     -# Initially there should be no patch ports.
>>>>     -check_patches
>>>>     -
>>>>     -# Configure two ovn-bridge mappings, but no patch ports should be
>>>>     created yet
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>> external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
>>>>     -check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
>>>>     -check_patches
>>>>     -
>>>>     -# Create a localnet port, but we should still have no patch
>>>>     ports, as they
>>>>     -# won't be created until there's a localnet port on a logical
>>>>     switch with
>>>>     -# another logical port bound to this chassis.
>>>>     -ovn-sbctl \
>>>>     -    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
>>>>     -    -- create Port_Binding datapath=@dp101 logical_port=localnet1
>>>>     tunnel_key=1 \
>>>>     -        type=localnet options:network_name=physnet1
>>>>     -check_patches
>>>>     -
>>>>     -# Create a localnet port on a logical switch with a port bound to
>>>>     this chassis.
>>>>     -# Now we should get some patch ports created.
>>>>     -ovn-sbctl \
>>>>     -    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
>>>>     -    -- create Port_Binding datapath=@dp102 logical_port=localnet2
>>>>     tunnel_key=1 \
>>>>     -        type=localnet options:network_name=physnet1 \
>>>>     -    -- create Port_Binding datapath=@dp102 logical_port=localvif2
>>>>     tunnel_key=2
>>>>     -ovs-vsctl add-port br-int localvif2 -- set Interface localvif2
>>>>     external_ids:iface-id=localvif2
>>>>     -check_patches \
>>>>     -    'br-int  patch-br-int-to-localnet2 
>>>> patch-localnet2-to-br-int' \
>>>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>>>     -
>>>>     -# Add logical patch ports to connect new logical datapath.
>>>>     -#
>>>>     -# OVN no longer uses OVS patch ports to implement logical patch
>>>>     ports, so
>>>>     -# the set of OVS patch ports doesn't change.
>>>>     -AT_CHECK([ovn-sbctl \
>>>>     -    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
>>>>     -    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
>>>>     -    -- create Port_Binding datapath=@dp1 logical_port=foo
>>>>     tunnel_key=1 type=patch options:peer=bar \
>>>>     -    -- create Port_Binding datapath=@dp2 logical_port=bar
>>>>     tunnel_key=2 type=patch options:peer=foo \
>>>>     -    -- create Port_Binding datapath=@dp1 logical_port=dp1vif
>>>>     tunnel_key=3 \
>>>>     -| uuidfilt], [0], [<0>
>>>>     -<1>
>>>>     -<2>
>>>>     -<3>
>>>>     -<4>
>>>>     -])
>>>>     -ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif
>>>>     external_ids:iface-id=dp1vif
>>>>     -check_patches \
>>>>     -    'br-int  patch-br-int-to-localnet2 
>>>> patch-localnet2-to-br-int' \
>>>>     -    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
>>>>     -
>>>>     -# Delete the mapping and the ovn-bridge-mapping patch ports
>>>>     should go away.
>>>>     -AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids
>>>>     ovn-bridge-mappings])
>>>>     -check_bridge_mappings
>>>>     -check_patches
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP_SBOX([hv])
>>>>     -OVN_CLEANUP_VSWITCH([main])
>>>>     -as ovn-sb
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# Checks that ovn-controller populates datapath-type and 
>>>> iface-types
>>>>     -# correctly in the Chassis external-ids column.
>>>>     -AT_SETUP([ovn-controller - Chassis external_ids])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_init_db ovn-sb
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0 \
>>>>     -    -- add-br br-eth1 \
>>>>     -    -- add-br br-eth2
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
>>>>     -
>>>>     -# Make sure that the datapath_type set in the Bridge table
>>>>     -# is mirrored into the Chassis record in the OVN_Southbound db.
>>>>     -check_datapath_type () {
>>>>     -    datapath_type=$1
>>>>     -    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid}
>>>>     external_ids:datapath-type | sed -e 's/"//g') #"
>>>>     -    test "${datapath_type}" = "${chassis_datapath_type}"
>>>>     -}
>>>>     -
>>>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>>>     -
>>>>     -ovs-vsctl set Bridge br-int datapath-type=foo
>>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>>     -
>>>>     -# Change "ovn-bridge-mappings" value. It should not change the
>>>>     "datapath-type".
>>>>     -ovs-vsctl set Open_vSwitch .
>>>>     external_ids:ovn-bridge-mappings=foo-mapping
>>>>     -check_datapath_type foo
>>>>     -
>>>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>>>     -OVS_WAIT_UNTIL([check_datapath_type bar])
>>>>     -
>>>>     -ovs-vsctl set Bridge br-int datapath-type=\"\"
>>>>     -OVS_WAIT_UNTIL([check_datapath_type ""])
>>>>     -
>>>>     -# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
>>>>     -ovs-vsctl set Open_vSwitch .
>>>>     external_ids:ovn-bridge-datapath-type=foo
>>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>>     -
>>>>     -# Change the br-int's datapath type to bar.
>>>>     -# It should be reset to foo since ovn-bridge-datapath-type is
>>>>     configured.
>>>>     -ovs-vsctl set Bridge br-int datapath-type=bar
>>>>     -OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int
>>>>     datapath-type`])
>>>>     -OVS_WAIT_UNTIL([check_datapath_type foo])
>>>>     -
>>>>     -ovs-vsctl set Open_vSwitch .
>>>>     external_ids:ovn-bridge-datapath-type=foobar
>>>>     -OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int
>>>>     datapath-type`])
>>>>     -OVS_WAIT_UNTIL([check_datapath_type foobar])
>>>>     -
>>>>     -expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types |
>>>>     tr -d '[[]] ""')
>>>>     -echo "expected_iface_types = ${expected_iface_types}"
>>>>     -chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>>>     external_ids:iface-types | sed -e 's/\"//g')
>>>>     -echo "chassis_iface_types = ${chassis_iface_types}"
>>>>     -AT_CHECK([test "${expected_iface_types}" = 
>>>> "${chassis_iface_types}"])
>>>>     -
>>>>     -# Change the value of external_ids:iface-types using ovn-sbctl.
>>>>     -# ovn-controller should again set it back to proper one.
>>>>     -ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid}
>>>>     external_ids:iface-types | sed -e 's/\"//g')
>>>>     -    echo "chassis_iface_types = ${chassis_iface_types}"
>>>>     -    test "${expected_iface_types}" = "${chassis_iface_types}"
>>>>     -])
>>>>     -
>>>>     -# Change the value of external_ids:system-id and make sure it's
>>>>     mirrored
>>>>     -# in the Chassis record in the OVN_Southbound database.
>>>>     -sysid=${sysid}-foo
>>>>     -ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
>>>>     -    test "${sysid}" = "${chassis_id}"
>>>>     -])
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP_SBOX([hv])
>>>>     -OVN_CLEANUP_VSWITCH([main])
>>>>     -as ovn-sb
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# Checks that ovn-controller correctly maintains the mapping from
>>>>     the Encap
>>>>     -# table in the Southbound database to OVS in the face of changes
>>>>     on both sides
>>>>     -AT_SETUP([ovn-controller - change Encap properties])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_init_db ovn-sb
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0 \
>>>>     -    -- add-br br-eth1 \
>>>>     -    -- add-br br-eth2
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -check_tunnel_property () {
>>>>     -    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
>>>>     -}
>>>>     -
>>>>     -# Start off with a remote chassis supporting STT
>>>>     -ovn-sbctl chassis-add fakechassis stt 192.168.0.2
>>>>     -OVS_WAIT_UNTIL([check_tunnel_property type stt])
>>>>     -
>>>>     -# See if we switch to Geneve as the first choice when it is 
>>>> available
>>>>     -# With multi-VTEP support we support tunnels with different IPs
>>>>     to the
>>>>     -# same chassis, and hence use the IP to annotate the tunnel
>>>>     (along with
>>>>     -# the chassis-id in ovn-chassis-id); if we supply a different 
>>>> IP here
>>>>     -# we won't be able to co-relate this to the tunnel port that was
>>>>     created
>>>>     -# in the previous step and, as a result, will end up creating
>>>>     another tunnel,
>>>>     -# ie. we can't just lookup using "ovn-fakech-0". So, need to use
>>>>     the same IP
>>>>     -# as above, i.e 192.168.0.2, here.
>>>>     -encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap --
>>>>     --id=@encap create encap type=geneve ip="192.168.0.2")
>>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>>     -
>>>>     -# Check that changes within an encap row are propagated
>>>>     -ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
>>>>     -OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip
>>>>     "\"192.168.0.2\""])
>>>>     -
>>>>     -# Change the type on the OVS side and check than OVN fixes it
>>>>     -ovs-vsctl set interface ovn-fakech-0 type=vxlan
>>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>>     -
>>>>     -# Delete the port entirely and it should be resurrected
>>>>     -ovs-vsctl del-port ovn-fakech-0
>>>>     -OVS_WAIT_UNTIL([check_tunnel_property type geneve])
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP_SBOX([hv])
>>>>     -OVN_CLEANUP_VSWITCH([main])
>>>>     -as ovn-sb
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# Check ovn-controller connection status to Southbound database
>>>>     -AT_SETUP([ovn-controller - check sbdb connection])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_init_db ovn-sb
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0 \
>>>>     -    -- add-br br-eth1 \
>>>>     -    -- add-br br-eth2
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -check_sbdb_connection () {
>>>>     -    test "$(ovs-appctl -t ovn-controller connection-status)" = 
>>>> "$1"
>>>>     -}
>>>>     -
>>>>     -OVS_WAIT_UNTIL([check_sbdb_connection connected])
>>>>     -
>>>>     -ovs-vsctl set open .
>>>>     external_ids:ovn-remote=tcp:192.168.0.10:6642
>>>>     <http://192.168.0.10:6642>
>>>>     -OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
>>>>     -
>>>>     -# reset the remote for clean-up
>>>>     -ovs-vsctl set open .
>>>> external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP_SBOX([hv])
>>>>     -OVN_CLEANUP_VSWITCH([main])
>>>>     -as ovn-sb
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn-macros.at <http://ovn-macros.at>
>>>>     b/tests/ovn-macros.at <http://ovn-macros.at>
>>>>     deleted file mode 100644
>>>>     index 7dba42c..0000000
>>>>     --- a/tests/ovn-macros.at <http://ovn-macros.at>
>>>>     +++ /dev/null
>>>>     @@ -1,180 +0,0 @@
>>>>     -# OVN_CLEANUP_VSWITCH(sim)
>>>>     -#
>>>>     -# Gracefully terminate vswitch daemons in the
>>>>     -# specified sandbox.
>>>>     -m4_define([OVN_CLEANUP_VSWITCH],[
>>>>     -    as $1
>>>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>>     -    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -])
>>>>     -
>>>>     -# OVN_CLEANUP_SBOX(sbox)
>>>>     -#
>>>>     -# Gracefully terminate OVN daemons in the specified
>>>>     -# sandbox instance. The sandbox name "vtep" is treated
>>>>     -# as a special case, and is assumed to have ovn-controller-vtep
>>>>     -# and ovs-vtep daemons running instead of ovn-controller.
>>>>     -m4_define([OVN_CLEANUP_SBOX],[
>>>>     -    as $1
>>>>     -    if test "$1" = "vtep"; then
>>>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
>>>>     -        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
>>>>     -    else
>>>>     -        OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -    fi
>>>>     -    OVN_CLEANUP_VSWITCH([$1])
>>>>     -])
>>>>     -
>>>>     -# OVN_CLEANUP(sim [, sim ...])
>>>>     -#
>>>>     -# Gracefully terminate all OVN daemons, including those in the
>>>>     -# specified sandbox instances.
>>>>     -m4_define([OVN_CLEANUP],[
>>>>     -    m4_foreach([sbox], [$@], [
>>>>     -        OVN_CLEANUP_SBOX([sbox])
>>>>     -    ])
>>>>     -    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 northd-backup
>>>>     -    OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>>     -
>>>>     -    OVN_CLEANUP_VSWITCH([main])
>>>>     -])
>>>>     -
>>>>     -m4_divert_push([PREPARE_TESTS])
>>>>     -
>>>>     -# ovn_init_db DATABASE
>>>>     -#
>>>>     -# Creates and initializes the given DATABASE (one of "ovn-sb" or
>>>>     "ovn-nb"),
>>>>     -# starts its ovsdb-server instance, and sets the appropriate
>>>>     environment
>>>>     -# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or
>>>>     ovn-nbctl uses the
>>>>     -# database by default.
>>>>     -#
>>>>     -# Usually invoked from ovn_start.
>>>>     -ovn_init_db () {
>>>>     -    echo "creating $1 database"
>>>>     -    local d=$ovs_base/$1
>>>>     -    mkdir "$d" || return 1
>>>>     -    : > "$d"/.$1.db.~lock~
>>>>     -    as $1 ovsdb-tool create "$d"/$1.db
>>>>     "$abs_top_srcdir"/ovn/$1.ovsschema
>>>>     -    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock
>>>>     "$d"/$1.db
>>>>     -    local var=`echo $1_db | tr a-z- A-Z_`
>>>>     -    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
>>>>     -}
>>>>     -
>>>>     -# ovn_start
>>>>     -#
>>>>     -# Creates and initializes ovn-sb and ovn-nb databases and starts
>>>>     their
>>>>     -# ovsdb-server instance, sets appropriate environment variables
>>>>     so that
>>>>     -# ovn-sbctl and ovn-nbctl use them by default, and starts
>>>>     ovn-northd running
>>>>     -# against them.
>>>>     -ovn_start () {
>>>>     -    ovn_init_db ovn-sb; ovn-sbctl init
>>>>     -    ovn_init_db ovn-nb; ovn-nbctl init
>>>>     -
>>>>     -    echo "starting ovn-northd"
>>>>     -    mkdir "$ovs_base"/northd
>>>>     -    as northd start_daemon ovn-northd -v \
>>>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -
>>>>     -    echo "starting backup ovn-northd"
>>>>     -    mkdir "$ovs_base"/northd-backup
>>>>     -    as northd-backup start_daemon ovn-northd -v \
>>>>     -  --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>>     -  --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -}
>>>>     -
>>>>     -# Interconnection networks.
>>>>     -#
>>>>     -# When multiple sandboxed Open vSwitch instances exist, one will
>>>>     inevitably
>>>>     -# want to connect them together.  These commands allow for that.
>>>>     Conceptually,
>>>>     -# an interconnection network is a switch for which these
>>>>     functions make it easy
>>>>     -# to plug into other switches in other sandboxed Open vSwitch
>>>>     instances.
>>>>     -# Interconnection networks are implemented as bridges in a switch
>>>>     named "main",
>>>>     -# so to use interconnection networks please avoid working with
>>>>     that switch
>>>>     -# directly.
>>>>     -
>>>>     -# net_add NETWORK
>>>>     -#
>>>>     -# Creates a new interconnection network named NETWORK.
>>>>     -net_add () {
>>>>     -    test -d "$ovs_base"/main || sim_add main || return 1
>>>>     -    as main ovs-vsctl add-br "$1"
>>>>     -}
>>>>     -
>>>>     -# net_attach NETWORK BRIDGE
>>>>     -#
>>>>     -# Adds a new port to BRIDGE in the default sandbox (as set with
>>>>     as()) and plugs
>>>>     -# it into the NETWORK interconnection network.  NETWORK must
>>>>     already have been
>>>>     -# created by a previous invocation of net_add.  The default
>>>>     sandbox must not be
>>>>     -# "main".
>>>>     -net_attach () {
>>>>     -    local net=$1 bridge=$2
>>>>     -
>>>>     -    local port=${sandbox}_$bridge
>>>>     -    as main ovs-vsctl \
>>>>     -        -- add-port $net $port \
>>>>     -        -- set Interface $port
>>>>     options:pstream="punix:$ovs_base/main/$port.sock"
>>>>     options:rxq_pcap="$ovs_base/main/$port-rx.pcap"
>>>>     options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
>>>>     -        || return 1
>>>>     -
>>>>     -    ovs-vsctl \
>>>>     -        -- set Interface $bridge
>>>>     options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap"
>>>>     options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
>>>>     -        -- add-port $bridge ${bridge}_$net \
>>>>     -        -- set Interface ${bridge}_$net
>>>>     options:stream="unix:$ovs_base/main/$port.sock"
>>>> options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap"
>>>> options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
>>>>     -        || return 1
>>>>     -}
>>>>     -
>>>>     -# ovn_attach NETWORK BRIDGE IP [MASKLEN]
>>>>     -#
>>>>     -# First, this command attaches BRIDGE to interconnection network
>>>>     NETWORK, just
>>>>     -# like "net_attach NETWORK BRIDGE".  Second, it configures
>>>>     (simulated) IP
>>>>     -# address IP (with network mask length MASKLEN, which defaults to
>>>>     24) on
>>>>     -# BRIDGE.  Finally, it configures the Open vSwitch database to
>>>>     work with OVN
>>>>     -# and starts ovn-controller.
>>>>     -ovn_attach() {
>>>>     -    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
>>>>     -    net_attach $net $bridge || return 1
>>>>     -
>>>>     -    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed 
>>>> s/\"//g`
>>>>     -    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
>>>>     -    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen
>>>>     >/dev/null || return 1
>>>>     -    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null ||
>>>>     return 1
>>>>     -    ovs-vsctl \
>>>>     -        -- set Open_vSwitch . external-ids:system-id=$sandbox \
>>>>     -        -- set Open_vSwitch .
>>>> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
>>>>     -        -- set Open_vSwitch .
>>>>     external-ids:ovn-encap-type=geneve,vxlan \
>>>>     -        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
>>>>     -        -- add-br br-int \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true \
>>>>     -        || return 1
>>>>     -    start_daemon ovn-controller || return 1
>>>>     -}
>>>>     -
>>>>     -# OVN_POPULATE_ARP
>>>>     -#
>>>>     -# This pre-populates the ARP tables of all of the OVN instances
>>>>     that have been
>>>>     -# started with ovn_attach().  That means that packets sent from
>>>>     one hypervisor
>>>>     -# to another never get dropped or delayed by ARP resolution,
>>>>     which makes
>>>>     -# testing easier.
>>>>     -ovn_populate_arp__() {
>>>>     -    for e1 in $arp_table; do
>>>>     -        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 
>>>> mac=$4
>>>>     -        for e2 in $arp_table; do
>>>>     -            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
>>>>     -            if test $sb1,$br1 != $sb2,$br2; then
>>>>     -                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac ||
>>>>     return 1
>>>>     -            fi
>>>>     -        done
>>>>     -    done
>>>>     -}
>>>>     -m4_divert_pop([PREPARE_TESTS])
>>>>     -
>>>>     -m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0],
>>>>     [ignore])])
>>>>     diff --git a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>>     b/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>>     deleted file mode 100644
>>>>     index d99d3af..0000000
>>>>     --- a/tests/ovn-nbctl.at <http://ovn-nbctl.at>
>>>>     +++ /dev/null
>>>>     @@ -1,1660 +0,0 @@
>>>>     -AT_BANNER([ovn-nbctl])
>>>>     -
>>>>     -OVS_START_SHELL_HELPERS
>>>>     -# OVN_NBCTL_TEST_START
>>>>     -m4_define([OVN_NBCTL_TEST_START],
>>>>     -  [AT_KEYWORDS([ovn])
>>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>>     -   ovn_nbctl_test_start $1])
>>>>     -ovn_nbctl_test_start() {
>>>>     -   dnl Create ovn-nb database.
>>>>     -   AT_CHECK([ovsdb-tool create ovn-nb.db
>>>>     $abs_top_srcdir/ovn/ovn-nb.ovsschema])
>>>>     -
>>>>     -   dnl Start ovsdb-server.
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile
>>>>     --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db],
>>>>     [0], [], [stderr])
>>>>     -   on_exit "kill `cat ovsdb-server.pid`"
>>>>     -   AS_CASE([$1],
>>>>     -     [daemon],
>>>>     -       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach
>>>>     --no-chdir --log-file -vsocket_util:off)
>>>>     -        on_exit "kill `cat ovn-nbctl.pid`"],
>>>>     -     [direct], [],
>>>>     -     [*], [AT_FAIL_IF(:)])
>>>>     -   AT_CHECK([ovn-nbctl init])
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d
>>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>>     -}
>>>>     -
>>>>     -# OVN_NBCTL_TEST_STOP
>>>>     -m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
>>>>     -ovn_nbctl_test_stop() {
>>>>     -   AT_CHECK([check_logs "$1"])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -}
>>>>     -OVS_END_SHELL_HELPERS
>>>>     -
>>>>     -# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
>>>>     -m4_define([OVN_NBCTL_TEST],
>>>>     -   [OVS_START_SHELL_HELPERS
>>>>     -    $1() {
>>>>     -      $3
>>>>     -    }
>>>>     -    OVS_END_SHELL_HELPERS
>>>>     -
>>>>     -    AT_SETUP([ovn-nbctl - $2 - direct])
>>>>     -    OVN_NBCTL_TEST_START direct
>>>>     -    $1
>>>>     -    OVN_NBCTL_TEST_STOP
>>>>     -    AT_CLEANUP
>>>>     -
>>>>     -    AT_SETUP([ovn-nbctl - $2 - daemon])
>>>>     -    OVN_NBCTL_TEST_START daemon
>>>>     -    $1
>>>>     -    OVN_NBCTL_TEST_STOP
>>>>     -    AT_CLEANUP])
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch 
>>>> commands], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>>     -<0> (ls0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>>     -<0> (ls0)
>>>>     -<1> (ls1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-del ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>>     -<0> (ls1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl show ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>>>     -  [switch <0> (ls0)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
>>>>     -  [ovn-nbctl: ls0: a switch with this name already exists
>>>>     -])
>>>>  ��  -AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
>>>>     -  [switch <0> (ls0)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], 
>>>> [1], [],
>>>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>>>     together
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
>>>>     -  [ovn-nbctl: Multiple logical switches named 'ls0'. Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
>>>>     -  [ovn-nbctl: ls2: switch name not found
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add])
>>>>     -AT_CHECK([ovn-nbctl ls-add])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
>>>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
>>>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port
>>>>     commands], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
>>>>     -  [ovn-nbctl: lp0: a port with this name already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>>     -<0> (lp0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
>>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>>     -<0> (lp0)
>>>>     -<1> (lp1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
>>>>     -  [ovn-nbctl: lp1: a port with this name already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
>>>>     -  [ovn-nbctl: lp1: port already exists but in switch ls0
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
>>>>     -  [ovn-nbctl: lp1: port already exists but has no parent
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-del lp1])
>>>>     -AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
>>>>     -<0> (lp0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
>>>>     -  [ovn-nbctl: lp2: port already exists with different parent lp3
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
>>>>     -  [ovn-nbctl: lp2: port already exists with different 
>>>> tag_request 5
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
>>>>     -  [ovn-nbctl: lp2: port already exists but has no tag_request
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
>>>>     -<0> (ls0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
>>>>     -  [ovn-nbctl: lp1: port name not found
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 
>>>> unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>>     -00:11:22:33:44:55
>>>>     -unknown
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff
>>>>     00:11:22:33:44:55])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>>>     -00:11:22:33:44:55
>>>>     -aa:bb:cc:dd:ee:ff
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
>>>>     -ovn_nbctl_test_acl() {
>>>>     -   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp 
>>>> drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info
>>>>     acl-add $1 to-lport 500 udp drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
>>>>     -   dnl Add duplicated ACL
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1],
>>>>     [], [stderr])
>>>>     -   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>>>     -   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip
>>>>     drop])
>>>>     -
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>>     -from-lport   600 (udp) drop log()
>>>>     -from-lport   400 (tcp) drop
>>>>     -from-lport   200 (ip) drop
>>>>     -  to-lport   500 (udp) drop log(name=test,severity=info)
>>>>     -  to-lport   300 (tcp) drop
>>>>     -  to-lport   100 (ip) drop
>>>>     -])
>>>>     -
>>>>     -   dnl Delete in one direction.
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>>     -from-lport   600 (udp) drop log()
>>>>     -from-lport   400 (tcp) drop
>>>>     -from-lport   200 (ip) drop
>>>>     -])
>>>>     -
>>>>     -   dnl Delete all ACLs.
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
>>>>     -
>>>>     -   dnl Delete a single flow.
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
>>>>     -   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
>>>>     -from-lport   600 (udp) drop
>>>>     -from-lport   200 (ip) drop
>>>>     -])
>>>>     -}
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -ovn_nbctl_test_acl ls0
>>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>>     -ovn_nbctl_test_acl ls1 --type=switch
>>>>     -AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
>>>>     -ovn_nbctl_test_acl pg0 --type=port-group
>>>>     -
>>>>     -dnl Test when port group doesn't exist
>>>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip
>>>>     drop], [1], [], [dnl
>>>>     -ovn-nbctl: pg1: port group name not found
>>>>     -])
>>>>     -
>>>>     -dnl Test when same name exists in logical switches and portgroups
>>>>     -AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [],
>>>>     [stderr])
>>>>     -AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip
>>>>     drop], [0], [ignore])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100
>>>>     burst=1000])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0
>>>>     rate=300 burst=3000])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301
>>>>     burst=30000])
>>>>     -
>>>>     -dnl Add duplicated qos
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302
>>>>     burst=30002], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'already existed' stderr], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4
>>>>     dscp=11 rate=302 burst=30002])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>>     -from-lport   600 (tcp) dscp=63
>>>>     -from-lport   500 (udp) rate=100 burst=1000
>>>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>>>     -  to-lport   300 (tcp) dscp=48
>>>>     -  to-lport   200 (ip) rate=101
>>>>     -  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
>>>>     -])
>>>>     -
>>>>     -dnl Delete in one direction.
>>>>     -AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
>>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>>     -from-lport   600 (tcp) dscp=63
>>>>     -from-lport   500 (udp) rate=100 burst=1000
>>>>     -from-lport   400 (tcp) rate=300 burst=3000 dscp=0
>>>>     -])
>>>>     -
>>>>     -dnl Delete all qos_rules.
>>>>     -AT_CHECK([ovn-nbctl qos-del ls0])
>>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102
>>>>     rate=301 dscp=19])
>>>>     -
>>>>     -dnl Delete a single flow.
>>>>     -AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
>>>>     -AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
>>>>     -from-lport   600 (ip) rate=1000101
>>>>     -from-lport   200 (ip) rate=301 burst=1000102 dscp=19
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>>>     rate=100010111111], [1], [],
>>>>     -[ovn-nbctl: 100010111111: rate must be in the range 
>>>> 1...4294967295
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip
>>>>     burst=100010111112 rate=100010], [1], [],
>>>>     -[ovn-nbctl: 100010111112: burst must be in the range 
>>>> 1...4294967295
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: -1: dscp must be in the range 0...63
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=",
>>>>     and "burst="
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123],
>>>>     [1], [],
>>>>     -[ovn-nbctl: Either "rate" and/or "dscp" must be specified
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
>>>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
>>>>     -AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
>>>>     -AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
>>>>     -AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
>>>>     -
>>>>     -dnl Add duplicate meter name
>>>>     -AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [],
>>>>     [stderr])
>>>>     -AT_CHECK([grep 'already exists' stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Add reserved meter name
>>>>     -AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [],
>>>>     [stderr])
>>>>     -AT_CHECK([grep 'reserved' stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Add meter with invalid rates
>>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps],
>>>>     [1], [],
>>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>>     -])
>>>>     -
>>>>     -dnl Add meter with invalid rates
>>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], 
>>>> [1], [],
>>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
>>>>     -[ovn-nbctl: rate must be in the range 1...4294967295
>>>>     -])
>>>>     -
>>>>     -dnl Add meter with invalid burst
>>>>     -AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps],
>>>>     [1], [],
>>>>     -[ovn-nbctl: unit must be "kbps" or "pktps"
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>>     -meter1: bands:
>>>>     -  drop: 10 kbps
>>>>     -meter2: bands:
>>>>     -  drop: 3 kbps, 2 kb burst
>>>>     -meter3: bands:
>>>>     -  drop: 100 kbps, 200 kb burst
>>>>     -meter4: bands:
>>>>     -  drop: 10 pktps, 30 packet burst
>>>>     -])
>>>>     -
>>>>     -dnl Delete a single meter.
>>>>     -AT_CHECK([ovn-nbctl meter-del meter2])
>>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>>     -meter1: bands:
>>>>     -  drop: 10 kbps
>>>>     -meter3: bands:
>>>>     -  drop: 100 kbps, 200 kb burst
>>>>     -meter4: bands:
>>>>     -  drop: 10 pktps, 30 packet burst
>>>>     -])
>>>>     -
>>>>     -dnl Delete all meters.
>>>>     -AT_CHECK([ovn-nbctl meter-del])
>>>>     -AT_CHECK([ovn-nbctl meter-list], [0], [dnl
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2],
>>>>     [1], [],
>>>>     -[ovn-nbctl: snatt: type must be one of "dnat", "snat" and
>>>>     "dnat_and_snat".
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2],
>>>>     [1], [],
>>>>     -[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], 
>>>> [1], [],
>>>>     -[ovn-nbctl: 30.0.0: should be an IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24
>>>>     <http://30.0.0.2/24> 192.168.1.2], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.2/24 <http://30.0.0.2/24>: should be an IPv4
>>>>     address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80
>>>>     <http://30.0.0.2:80> 192.168.1.2], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.2:80 <http://30.0.0.2:80>: should be an IPv4
>>>>     address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a],
>>>>     [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80
>>>>     <http://192.168.1.2:80>], [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>>>     IPv4 address or network.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a
>>>>     <http://192.168.1.2/a>], [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2/a <http://192.168.1.2/a>: should be an
>>>>     IPv4 address or network.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a],
>>>>     [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: 192.168.1: should be an IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80
>>>>     <http://192.168.1.2:80>], [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2:80 <http://192.168.1.2:80>: should be an
>>>>     IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24
>>>>     <http://192.168.1.2/24>], [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>>>     IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>>     192.168.1.2/24 <http://192.168.1.2/24>], [1], [],
>>>>     -[ovn-nbctl: 192.168.1.2/24 <http://192.168.1.2/24>: should be an
>>>>     IPv4 address.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>>     192.168.1.2 lp0], [1], [],
>>>>     -[ovn-nbctl: lr-nat-add with logical_port must also specify
>>>>     external_mac.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
>>>>     00:00:00:01:02:03], [1], [],
>>>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>>>     type is "dnat_and_snat".
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
>>>>     00:00:00:01:02:03], [1], [],
>>>>     -[ovn-nbctl: logical_port and external_mac are only valid when
>>>>     type is "dnat_and_snat".
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>>     192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
>>>>     -[ovn-nbctl: lp0: port name not found
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>>     192.168.1.2 lp0 00:00:00:01:02], [1], [],
>>>>     -[ovn-nbctl: invalid mac address 00:00:00:01:02.
>>>>     -])
>>>>     -
>>>>     -dnl Add snat and dnat
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>>>     <http://192.168.1.0/24>])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>>     192.168.1.2])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2
>>>>     192.168.1.3 lp0 00:00:00:01:02:03])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>>        LOGICAL_PORT
>>>>     -dnat             30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>>      00:00:00:01:02:03    lp0
>>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24
>>>>     <http://192.168.1.0/24>], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>>>     NAT with this external_ip and logical_ip already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24
>>>>     <http://192.168.1.10/24>], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.0/24 <http://192.168.1.0/24>: a
>>>>     NAT with this external_ip and logical_ip already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1
>>>>     192.168.1.0/24 <http://192.168.1.0/24>])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24
>>>>     <http://192.168.1.0/24>], [1], [],
>>>>     -[ovn-nbctl: a NAT with this type (snat) and logical_ip
>>>>     (192.168.1.0/24 <http://192.168.1.0/24>) already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2],
>>>>     [1], [],
>>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>>>     with this external_ip and logical_ip already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1
>>>>     192.168.1.2])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3],
>>>>     [1], [],
>>>>     -[ovn-nbctl: a NAT with this type (dnat) and external_ip
>>>>     (30.0.0.1) already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>>     192.168.1.2], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.1, 192.168.1.2 <http://192.168.1.2>: a NAT
>>>>     with this external_ip and logical_ip already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>>     30.0.0.1 192.168.1.2])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1
>>>>     192.168.1.3], [1], [],
>>>>     -[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
>>>>     (30.0.0.1) already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>>     30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>>        LOGICAL_PORT
>>>>     -dnat             30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>>      00:00:00:04:05:06    lp0
>>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat
>>>>     30.0.0.2 192.168.1.3])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>>        LOGICAL_PORT
>>>>     -dnat             30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -])
>>>>     -
>>>>     -dnl Deletes the NATs
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], 
>>>> [1], [],
>>>>     -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and
>>>>     external_ip (30.0.0.3)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
>>>>     -[ovn-nbctl: no matching NAT with the type (dnat) and external_ip
>>>>     (30.0.0.2)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24
>>>>     <http://192.168.10.0/24>], [1], [],
>>>>     -[ovn-nbctl: no matching NAT with the type (snat) and logical_ip
>>>>     (192.168.10.0/24 <http://192.168.10.0/24>)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat
>>>>     192.168.10.0/24 <http://192.168.10.0/24>])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>>        LOGICAL_PORT
>>>>     -dnat             30.0.0.1           192.168.1.2
>>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
>>>>     -TYPE             EXTERNAL_IP        LOGICAL_IP EXTERNAL_MAC
>>>>        LOGICAL_PORT
>>>>     -dnat_and_snat    30.0.0.2           192.168.1.3
>>>>     -snat             30.0.0.1 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
>>>>     -dnl Add two LBs.
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP
>>>>     address and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP
>>>>     address and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80
>>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20 tcp], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.20 <http://192.168.10.20>: should be an IP
>>>>     address and a port number with : as a separator.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>], [1], [],
>>>>     -[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address
>>>>     and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>], [1], [],
>>>>     -[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and
>>>>     a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>>     192.168.10.10,192.168.10.20:80 <http://192.168.10.20:80>], [1], 
>>>> [],
>>>>     -[ovn-nbctl: 192.168.10.20:80 <http://192.168.10.20:80>: should be
>>>>     an IP address.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>>     192.168.10.10:a80], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>>     192.168.10.10:], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>:: should be an
>>>>     IP address.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10
>>>>     192.168.10.1a], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.1a: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 <http://30.0.0.10>:
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], 
>>>> [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900
>>>>     <http://192.168.10.10:900> tcp], [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -dnl Add ips to lb
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,,])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     ,,,192.168.10.10:80 <http://192.168.10.10:80>,,,,192.168.10.20:80
>>>>     <http://192.168.10.20:80>,,,,])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>
>>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -])
>>>>     -
>>>>     -dnl Update the VIP of the lb1.
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>>     <http://30.0.0.10:80> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080> udp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     -])
>>>>     -
>>>>     -dnl Config lb1 with another VIP.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 <http://30.0.0.20:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80> udp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     - udp 30.0.0.20:80 <http://30.0.0.20:80> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80 
>>>> <http://30.0.0.20:80>])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     -])
>>>>     -
>>>>     -dnl Add LBs whose vip is just an IP address.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     -<2>    lb2                 tcp/udp    30.0.0.30  192.168.10.10
>>>>     -<3>    lb3                 tcp/udp    30.0.0.30  192.168.10.10
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>            IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080>
>>>>     -<2>    lb2                 tcp 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>>> <http://192.168.10.20:80>
>>>>     -<3>    lb2                 tcp 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>>> <http://192.168.10.20:80>
>>>>     -])
>>>>     -
>>>>     -dnl If there are multiple load balancers with the same name, use
>>>>     a UUID to update/delete.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> tcp], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80
>>>>     <http://30.0.0.10:80> 192.168.10.10:8080
>>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080> udp])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:8080
>>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080> udp])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090
>>>>     <http://30.0.0.10:9090> 192.168.10.10:8080
>>>>     <http://192.168.10.10:8080>,192.168.10.20:8080
>>>>     <http://192.168.10.20:8080> udp])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80 
>>>> <http://30.0.0.10:80>])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>            IPs
>>>>     -<0>    lb2                 tcp 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>>> <http://192.168.10.20:80>
>>>>     -<1>    lb2                 tcp 30.0.0.10:8080
>>>>     <http://30.0.0.10:8080> 192.168.10.10:80
>>>>     <http://192.168.10.10:80>,192.168.10.20:80 
>>>> <http://192.168.10.20:80>
>>>>     -])
>>>>     -
>>>>     -dnl Add load balancer to logical switch.
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80> udp])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10
>>>>     192.168.10.10,192.168.10.20])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>>>      192.168.10.10,192.168.10.20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>>>      192.168.10.10,192.168.10.20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>>>     -
>>>>     -dnl Remove all load balancers from logical switch.
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>>     -
>>>>     -dnl Add load balancer to logical router.
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb0                 tcp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<2>    lb3                 tcp/udp    30.0.0.10
>>>>      192.168.10.10,192.168.10.20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>          IPs
>>>>     -<0>    lb1                 udp 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     192.168.10.10:80 <http://192.168.10.10:80>,192.168.10.20:80
>>>>     <http://192.168.10.20:80>
>>>>     -<1>    lb3                 tcp/udp    30.0.0.10
>>>>      192.168.10.10,192.168.10.20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>>>     -
>>>>     -dnl Remove all load balancers from logical router.
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>>     -
>>>>     -dnl Remove load balancers after adding them to a logical
>>>>     router/switch.
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
>>>>     -dnl A bunch of commands that should fail
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>>     -[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP
>>>>     address and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>>     -[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP
>>>>     address and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>>>     -[ovn-nbctl: fd0f::20: should be an IP address and a port number
>>>>     with : as a separator.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff
>>>>     [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
>>>>     -[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP
>>>>     address and a port number with : as a separator).
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
>>>>     -[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>>     fd0f::10,[[fd0f::20]]:80], [1], [],
>>>>     -[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>>     [[fd0f::10]]:a80], [1], [],
>>>>     -[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>>     [[fd0f::10]]:], [1], [],
>>>>     -[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10
>>>>     fd0f::1001a], [1], [],
>>>>     -[ovn-nbctl: fd0f::1001a: should be an IP address.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp],
>>>>     [1], [],
>>>>     -[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>>>     family is different from VIP ae0f::10.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.10 <http://192.168.10.10>: IP address
>>>>     family is different from VIP ae0f::10.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80
>>>>     <http://192.168.10.10:80>], [1], [],
>>>>     -[ovn-nbctl: 192.168.10.10:80 <http://192.168.10.10:80>: IP
>>>>     address family is different from VIP [[ae0f::10]]:80.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
>>>>     -[ovn-nbctl: ae0f::10: IP address family is different from VIP
>>>>     30.0.0.10.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 <http://30.0.0.10:80>
>>>>     [[ae0f::10]]:80], [1], [],
>>>>     -[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from
>>>>     VIP 30.0.0.10:80 <http://30.0.0.10:80>.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0
>>>>     ae0f:0000:0000:0000:0000:0000:0000:0010 fd0f::20],
>>>>     -[1], [], [ovn-nbctl: lb0: a load balancer with this vip
>>>>     (ae0f::10) already exists
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>>     -
>>>>     -dnl Add ips to lb
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>>     ,,,[[fd0f::10]]:80,,,,,])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>>     ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80 [[fd0f::10]]:80
>>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>>     -
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -])
>>>>     -
>>>>     -dnl Update the VIP of the lb1.
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     -])
>>>>     -
>>>>     -dnl Config lb1 with another VIP.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 
>>>> udp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     - udp        [[ae0f::20]]:80    [[fd0f::10]]:80
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     -])
>>>>     -
>>>>     -dnl Add LBs whose vip is just an IP address.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     -<2>    lb2                 tcp/udp    ae0f::30  fd0f::10
>>>>     -<3>    lb3                 tcp/udp    ae0f::30  fd0f::10
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>             IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:8080
>>>>     -<2>    lb2                 tcp [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<3>    lb2                 tcp [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -])
>>>>     -
>>>>     -dnl If there are multiple load balancers with the same name, use
>>>>     a UUID to update/delete.
>>>>     -AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090
>>>>     [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
>>>>     -AT_CHECK([ovn-nbctl lb-del lb1])
>>>>     -AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>             IPs
>>>>     -<0>    lb2                 tcp [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb2                 tcp [[ae0f::10]]:8080
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -])
>>>>     -
>>>>     -dnl Add load balancer to logical switch.
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>>     -AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
>>>>     -
>>>>     -dnl Remove all load balancers from logical switch.
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-del ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
>>>>     -
>>>>     -dnl Add load balancer to logical router.
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
>>>>     -[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb0                 tcp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<2>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
>>>>     -UUID                                    LB PROTO VIP
>>>>           IPs
>>>>     -<0>    lb1                 udp [[ae0f::10]]:80
>>>>     [[fd0f::10]]:80,[[fd0f::20]]:80
>>>>     -<1>    lb3                 tcp/udp    ae0f::10  fd0f::10,fd0f::20
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
>>>>     -AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
>>>>     -
>>>>     -dnl Remove all load balancers from logical router.
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router
>>>>     commands], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>>     -<0> (lr0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>>     -<0> (lr0)
>>>>     -<1> (lr1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
>>>>     -<0> (lr1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl show lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>>>     -  [router <0> (lr0)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
>>>>     -  [ovn-nbctl: lr0: a router with this name already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
>>>>     -  [router <0> (lr0)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], 
>>>> [1], [],
>>>>     -  [ovn-nbctl: --may-exist and --add-duplicate may not be used
>>>>     together
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
>>>>     -  [ovn-nbctl: Multiple logical routers named 'lr0'. Use a UUID.
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
>>>>     -  [ovn-nbctl: lr2: router name not found
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-add])
>>>>     -AT_CHECK([ovn-nbctl lr-add])
>>>>     -AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
>>>>     -  [ovn-nbctl: --add-duplicate requires specifying a name
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
>>>>     -  [ovn-nbctl: --may-exist requires specifying a name
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port
>>>>     commands], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02
>>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04
>>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>>     -  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
>>>>     -router <0> (lr0)
>>>>     -    port lrp0
>>>>     -        mac: "00:00:00:01:02:03"
>>>>     -        networks: [["192.168.1.1/24 <http://192.168.1.1/24>"]]
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>>     -  [ovn-nbctl: lrp0: a port with this name already exists
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>])
>>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>>     -<0> (lrp0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24> peer=lrp1-peer])
>>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>>     -<0> (lrp0)
>>>>     -<1> (lrp1)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-add lr1])
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24>], [1], [],
>>>>     -  [ovn-nbctl: lrp1: a port with this name already exists
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], 
>>>> [],
>>>>     -  [ovn-nbctl: lrp1: port already exists but in router lr0
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:04:05:06 192.168.1.1/24 <http://192.168.1.1/24>], [1], 
>>>> [],
>>>>     -  [ovn-nbctl: lrp1: port already exists with mac 
>>>> 00:00:00:01:02:03
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>], [1], 
>>>> [],
>>>>     -  [ovn-nbctl: lrp1: port already exists with mismatching peer
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24>
>>>>     peer=lrp1-peer], [1], [],
>>>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>>     peer=lrp1-peer])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-del lrp1])
>>>>     -AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
>>>>     -<0> (lrp0)
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>>     10.0.0.1/24 <http://10.0.0.1/24> peer=lrp1-peer])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 192.168.1.1/24 <http://192.168.1.1/24>
>>>>     172.16.0.1/24 <http://172.16.0.1/24> peer=lrp1-peer], [1], [],
>>>>     -  [ovn-nbctl: lrp1: port already exists with different network
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1
>>>>     00:00:00:01:02:03 10.0.0.1/24 <http://10.0.0.1/24> 192.168.1.1/24
>>>>     <http://192.168.1.1/24> peer=lrp1-peer])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port
>>>>     gateway chassis], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: lp0: port name not found
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
>>>>     -[ovn-nbctl: lp0: port name not found
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: lp0: port name not found
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], 
>>>> [1], [],
>>>>     -[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis1     0
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis1    10
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis1    20
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis1    20
>>>>     -lrp0-chassis2     5
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis2     5
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
>>>>     -AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
>>>>     -lrp0-chassis2    10
>>>>     -lrp0-chassis3     5
>>>>     -lrp0-chassis1     1
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port
>>>>     enable and disable], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03
>>>>     192.168.1.1/24 <http://192.168.1.1/24>])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
>>>>     -AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
>>>>     -  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -
>>>>     -dnl Check IPv4 routes
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>>>     192.168.0.1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24
>>>>     <http://10.0.1.0/24> 11.0.1.1 lp0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>>>     <http://10.0.0.1/24> 11.0.0.2])
>>>>     -
>>>>     -dnl Add overlapping route with 10.0.0.1/24 <http://10.0.0.1/24>
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>>     <http://10.0.0.111/24> 11.0.0.1], [1], [],
>>>>     -  [ovn-nbctl: duplicate prefix: 10.0.0.0/24 <http://10.0.0.0/24>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1],
>>>>     [1], [],
>>>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a
>>>>     <http://10.0.0.111/24a> 11.0.0.1], [1], [],
>>>>     -  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
>>>>     <http://10.0.0.111/24a>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>>     <http://10.0.0.111/24> 11.0.0.1a], [1], [],
>>>>     -  [ovn-nbctl: bad next hop argument: 11.0.0.1a
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24
>>>>     <http://10.0.0.111/24> 11.0.0.1/24 <http://11.0.0.1/24>], [1], [],
>>>>     -  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
>>>>     <http://11.0.0.1/24>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>>     2001:0db8:0:f103::1/64], [1], [],
>>>>     -  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>>>     <http://10.0.0.111/24> 11.0.0.1])
>>>>     -AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24
>>>>     <http://9.16.1.0/24> 11.0.0.1])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv4 Routes
>>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip
>>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>>     - 9.16.1.0/24 <http://9.16.1.0/24> 11.0.0.1 src-ip
>>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24
>>>>     <http://10.0.0.111/24> 11.0.0.1 lp1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv4 Routes
>>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip lp1
>>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>>     - 9.16.1.0/24 <http://9.16.1.0/24> 11.0.0.1 src-ip
>>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>>     -])
>>>>     -
>>>>     -dnl Delete non-existent prefix
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24
>>>>     <http://10.0.2.1/24>], [1], [],
>>>>     -  [ovn-nbctl: no matching prefix: 10.0.2.0/24 
>>>> <http://10.0.2.0/24>
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24
>>>>     <http://10.0.2.1/24>])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24
>>>>     <http://10.0.1.1/24>])
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24
>>>>     <http://9.16.1.0/24>])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv4 Routes
>>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip lp1
>>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -dnl Check IPv6 routes
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>>>     2001:0db8:0:f101::1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>>>     2001:0db8:0:f102::1 lp0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>>     2001:0db8:0:f103::1])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv6 Routes
>>>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv6 Routes
>>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-del lr0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -dnl Check IPv4 and IPv6 routes
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 <http://0.0.0.0/0>
>>>>     192.168.0.1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24
>>>>     <http://10.0.1.1/24> 11.0.1.1 lp0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24
>>>>     <http://10.0.0.1/24> 11.0.0.1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0
>>>>     2001:0db8:0:f101::1])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64
>>>>     2001:0db8:0:f102::1 lp0])
>>>>     -AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64
>>>>     2001:0db8:0:f103::1])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
>>>>     -IPv4 Routes
>>>>     - 10.0.0.0/24 <http://10.0.0.0/24> 11.0.0.1 dst-ip
>>>>     - 10.0.1.0/24 <http://10.0.1.0/24> 11.0.1.1 dst-ip lp0
>>>>     - 0.0.0.0/0 <http://0.0.0.0/0>  192.168.0.1 dst-ip
>>>>     -
>>>>     -IPv6 Routes
>>>>     -            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
>>>>     -          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
>>>>     -                     ::/0        2001:db8:0:f101::1 dst-ip
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
>>>>     -AT_CHECK([ovn-nbctl lr-add lr0])
>>>>     -
>>>>     -dnl Add policies with allow and drop actions
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>>>     <http://1.1.1.0/24>" drop])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24
>>>>     <http://1.1.2.0/24>" allow])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24
>>>>     <http://2.1.1.0/24>" allow])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24
>>>>     <http://2.1.2.0/24>" drop])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64"
>>>>     drop])
>>>>     -
>>>>     -dnl Add duplicated policy
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24
>>>>     <http://1.1.1.0/24>" drop], [1], [],
>>>>     -  [ovn-nbctl: Same routing policy already existed on the logical
>>>>     router lr0.
>>>>     -])
>>>>     -
>>>>     -dnl Add duplicated policy
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24
>>>>     <http://1.1.1.0/24>" deny], [1], [],
>>>>     -  [ovn-nbctl: deny: action must be one of "allow", "drop", and
>>>>     "reroute"
>>>>     -])
>>>>     -
>>>>     -dnl Delete by priority and match string
>>>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24
>>>>     <http://1.1.1.0/24>"])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>>>     -Routing Policies
>>>>     -       101                              ip4.src == 2.1.1.0/24
>>>>     <http://2.1.1.0/24>           allow
>>>>     -       101                              ip4.src == 2.1.2.0/24
>>>>     <http://2.1.2.0/24>            drop
>>>>     -       101                               ip6.src == 2002::/64
>>>>             drop
>>>>     -       100                              ip4.src == 1.1.2.0/24
>>>>     <http://1.1.2.0/24>           allow
>>>>     -])
>>>>     -
>>>>     -dnl Delete all policies for given priority
>>>>     -AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
>>>>     -AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
>>>>     -Routing Policies
>>>>     -       100                              ip4.src == 1.1.2.0/24
>>>>     <http://1.1.2.0/24>           allow
>>>>     -])
>>>>     -
>>>>     -dnl Add policy with reroute action
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24
>>>>     <http://3.1.2.0/24>" reroute 3.3.3.3])
>>>>     -
>>>>     -dnl Add policy with invalid reroute ip
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24
>>>>     <http://3.1.2.0/24>" reroute 3.3.3.x], [1], [],
>>>>     -  [ovn-nbctl: bad next hop argument: 3.3.3.x
>>>>     -])
>>>>     -
>>>>     -dnl Add policy with reroute action
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64"
>>>>     reroute 2002::5])
>>>>     -
>>>>     -dnl Add policy with invalid reroute ip
>>>>     -AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64"
>>>>     reroute 2002::x], [1], [],
>>>>     -  [ovn-nbctl: bad next hop argument: 2002::x
>>>>     -])
>>>>     -
>>>>     -])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
>>>>     -
>>>>     -dnl switchport type defaults to empty
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -
>>>>     -])
>>>>     -
>>>>     -dnl The following are the valid entries for
>>>>     -dnl switchport type
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -l2gateway
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -router
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -localnet
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -localport
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -vtep
>>>>     -])
>>>>     -
>>>>     -dnl All of these are valid southbound port types but
>>>>     -dnl should be rejected for northbound logical switch
>>>>     -dnl ports.
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
>>>>     -ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized.
>>>>     Not setting type.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
>>>>     -ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not
>>>>     setting type.
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], 
>>>> [], [dnl
>>>>     -ovn-nbctl: Logical switch port type 'chassisredirect' is
>>>>     unrecognized. Not setting type.
>>>>     -])
>>>>     -
>>>>     -dnl switch port type should still be "vtep" since previous
>>>>     -dnl commands failed.
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -vtep
>>>>     -])
>>>>     -
>>>>     -dnl Attempt a nonsense type
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
>>>>     -ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not
>>>>     setting type.
>>>>     -])
>>>>     -
>>>>     -dnl Empty string should work too
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
>>>>     -
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
>>>>     -AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection
>>>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
>>>>     -AT_CHECK([ovn-nbctl list connection | grep inactivity_probe],
>>>>     [0], [dnl
>>>>     -inactivity_probe    : 30000
>>>>     -inactivity_probe    : 30000
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
>>>>     -dnl Check that dry run has no permanent effect.
>>>>     -AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt],
>>>>     [0], [dnl
>>>>     -<0> (ls0)
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>>     -])
>>>>     -
>>>>     -dnl Check that dry-run mode is not sticky.
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
>>>>     -<0> (ls0)
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
>>>>     -
>>>>     -dnl Expect one line for one command.
>>>>     -AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
>>>>     -<0> (ls0)\n<1> (ls1)
>>>>     -])
>>>>     -
>>>>     -dnl Expect lines for two commands.
>>>>     -AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt],
>>>>     [0], [dnl
>>>>     -<0> (ls0)\n<1> (ls1)
>>>>     -<0> (ls0)\n<1> (ls1)
>>>>     -])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error
>>>>     paths], [
>>>>     -dnl FIXME: Duplicate options are allowed when passed with global
>>>>     options.
>>>>     -dnl        For example: ovn-nbctl --if-exists --if-exists list
>>>>     Logical_Switch
>>>>     -
>>>>     -dnl Duplicate option
>>>>     -AT_CHECK([ovn-nbctl -- --if-exists --if-exists list
>>>>     Logical_Switch], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'option specified multiple times' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -dnl Missing command
>>>>     -AT_CHECK([ovn-nbctl], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Unknown command
>>>>     -AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Unknown option
>>>>     -AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], 
>>>> [stderr])
>>>>     -AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], 
>>>> [stderr])
>>>>     -AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Missing option argument
>>>>     -AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'option .* requires an argument' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [],
>>>>     [stderr])
>>>>     -AT_CHECK([grep 'missing argument to .* option' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -dnl Unexpected option argument
>>>>     -AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1],
>>>>     [], [stderr])
>>>>     -AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .*
>>>>     requires an argument' stderr], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1],
>>>>     [], [stderr])
>>>>     -AT_CHECK([grep 'option on .* does not accept an argument'
>>>>     stderr], [0], [ignore])
>>>>     -
>>>>     -dnl Not enough arguments
>>>>     -AT_CHECK([ovn-nbctl list], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>>>     [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command requires at least .* arguments' stderr],
>>>>     [0], [ignore])
>>>>     -
>>>>     -dnl Too many arguments
>>>>     -AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>>     [ignore])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
>>>>     -AT_CHECK([grep 'command takes at most .* arguments' stderr], [0],
>>>>     [ignore])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
>>>>     -dnl Check that port group can be looked up by name
>>>>     -AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
>>>>     -pg0
>>>>     -])])
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
>>>>     -dnl This test addresses a specific issue seen when running
>>>>     ovn-nbctl in
>>>>     -dnl daemon mode. All we have to do is ensure that each time we
>>>>     list database
>>>>     -dnl information, there is not an extra newline at the beginning
>>>>     of the output.
>>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>>>     [dnl
>>>>     -name                : sw1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0],
>>>>     [dnl
>>>>     -name                : sw1
>>>>     -])])
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table 
>>>> formatting], [
>>>>     -dnl This test addresses a specific issue seen when running
>>>>     ovn-nbctl in
>>>>     -dnl daemon mode. We need to ensure that table formatting options
>>>>     are honored
>>>>     -dnl when listing database information.
>>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch
>>>>     sw1], [0], [dnl
>>>>     -sw1
>>>>     -])])
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group
>>>>     commands], [
>>>>     -AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group 
>>>> pg1], [0],
>>>>     -[pg1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
>>>>     -SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>>>     sw1-p1)
>>>>     -AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
>>>>     -SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port
>>>>     sw1-p2)
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1],
>>>>     [0],[dnl
>>>>     -pg1
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>>>     port_group pg1], [0], [dnl
>>>>     -$SW1P1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
>>>>     -AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list
>>>>     port_group pg1], [0], [dnl
>>>>     -$SW1P2
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
>>>>     -AT_CHECK([ovn-nbctl list port_group], [0], [])
>>>>     -])
>>>>     -
>>>>     -AT_SETUP([ovn-nbctl - daemon retry connection])
>>>>     -OVN_NBCTL_TEST_START daemon
>>>>     -AT_CHECK([kill `cat ovsdb-server.pid`])
>>>>     -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file
>>>>     --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [],
>>>>     [stderr])
>>>>     -AT_CHECK([ovn-nbctl show], [0], [ignore])
>>>>     -OVN_NBCTL_TEST_STOP /Terminated/d
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn-northd.at <http://ovn-northd.at>
>>>>     b/tests/ovn-northd.at <http://ovn-northd.at>
>>>>     deleted file mode 100644
>>>>     index 62e58fd..0000000
>>>>     --- a/tests/ovn-northd.at <http://ovn-northd.at>
>>>>     +++ /dev/null
>>>>     @@ -1,900 +0,0 @@
>>>>     -AT_BANNER([OVN northd])
>>>>     -AT_SETUP([ovn -- check   from NBDB to SBDB])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>>     -
>>>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl --wait=sb \
>>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>>     -                                     chassis_name=gw1 \
>>>>     -                                     priority=20 -- \
>>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>>     -                                     chassis_name=gw2 \
>>>>     -                                     priority=10 -- \
>>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>>     Gateway_Chassis name="alice_gw1"`
>>>>     -
>>>>     -# With the new ha_chassis_group table added, there should be no
>>>>     rows in
>>>>     -# gateway_chassis table in SB DB.
>>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# There should be one ha_chassis_group with the name "alice"
>>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="alice"`
>>>>     -
>>>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>>>     -
>>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=alice`
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>>     port_binding \
>>>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# There should be one ha_chassis_group with the name "alice"
>>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="alice"`
>>>>     -
>>>>     -AT_CHECK([test $ha_chassi_grp_name = alice])
>>>>     -
>>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=alice`
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>>     port_binding \
>>>>     -logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>>> ha_chassis_group`
>>>>     -# Trim the spaces.
>>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>>     -
>>>>     -ha_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list="$ha_ch_list $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>>     -
>>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>>     -
>>>>     -# Delete chassis - gw2 in SB DB.
>>>>     -# ovn-northd should not recreate ha_chassis rows
>>>>     -# repeatedly when gw2 is deleted.
>>>>     -ovn-sbctl chassis-del gw2
>>>>     -
>>>>     -ha_ch_list_1=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>>>     -
>>>>     -ha_ch_list_2=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>>>     -
>>>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>>>     -
>>>>     -# Add back the gw2 chassis
>>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>>     -
>>>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>>>     -gw_ch=`ovn-sbctl --bare --columns gateway_chassis find 
>>>> port_binding \
>>>>     -logical_port="cr-alice"`
>>>>     -AT_CHECK([test "$gw_ch" = ""])
>>>>     -
>>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>>> ha_chassis_group`
>>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>>     -# Trim the spaces.
>>>>     -echo "ha ch in grp = $ha_ch"
>>>>     -
>>>>     -ha_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list="$ha_ch_list $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>>     -
>>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>>     -
>>>>     -# delete the 2nd Gateway_Chassis on NBDB for alice port
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port alice
>>>>     gateway_chassis=${nb_gwc1_uuid}
>>>>     -
>>>>     -# There should be only 1 row in ha_chassis SB DB table.
>>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>>     -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# There should be only 1 row in ha_chassis SB DB table.
>>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>>     -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# delete all the gateway_chassis on NBDB for alice port
>>>>     -
>>>>     -ovn-nbctl --wait=sb clear Logical_Router_Port alice 
>>>> gateway_chassis
>>>>     -
>>>>     -# expect that the ha_chassis doesn't exist anymore
>>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# expect that the ha_chassis doesn't exist anymore
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to
>>>>     SBDB backwards compatibility])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>>     -ovn-sbctl chassis-add gw2 geneve 1.2.4.8
>>>>     -
>>>>     -ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03
>>>>     172.16.1.1/24 <http://172.16.1.1/24> \
>>>>     -    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
>>>>     -
>>>>     -
>>>>     -# It should be converted to ha_chassis_group entries in SBDB, and
>>>>     -# still redirect-chassis is kept for backwards compatibility
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc
>>>>     -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group
>>>>     | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# There should be one ha_chassis_group with the name "bob_gw1"
>>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="bob_gw1"`
>>>>     -
>>>>     -AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
>>>>     -
>>>>     -ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=bob_gw1`
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find
>>>>     port_binding \
>>>>     -logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb remove Logical_Router_Port bob options
>>>>     redirect-chassis
>>>>     -
>>>>     -# expect that the ha_chassis/ha_chassis_group doesn't exist 
>>>> anymore
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check up state of VIF LSP])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add S1
>>>>     -ovn-nbctl --wait=sb lsp-add S1 S1-vm1
>>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
>>>>     -
>>>>     -ovn-sbctl chassis-add hv1 geneve 127.0.0.1
>>>>     -ovn-sbctl lsp-bind S1-vm1 hv1
>>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check up state of router LSP linked to a
>>>>     distributed LR])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl ls-add S1
>>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check up state of router LSP linked to a gateway
>>>>     LR])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
>>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl ls-add S1
>>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>>     -ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
>>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>>     -
>>>>     -ovn-sbctl lsp-bind S1-R1 gw1
>>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check up state of router LSP linked to an LRP
>>>>     with set Gateway Chassis])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-sbctl chassis-add gw1 geneve 127.0.0.1
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
>>>>     -
>>>>     -ovn-nbctl ls-add S1
>>>>     -ovn-nbctl lsp-add S1 S1-R1
>>>>     -ovn-nbctl lsp-set-type S1-R1 router
>>>>     -ovn-nbctl lsp-set-addresses S1-R1 router
>>>>     -ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
>>>>     -AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl lr-add ro
>>>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 
>>>> aef0:0:0:0:0:0:0:1/64
>>>>     -ovn-nbctl ls-add sw
>>>>     -ovn-nbctl lsp-add sw sw-ro
>>>>     -ovn-nbctl lsp-set-type sw-ro router
>>>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:send_periodic=true
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:address_mode=slaac
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:mtu=1280
>>>>     -
>>>>     -uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding
>>>>     logical_port=ro-sw)
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_send_periodic],
>>>>     -[0], ["true"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_address_mode],
>>>>     -[0], [slaac
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[0], ["600"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[0], ["200"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid} 
>>>> options:ipv6_ra_mtu],
>>>>     -[0], ["1280"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_src_eth],
>>>>     -[0], ["00:00:00:00:00:01"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_src_addr],
>>>>     -[0], ["fe80::200:ff:fe00:1"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_prefixes],
>>>>     -[0], ["aef0::/64"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:max_interval=300
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:min_interval=600
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[0], ["300"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[0], ["225"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:max_interval=300
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:min_interval=250
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[0], ["300"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[0], ["225"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:max_interval=0
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:min_interval=0
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[0], ["4"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[0], ["3"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:max_interval=3600
>>>>     -ovn-nbctl --wait=sb set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:min_interval=2400
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[0], ["1800"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[0], ["1350"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb set Logical_Router_port ro-sw
>>>>     ipv6_ra_configs:send_periodic=false
>>>>     -
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_send_periodic],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in
>>>>     Port_Binding record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_max_interval],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in
>>>>     Port_Binding record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_min_interval],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in
>>>>     Port_Binding record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_mtu],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record
>>>>     "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_address_mode],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in
>>>>     Port_Binding record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_src_eth],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding
>>>>     record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_src_addr],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding
>>>>     record "${uuid}" column options
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid}
>>>>     options:ipv6_ra_prefixes],
>>>>     -[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding
>>>>     record "${uuid}" column options
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- test unixctl])
>>>>     -ovn_init_db ovn-sb; ovn-sbctl init
>>>>     -ovn_init_db ovn-nb; ovn-nbctl init
>>>>     -
>>>>     -# test unixctl option
>>>>     -mkdir "$ovs_base"/northd
>>>>     -as northd start_daemon ovn-northd
>>>>     --unixctl="$ovs_base"/northd/ovn-northd.ctl
>>>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -ovn-nbctl ls-add sw
>>>>     -ovn-nbctl --wait=sb lsp-add sw p1
>>>>     -# northd created with unixctl option successfully created
>>>>     port_binding entry
>>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>>     logical_port="p1" | wc -l], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
>>>>     -
>>>>     -# ovs-appctl exit with unixctl option
>>>> -OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl],
>>>>     ["$ovs_base"/northd/ovn-northd.pid])
>>>>     -
>>>>     -# Check no port_binding entry for new port as ovn-northd is not
>>>>     running
>>>>     -ovn-nbctl lsp-add sw p2
>>>>     -ovn-nbctl --timeout=10 --wait=sb sync
>>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>>     logical_port="p2" | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# test default unixctl path
>>>>     -as northd start_daemon ovn-northd
>>>>     --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock
>>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -ovn-nbctl --wait=sb lsp-add sw p3
>>>>     -# northd created with default unixctl path successfully created
>>>>     port_binding entry
>>>>     -AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding
>>>>     logical_port="p3" | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -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])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to
>>>>     SBDB])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>>     -
>>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>>> rows
>>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>>     -# a logical router port or logical port of type external.
>>>>     -AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group
>>>>     name="hagrp1" \
>>>>     -| wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>>>     -
>>>>     -# There should be no HA_Chassis rows in SB DB.
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>>>     $3}' \
>>>>     -| grep -v '-' | wc -l ], [0], [0
>>>>     -])
>>>>     -
>>>>     -# Add chassis ch1.
>>>>     -ovn-sbctl chassis-add ch1 geneve 127.0.0.2
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc
>>>>     -l`])
>>>>     -
>>>>     -# There should be no HA_Chassis rows
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print
>>>>     $3}' \
>>>>     -| grep -v '-' | wc -l ], [0], [0
>>>>     -])
>>>>     -
>>>>     -# Create a logical router port and attach ha chassis group.
>>>>     -ovn-nbctl lr-add lr0
>>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13
>>>>     172.168.0.100/24 <http://172.168.0.100/24>
>>>>     -
>>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=hagrp1`
>>>>     -ovn-nbctl set logical_router_port lr0-public
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Make sure that ovn-northd doesn't recreate the ha_chassis
>>>>     -# records if the chassis record is missing in SB DB.
>>>>     -
>>>>     -ha_ch_list_1=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list_1="$ha_ch_list_1 $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
>>>>     -
>>>>     -ha_ch_list_2=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list_2="$ha_ch_list_2 $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
>>>>     -
>>>>     -AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
>>>>     -
>>>>     -# 2 HA chassis should be created with 'chassis' column empty 
>>>> because
>>>>     -# we have not added hv1 and hv2 chassis to the SB DB.
>>>>     -AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis |
>>>>     awk '{print $3}' \
>>>>     -| grep -v '-' | wc -l`])
>>>>     -
>>>>     -# We should have 1 ha chassis with 'chassis' column set for hv1
>>>>     -AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | awk '{print $3}' \
>>>>     -| grep '-' | wc -l`])
>>>>     -
>>>>     -# Create another logical router port and associate to the same
>>>>     ha_chasis_group
>>>>     -ovn-nbctl lr-add lr1
>>>>     -ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14
>>>>     182.168.0.100/24 <http://182.168.0.100/24>
>>>>     -
>>>>     -ovn-nbctl set logical_router_port lr1-public
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -# We should still have 1 HA chassis group and 3 HA chassis in 
>>>> SB DB.
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Change the priority of ch1 - ha chassis in NB DB. It should get
>>>>     -# reflected in SB DB.
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority 
>>>> find \
>>>>     -ha_chassis | grep 100 | wc -l`])
>>>>     -
>>>>     -# Delete ch1 HA chassis in NB DB.
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>>     chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Add back the ha chassis
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
>>>>     -OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep
>>>>     chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Delete lr0-public. We should still have 1 HA chassis group and
>>>>     -# 3 HA chassis in SB DB.
>>>>     -ovn-nbctl --wait=sb lrp-del lr0-public
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Delete lr1-public. There should be no HA chassis group in SB 
>>>> DB.
>>>>     -ovn-nbctl --wait=sb lrp-del lr1-public
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>>>     -l`])
>>>>     -
>>>>     -# Add lr0-public again
>>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 
>>>> 172.168.0.100/24
>>>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> set
>>>>     logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Create a Gateway chassis. ovn-northd should ignore this.
>>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
>>>>     -
>>>>     -# There should be only 1 HA chassis group in SB DB with the
>>>>     -# name hagrp1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Now delete HA chassis group. ovn-northd should create HA
>>>>     chassis group
>>>>     -# with the Gateway chassis name
>>>>     -ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
>>>>     -ovn-nbctl ha-chassis-group-del hagrp1
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>>>     -find ha_chassis | wc -l`])
>>>>     -
>>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>>     -
>>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>>     chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Test if 'ref_chassis' column is properly set or not in
>>>>     -# SB DB ha_chassis_group.
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>>>     -
>>>>     -ovn-sbctl chassis-add ch2 geneve 127.0.0.3
>>>>     -ovn-sbctl chassis-add ch3 geneve 127.0.0.4
>>>>     -ovn-sbctl chassis-add comp1 geneve 127.0.0.5
>>>>     -ovn-sbctl chassis-add comp2 geneve 127.0.0.6
>>>>     -
>>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
>>>>     <http://10.0.0.1/24>
>>>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>>>     -
>>>>     -ovn-sbctl lsp-bind sw0-p1 comp1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
>>>>     -
>>>>     -comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="comp1"`
>>>>     -comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="comp2"`
>>>>     -ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="comp1"`
>>>>     -
>>>>     -echo "comp1_ch_uuid = $comp1_ch_uuid"
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp1_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# unbind sw0-p1
>>>>     -ovn-sbctl lsp-unbind sw0-p1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "" = "$ref_ch_list"])
>>>>     -
>>>>     -# Bind sw0-p1 in comp2
>>>>     -ovn-sbctl lsp-bind sw0-p1 comp2
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>>>     -ovn-nbctl lr-add lr1
>>>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add sw1 sw1-lr1
>>>>     -ovn-nbctl lsp-set-type sw1-lr1 router
>>>>     -ovn-nbctl lsp-set-addresses sw1-lr1 router
>>>>     -ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
>>>>     -
>>>>     -# Bind sw1-p1 in comp1.
>>>>     -ovn-sbctl lsp-bind sw1-p1 comp1
>>>>     -# Wait until sw1-p1 is up
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
>>>>     -
>>>>     -# sw1-p1 is not connected to lr0. So comp1 should not be in
>>>>     'ref_chassis'
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Now attach sw0 to lr1
>>>>     -ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
>>>>     <http://10.0.0.10/24>
>>>>     -ovn-nbctl lsp-add sw0 sw0-lr1
>>>>     -ovn-nbctl lsp-set-type sw0-lr1 router
>>>>     -ovn-nbctl lsp-set-addresses sw0-lr1 router
>>>>     -ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
>>>>     -
>>>>     -# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is
>>>>     indirectly
>>>>     -# connected to lr0
>>>>     -exp_ref_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>>     -do
>>>>     -    if test $i = $comp1_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    elif test $i = $comp2_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    fi
>>>>     -done
>>>>     -
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# Unind sw1-p1. comp2 should not be in the ref_chassis.
>>>>     -ovn-sbctl lsp-unbind sw1-p1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Create sw2 and attach it to lr2
>>>>     -ovn-nbctl ls-add sw2
>>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>>     -ovn-nbctl lr-add lr2
>>>>     -ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
>>>>     <http://30.0.0.1/24>
>>>>     -ovn-nbctl lsp-add sw2 sw2-lr2
>>>>     -ovn-nbctl lsp-set-type sw2-lr2 router
>>>>     -ovn-nbctl lsp-set-addresses sw2-lr2 router
>>>>     -ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
>>>>     -
>>>>     -# Bind sw2-p1 to comp1
>>>>     -ovn-sbctl lsp-bind sw2-p1 comp1
>>>>     -# Wait until sw2-p1 is up
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
>>>>     -
>>>>     -# sw2-p1 is not connected to lr0. So comp1 should not be in
>>>>     'ref_chassis'
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected
>>>>     to lr0.
>>>>     -ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
>>>>     <http://20.0.0.10/24>
>>>>     -ovn-nbctl lsp-add sw1 sw1-lr2
>>>>     -ovn-nbctl lsp-set-type sw1-lr2 router
>>>>     -ovn-nbctl lsp-set-addresses sw1-lr2 router
>>>>     -ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
>>>>     -
>>>>     -# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2)
>>>>     should be in
>>>>     -# 'ref_chassis'
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# Create sw0-p2 and bind it to comp1
>>>>     -ovn-nbctl lsp-add sw0 sw0-p2
>>>>     -ovn-sbctl lsp-bind sw0-p2 comp1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# unbind sw0-p2
>>>>     -ovn-sbctl lsp-unbind sw0-p2
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# Delete lr1-sw0. comp1 should be deleted from ref_chassis as
>>>>     there is no link
>>>>     -# from sw1 and sw2 to lr0.
>>>>     -ovn-nbctl lrp-del lr1-sw0
>>>>     -
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$comp2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Set redirect-chassis option to lr0-public. It should be 
>>>> ignored.
>>>>     -ovn-nbctl set logical_router_port lr0-public
>>>>     options:redirect-chassis=ch1
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="lr0-public" | wc -l`])
>>>>     -
>>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>>     chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Delete the gateway chassis. HA chassis group should be created
>>>>     in SB DB
>>>>     -# for the redirect-chassis option.
>>>>     -ovn-nbctl clear logical_router_port lr0-public gateway_chassis
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group | wc -l`])
>>>>     -
>>>>     -ovn-sbctl list ha_chassis_group
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="lr0-public_ch1" | wc -l`])
>>>>     -
>>>>     -ovn-sbctl --bare --columns _uuid find ha_chassis
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep 
>>>> chassis |
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Clear the redirect-chassis option.
>>>>     -ovn-nbctl clear logical_router_port lr0-public options
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  
>>>> wc -l`])
>>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>>     -
>>>>     -# Delete old sw0.
>>>>     -ovn-nbctl ls-del sw0
>>>>     -
>>>>     -# Create external logical ports and associate ha_chassis_group
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl lsp-add sw0 sw0-pext1
>>>>     -ovn-nbctl lsp-add sw0 sw0-pext2
>>>>     -ovn-nbctl lsp-add sw0 sw0-p1
>>>>     -
>>>>     -ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 
>>>> 10.0.0.3"
>>>>     -ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 
>>>> 10.0.0.4"
>>>>     -ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
>>>>     -
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>>     -
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
>>>>     -
>>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>>> rows
>>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>>     -# a logical router port or logical port of type external.
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  
>>>> wc -l`])
>>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>>     -
>>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find 
>>>> ha_chassis_group \
>>>>     -name=hagrp1`
>>>>     -
>>>>     -# The type of the lsp - sw0-pext1 is still not set to external.
>>>>     -# So ha_chassis_group should be ignored.
>>>>     -ovn-nbctl set logical_switch_port sw0-pext1
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc
>>>>     -l`])
>>>>     -
>>>>     -# Set the type of sw0-pext1 to external
>>>>     -ovn-nbctl lsp-set-type sw0-pext1 external
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>>>     ha_chassis_group \
>>>>     -name=hagrp1`
>>>>     -
>>>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>>>     -
>>>>     -# Set the type of sw0-pext2 to external and associate
>>>>     ha_chassis_group
>>>>     -ovn-nbctl lsp-set-type sw0-pext2 external
>>>>     -ovn-nbctl set logical_switch_port sw0-pext2
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
>>>>     -ha_chassis_group find port_binding logical_port=sw0-pext1`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare
>>>>     --columns \
>>>>     -ha_chassis_group find port_binding logical_port=sw0-pext2`])
>>>>     -
>>>>     -# sw0-p1 is a normal port. So ha_chassis_group should not be set
>>>>     -# in port_binding.
>>>>     -ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
>>>>     -ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding \
>>>>     -logical_port=sw0-p1) = x], [0], [])
>>>>     -
>>>>     -# Clear ha_chassis_group for sw0-pext1
>>>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1
>>>>     ha_chassis_group
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding \
>>>>     -logical_port=sw0-pext1) = x], [0], [])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="hagrp1" | wc -l`])
>>>>     -
>>>>     -AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -# Clear ha_chassis_group for sw0-pext2
>>>>     -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2
>>>>     ha_chassis_group
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding \
>>>>     -logical_port=sw0-pext2) = x], [0], [])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  
>>>> wc -l`])
>>>>     -AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>>     -
>>>>     -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])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn-performance.at <http://ovn-performance.at>
>>>>     b/tests/ovn-performance.at <http://ovn-performance.at>
>>>>     deleted file mode 100644
>>>>     index a8a15f8..0000000
>>>>     --- a/tests/ovn-performance.at <http://ovn-performance.at>
>>>>     +++ /dev/null
>>>>     @@ -1,424 +0,0 @@
>>>>     -#
>>>>     -# Tests targeting performance of OVN components.
>>>>     -#
>>>>     -
>>>>     -m4_divert_push([PREPARE_TESTS])
>>>>     -
>>>>     -# vec_cmp VALUE_VEC OP-VALUE_VEC
>>>>     -#
>>>>     -# Compares each value from VALUE_VEC to the operator-value pair
>>>>     from the
>>>>     -# OP-VALUE_VEC.
>>>>     -#
>>>>     -# VALUE_VEC must be a list of values separated by a character
>>>>     from $IFS.
>>>>     -# OP-VALUE_VEC must be a list of operator-value expressions
>>>>     separated by a
>>>>     -# character from $IFS.  Operator-value expressions cannot contain
>>>>     any characters
>>>>     -# from $IFS like spaces. '=' is treated as an equality operator
>>>>     ('==') for
>>>>     -# conciseness.
>>>>     -#
>>>>     -# Returns the result of each comparison as a list of boolean
>>>>     values (0 or 1)
>>>>     -# separated by a new-line character.
>>>>     -vec_cmp() {
>>>>     -    local a b i j
>>>>     -
>>>>     -    i=0
>>>>     -    for a in $1; do
>>>>     -        j=0
>>>>     -        for b in $2; do
>>>>     -            if test $i -eq $j; then
>>>>     -                # Replace assignment '=' with equality comparison
>>>>     '=='
>>>>     -                case "$b" in
>>>>     -                =[[0-9]]*) b="=$b" ;;
>>>>     -                esac
>>>>     -
>>>>     -                echo $(($a $b))
>>>>     -                break
>>>>     -            fi
>>>>     -            j=$((j + 1))
>>>>     -        done
>>>>     -        i=$((i + 1))
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# vec_sub VEC_A VEC_B
>>>>     -#
>>>>     -# Subtracts two vectors:
>>>>     -#
>>>>     -#     VEC_A = [a1, a2, ...]
>>>>     -#     VEC_B = [b1, b2, ...]
>>>>     -#     OUT = [(a1 - b1), (a2 - b2), ...]
>>>>     -#
>>>>     -# VEC_A and VEC_B must be lists of values separated by a
>>>>     character from $IFS.
>>>>     -vec_sub() {
>>>>     -    local a b i j
>>>>     -
>>>>     -    i=0
>>>>     -    for a in $1; do
>>>>     -        j=0
>>>>     -        for b in $2; do
>>>>     -            if test $i -eq $j; then
>>>>     -                echo $((a - b))
>>>>     -                break
>>>>     -            fi
>>>>     -            j=$((j + 1))
>>>>     -        done
>>>>     -        i=$((i + 1))
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# vec_fold VEC OP
>>>>     -#
>>>>     -# Reduces a vector to a single value by applying the binary
>>>>     operator OP (i.e.,
>>>>     -# one that requires two arguments) cumulatively to all vector
>>>>     elements from left
>>>>     -# to right:
>>>>     -#
>>>>     -#     VEC = [e1, e2, e3 ...]
>>>>     -#     OUT = (...((e1 OP e2) OP e3) OP ...)
>>>>     -#
>>>>     -# VEC must be a list of values separated by a character from 
>>>> $IFS.
>>>>     -vec_fold() {
>>>>     -    local first op prod
>>>>     -
>>>>     -    first=1
>>>>     -    op=$2
>>>>     -    for a in $1; do
>>>>     -        if test $first -eq 1; then
>>>>     -            prod=$a
>>>>     -            first=0
>>>>     -        else
>>>>     -            prod=$((prod $op a))
>>>>     -        fi
>>>>     -    done
>>>>     -    echo $prod
>>>>     -}
>>>>     -
>>>>     -# read_counters SANDBOXES TARGET COUNTER
>>>>     -#
>>>>     -# Prints out the coverage COUNTER for the TARGET in each of the
>>>>     SANDBOXES.
>>>>     -#
>>>>     -# SANDBOXES must be a list of strings separated by a character
>>>>     from $IFS.
>>>>     -read_counters() {
>>>>     -    local sims="$1" target="$2" counter="$3"
>>>>     -
>>>>     -    for sim in $sims; do
>>>>     -        as $sim ovs-appctl -t "$target" coverage/read-counter
>>>>     "$counter" || return 1
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
>>>>     -#
>>>>     -# Runs the COMMAND and reports the COUNTER change registered
>>>>     during the command
>>>>     -# run for the given TARGET in each of the SANDBOXES.
>>>>     -counter_delta_() {
>>>>     -    local sims="$1" target="$2" counter="$3" cmd="$4"
>>>>     -    local before after
>>>>     -
>>>>     -    before=$(read_counters "$sims" "$target" "$counter") || 
>>>> return 1
>>>>     -    eval "$cmd" >/dev/null || return 1
>>>>     -    after=$(read_counters "$sims" "$target" "$counter") || 
>>>> return 1
>>>>     -
>>>>     -    vec_sub "$after" "$before"
>>>>     -}
>>>>     -
>>>>     -# counter_delta SANDBOXES TARGET COUNTER COMMAND
>>>>     -#
>>>>     -# Same as counter_delta_ but also prints the COUNTER values
>>>>     together with the
>>>>     -# COMMAND to standard error.
>>>>     -counter_delta() {
>>>>     -    local cmd="$4"
>>>>     -    local v
>>>>     -
>>>>     -    v=$(counter_delta_ "$@") || return 1
>>>>     -
>>>>     -    # Dump the counters and the command for troubleshooting
>>>>     -    echo "$v" | tr '\n' '\t' >&2
>>>>     -    echo "$cmd" >&2
>>>>     -
>>>>     -    echo "$v"
>>>>     -}
>>>>     -
>>>>     -# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
>>>>     -#
>>>>     -# Check if COUNTER change in the TARGET app in each of the
>>>>     SANDBOXES after
>>>>     -# running the COMMAND meets the conditions listed as
>>>>     operator-value pairs in
>>>>     -# CONDS.
>>>>     -vec_cmp_counter_delta() {
>>>>     -    local v
>>>>     -
>>>>     -    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
>>>>     -    v=$(vec_cmp "$v" "$4") || return 1
>>>>     -    v=$(vec_fold "$v" "&&") || return 1
>>>>     -
>>>>     -    echo "$v"
>>>>     -}
>>>>     -
>>>>     -# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
>>>>     -#
>>>>     -# Check if COUNTER change in the TARGET app in each of the
>>>>     SANDBOXES after
>>>>     -# running the COMMAND meets the COND condition given as a
>>>>     operator-value pair.
>>>>     -cmp_counter_delta() {
>>>>     -    local conds=""
>>>>     -
>>>>     -    # Use the same condition for each sandbox
>>>>     -    for _ in $1; do
>>>>     -        conds="$conds $4"
>>>>     -    done
>>>>     -
>>>>     -    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
>>>>     -}
>>>>     -
>>>>     -m4_divert_pop([PREPARE_TESTS])
>>>>     -
>>>>     -# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
>>>>     -#
>>>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>>>     in all of
>>>>     -# the SANDBOXES did not change.
>>>>     -m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
>>>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
>>>>     -    rc=$?
>>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>>     -])
>>>>     -
>>>>     -# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER 
>>>> COMMAND
>>>>     -#
>>>>     -# Runs the COMMAND and checks if the COUNTER value for the 
>>>> TARGET in
>>>>     -# all of the SANDBOXES has changed.
>>>>     -m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
>>>>     -    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
>>>>     -    rc=$?
>>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>>     -])
>>>>     -
>>>>     -# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
>>>>     -#
>>>>     -# Runs the COMMAND and checks if the COUNTER value for the TARGET
>>>>     in all of the
>>>>     -# SANDBOXES satisfies the conditions listed in CONDS.
>>>>     -m4_define([CHECK_COUNTER_DELTA_COND],[
>>>>     -    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
>>>>     -    rc=$?
>>>>     -    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
>>>>     -])
>>>>     -
>>>>     -# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
>>>>     -#
>>>>     -# Checks if the COUNTER value has changed for any of the
>>>>     ovn-controller
>>>>     -# processes in the SANDBOXES when the COMMAND was run.
>>>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT],[
>>>>     -    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2],
>>>>     [$3])
>>>>     -])
>>>>     -
>>>>     -# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
>>>>     -#
>>>>     -# Checks if the COUNTER value has not changed for any of the
>>>>     ovn-controller
>>>>     -# processes in the SANDBOXES when the COMMAND was run.
>>>>     -m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
>>>>     -    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], 
>>>> [$3])
>>>>     -])
>>>>     -
>>>>     -# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
>>>>     -#
>>>>     -# Checks if the change of the COUNTER value, when the COMMAND was
>>>>     run, of the
>>>>     -# ovn-controller process in each of the SANDBOXES meets the
>>>>     conditions in
>>>>     -# CONDS. CONDS must be a list of operator-value pairs, for
>>>>     example "[>0 =0]",
>>>>     -# following the same order as SANDBOXES.
>>>>     -m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
>>>>     -    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3],
>>>>     [$4])
>>>>     -])
>>>>     -
>>>>     -AT_SETUP([ovn -- ovn-controller incremental processing])
>>>>     -# Check which operations the trigger full logical flow 
>>>> processing.
>>>>     -#
>>>>     -# Create and destroy logical routers, switches, ports, address
>>>>     sets and ACLs
>>>>     -# while counting calls to lflow_run() in ovn-controller.
>>>>     -
>>>>     -ovn_start
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -done
>>>>     -
>>>>     -# Add router lr1
>>>>     -OVN_CONTROLLER_EXPECT_HIT(
>>>>     -    [hv1 hv2], [lflow_run],
>>>>     -    [ovn-nbctl --wait=hv lr-add lr1]
>>>>     -)
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    ls=ls$i
>>>>     -    lsp=$ls-lr1
>>>>     -    lrp=lr1-$ls
>>>>     -
>>>>     -    # Add switch $ls
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv ls-add $ls]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config
>>>>     subnet=10.0.$i.0/24]
>>>>     -    )
>>>>     -
>>>>     -    # Add router port to $ls
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01
>>>>     10.0.$i.1/24]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-set-options $lsp 
>>>> router-port=$lrp]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
>>>>     -    )
>>>>     -done
>>>>     -
>>>>     -get_lsp_uuid () {
>>>>     -    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
>>>>     -}
>>>>     -
>>>>     -pg_ports=
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    j=$((i%2 + 1))
>>>>     -    as=as$i
>>>>     -    ls=ls$i
>>>>     -    lp=lp$i
>>>>     -    vif=vif$i
>>>>     -
>>>>     -    # Add port $lp
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-add $ls $lp]
>>>>     -    )
>>>>     -
>>>>     -    pg_ports="$pg_port `get_lsp_uuid $lp`"
>>>>     -
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl wait-until Logical_Switch_Port $lp
>>>>     dynamic_addresses!=[[]] &&
>>>>     -         ovn-nbctl --wait=hv sync]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl get Logical_Switch_Port $lp 
>>>> dynamic_addresses &&
>>>>     -         ovn-nbctl --wait=hv sync]
>>>>     -    )
>>>>     -
>>>>     -    # Add address set $as
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv create Address_Set name="$as"]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv add Address_Set "$as" addresses
>>>>     "10.0.$i.10"]
>>>>     -    )
>>>>     -
>>>>     -    # Add ACLs for port $lp
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport
>>>>     == \"$lp\" && ip4.src == \$$as' allow]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport
>>>>     == \"$lp\"' drop]
>>>>     -    )
>>>>     -
>>>>     -    # Bind port $lp and wait for it to come up
>>>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>>>     -        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface
>>>>     $vif external-ids:iface-id=$lp &&
>>>>     -         ovn-nbctl wait-until Logical_Switch_Port $lp 
>>>> 'up=true' &&
>>>>     -         ovn-nbctl --wait=hv sync]
>>>>     -    )
>>>>     -done
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    j=$((i%2 + 1))
>>>>     -    as=as$i
>>>>     -    ls=ls$i
>>>>     -    lp=lp$i
>>>>     -
>>>>     -    # Delete ACLs for port $lp
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport
>>>>     == \"$lp\" && ip4.src == \$$as']
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport
>>>>     == \"$lp\"']
>>>>     -    )
>>>>     -
>>>>     -    # Delete address set $as
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses
>>>>     "10.0.$i.10"]
>>>>     -    )
>>>>     -    OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
>>>>     -    )
>>>>     -done
>>>>     -
>>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -    [hv1 hv2], [lflow_run],
>>>>     -    [ovn-nbctl --wait=hv create Port_Group name=pg1
>>>>     ports=\"$pg_ports\"]
>>>>     -)
>>>>     -
>>>>     -# Add ACLs for port group pg1
>>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -    [hv1 hv2], [lflow_run],
>>>>     -    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport ==
>>>>     @pg1 && ip4.src == $pg1_ip4' allow]
>>>>     -)
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    j=$((i%2 + 1))
>>>>     -    lp=lp$i
>>>>     -
>>>>     -    # Delete port $lp
>>>>     -    OVN_CONTROLLER_EXPECT_HIT_COND(
>>>>     -        [hv$i hv$j], [lflow_run], [>0 =0],
>>>>     -        [ovn-nbctl --wait=hv lsp-del $lp]
>>>>     -    )
>>>>     -done
>>>>     -
>>>>     -# Delete port group pg1
>>>>     -OVN_CONTROLLER_EXPECT_NO_HIT(
>>>>     -    [hv1 hv2], [lflow_run],
>>>>     -    [ovn-nbctl --wait=hv destroy Port_Group pg1]
>>>>     -)
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    ls=ls$i
>>>>     -
>>>>     -    # Delete switch $ls
>>>>     -    OVN_CONTROLLER_EXPECT_HIT(
>>>>     -        [hv1 hv2], [lflow_run],
>>>>     -        [ovn-nbctl --wait=hv ls-del $ls]
>>>>     -    )
>>>>     -done
>>>>     -
>>>>     -# Delete router lr1
>>>>     -OVN_CONTROLLER_EXPECT_HIT(
>>>>     -    [hv1 hv2], [lflow_run],
>>>>     -    [ovn-nbctl --wait=hv lr-del lr1]
>>>>     -)
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>>     b/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>>     deleted file mode 100644
>>>>     index 650e357..0000000
>>>>     --- a/tests/ovn-sbctl.at <http://ovn-sbctl.at>
>>>>     +++ /dev/null
>>>>     @@ -1,150 +0,0 @@
>>>>     -AT_BANNER([ovn-sbctl])
>>>>     -
>>>>     -# OVN_SBCTL_TEST_START
>>>>     -m4_define([OVN_SBCTL_TEST_START],
>>>>     -  [dnl Create databases (ovn-nb, ovn-sb).
>>>>     -   AT_KEYWORDS([ovn])
>>>>     -   for daemon in ovn-nb ovn-sb; do
>>>>     -      AT_CHECK([ovsdb-tool create $daemon.db
>>>>     $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
>>>>     -   done
>>>>     -
>>>>     -   dnl Start ovsdb-servers.
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>>     --pidfile=ovnnb_db.pid --unixctl=$OVS_RUNDIR/ovnnb_db.ctl
>>>>     --log-file=ovsdb_nb.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock
>>>>     ovn-nb.db ], [0], [], [stderr])
>>>>     -   AT_CHECK([ovsdb-server --detach --no-chdir
>>>>     --pidfile=ovnsb_db.pid --unixctl=$OVS_RUNDIR/ovnsb_db.ctl
>>>>     --log-file=ovsdb_sb.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock
>>>>     ovn-sb.db], [0], [], [stderr])
>>>>     -   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d
>>>>     -/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
>>>>     -   AT_CAPTURE_FILE([ovsdb-server.log])
>>>>     -
>>>>     -   dnl Start ovn-northd.
>>>>     -   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file
>>>>     --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock
>>>>     --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
>>>>     -   on_exit "kill `cat ovn-northd.pid`"
>>>>     -   AT_CHECK([[sed < stderr '
>>>>     -/vlog|INFO|opened log file/d']])
>>>>     -   AT_CAPTURE_FILE([ovn-northd.log])
>>>>     -])
>>>>     -
>>>>     -# OVN_SBCTL_TEST_STOP
>>>>     -m4_define([OVN_SBCTL_TEST_STOP],
>>>>     -  [AT_CHECK([check_logs "$1"])
>>>>     -   OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl],
>>>>     [$OVS_RUNDIR/ovnnb_db.pid])
>>>>     -  OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl],
>>>>     [$OVS_RUNDIR/ovnsb_db.pid])])
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -AT_SETUP([ovn-sbctl - chassis commands])
>>>>     -OVN_SBCTL_TEST_START
>>>>     -ovn_init_db ovn-sb
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
>>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>>     ip,type list encap | sort],
>>>>     -         [0], [dnl
>>>>     -1.2.3.4,geneve
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
>>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>>     ip,type list encap | sort],
>>>>     -         [0], [dnl
>>>>     -1.2.3.4,geneve
>>>>     -1.2.3.5,geneve
>>>>     -1.2.3.5,stt
>>>>     -1.2.3.5,vxlan
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl chassis-del ch0])
>>>>     -AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns
>>>>     ip,type list encap | sort],
>>>>     -         [0], [dnl
>>>>     -1.2.3.5,geneve
>>>>     -1.2.3.5,stt
>>>>     -1.2.3.5,vxlan
>>>>     -])
>>>>     -
>>>>     -OVN_SBCTL_TEST_STOP
>>>>     -as ovn-sb
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -AT_SETUP([ovn-sbctl])
>>>>     -OVN_SBCTL_TEST_START
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add br-test])
>>>>     -AT_CHECK([ovn-nbctl lsp-add br-test vif0])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
>>>>     -AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
>>>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>>     -Chassis ch0
>>>>     -    Encap stt
>>>>     -        ip: "1.2.3.5"
>>>>     -        options: {csum="true"}
>>>>     -    Port_Binding vif0
>>>>     -])
>>>>     -
>>>>     -# adds another 'vif1'
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
>>>>     -AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
>>>>     -Chassis ch0
>>>>     -    Encap stt
>>>>     -        ip: "1.2.3.5"
>>>>     -        options: {csum="true"}
>>>>     -    Port_Binding vif
>>>>     -    Port_Binding vif
>>>>     -])
>>>>     -
>>>>     -# deletes 'vif1'
>>>>     -AT_CHECK([ovn-nbctl lsp-del vif1])
>>>>     -AT_CHECK([ovn-nbctl --wait=sb sync])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl show], [0], [dnl
>>>>     -Chassis ch0
>>>>     -    Encap stt
>>>>     -        ip: "1.2.3.5"
>>>>     -        options: {csum="true"}
>>>>     -    Port_Binding vif0
>>>>     -])
>>>>     -
>>>>     -uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':'
>>>>     -f2 | tr -d ' ')
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis
>>>>     list Port_Binding], [0], [dnl
>>>>     -logical_port        : vif0
>>>>     -mac                 : [["f0:ab:cd:ef:01:02"]]
>>>>     -chassis             : ${uuid}
>>>>     -])
>>>>     -
>>>>     -# test the passing down of logical port type and options.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0
>>>>     vtep_logical_switch=l0])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0
>>>>     options!={}])
>>>>     -AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list
>>>>     Port_Binding vtep0], [0], [dnl
>>>>     -logical_port        : vtep0
>>>>     -mac                 : [[]]
>>>>     -type                : vtep
>>>>     -options             : {vtep_logical_switch=l0,
>>>>     vtep_physical_switch=p0}
>>>>     -])
>>>>     -
>>>>     -OVN_SBCTL_TEST_STOP
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -dnl
>>>> ---------------------------------------------------------------------
>>>>     -
>>>>     -AT_SETUP([ovn-sbctl - connection])
>>>>     -OVN_SBCTL_TEST_START
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection
>>>>     ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
>>>>     -AT_CHECK([ovn-sbctl list connection | grep inactivity_probe],
>>>>     [0], [dnl
>>>>     -inactivity_probe    : 30000
>>>>     -inactivity_probe    : 30000
>>>>     -])
>>>>     -
>>>>     -OVN_SBCTL_TEST_STOP
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at
>>>>     <http://ovn.at>
>>>>     deleted file mode 100644
>>>>     index cb380d2..0000000
>>>>     --- a/tests/ovn.at <http://ovn.at>
>>>>     +++ /dev/null
>>>>     @@ -1,14702 +0,0 @@
>>>>     -# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
>>>>     -#
>>>>     -# This compares packets read from PCAP, in pcap format, to 
>>>> those read
>>>>     -# from EXPECTED, which is a text file containing packets as hex
>>>>     -# strings, one per line.  If PCAP contains fewer packets than
>>>>     -# EXPECTED, it waits up to 10 seconds for more packets to appear.
>>>>     -#
>>>>     -# The implementation is an m4 macro that is mostly implemented in
>>>>     -# terms of a shell function.  This reduces the size of the 
>>>> generated
>>>>     -# testsuite file since the shell function is only emitted once 
>>>> even
>>>>     -# when this macro is invoked many times.
>>>>     -m4_divert_text([PREPARE_TESTS],
>>>>     -  [ovn_check_packets__ () {
>>>>     -     echo
>>>>     -     echo "checking packets in $1 against $2:"
>>>>     -     rcv_pcap=$1
>>>>     -     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
>>>>     -     exp_text=$2
>>>>     -     exp_n=`wc -l < "$exp_text"`
>>>>     -     OVS_WAIT_UNTIL(
>>>>     -       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $rcv_pcap > $rcv_text
>>>>     -        rcv_n=`wc -l < "$rcv_text"`
>>>>     -        echo "rcv_n=$rcv_n exp_n=$exp_n"
>>>>     -        test $rcv_n -ge $exp_n])
>>>>     -     sort $exp_text > expout
>>>>     -   }
>>>>     -])
>>>>     -m4_define([OVN_CHECK_PACKETS],
>>>>     -  [ovn_check_packets__ "$1" "$2"
>>>>     -   AT_CHECK([sort $rcv_text], [0], [expout])])
>>>>     -
>>>>     -AT_BANNER([OVN components])
>>>>     -
>>>>     -AT_SETUP([ovn -- lexer])
>>>>     -dnl For lines without =>, input and expected output are 
>>>> identical.
>>>>     -dnl For lines with =>, input precedes => and expected output
>>>>     follows =>.
>>>>     -AT_DATA([test-cases.txt], [dnl
>>>>     -foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
>>>>     -"abc\u0020def" => "abc def"
>>>>     -" => error("Input ends inside quoted string.")dnl "
>>>>     -
>>>>     -$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
>>>>     -$1 => error("`$' must be followed by a valid identifier.") 1
>>>>     -
>>>>     -a/*b*/c => a c
>>>>     -a//b c => a
>>>>     -a/**/b => a b
>>>>     -a/*/b => a error("`/*' without matching `*/'.")
>>>>     -a/*/**/b => a b
>>>>     -a/b => a error("`/' is only valid as part of `//' or `/*'.") b
>>>>     -
>>>>     -0 1 12345 18446744073709551615
>>>>     -18446744073709551616 => error("Decimal constants must be less
>>>>     than 2**64.")
>>>>     -9999999999999999999999 => error("Decimal constants must be less
>>>>     than 2**64.")
>>>>     -01 => error("Decimal constants must not have leading zeros.")
>>>>     -
>>>>     -0/0
>>>>     -0/1
>>>>     -1/0 => error("Value contains unmasked 1-bits.")
>>>>     -1/1
>>>>     -128/384
>>>>     -1/3
>>>>     -1/ => error("Integer constant expected.")
>>>>     -
>>>>     -1/0x123 => error("Value and mask have incompatible formats.")
>>>>     -
>>>>     -0x1234
>>>>     -0x01234 => 0x1234
>>>>     -0x0 => 0
>>>>     -0x000 => 0
>>>>     -0xfedcba9876543210
>>>>     -0XFEDCBA9876543210 => 0xfedcba9876543210
>>>>     -0xfedcba9876543210fedcba9876543210
>>>>     -0x0000fedcba9876543210fedcba9876543210 =>
>>>>     0xfedcba9876543210fedcba9876543210
>>>>     -0x => error("Hex digits expected following 0x.")
>>>>     -0X => error("Hex digits expected following 0X.")
>>>>     -0x0/0x0 => 0/0
>>>>     -0x0/0x1 => 0/0x1
>>>>     -0x1/0x0 => error("Value contains unmasked 1-bits.")
>>>>     -0xffff/0x1ffff
>>>>     -0x. => error("Invalid syntax in hexadecimal constant.")
>>>>     -
>>>>     -192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
>>>>     -256.1.2.3 => error("Invalid numeric constant.")
>>>>     -192.168.0.0/16 <http://192.168.0.0/16>
>>>>     -192.168.0.0/255.255.0.0 <http://192.168.0.0/255.255.0.0> =>
>>>>     192.168.0.0/16 <http://192.168.0.0/16>
>>>>     -192.168.0.0/255.255.255.0 <http://192.168.0.0/255.255.255.0> =>
>>>>     192.168.0.0/24 <http://192.168.0.0/24>
>>>>     -192.168.0.0/255.255.0.255 <http://192.168.0.0/255.255.0.255>
>>>>     -192.168.0.0/255.0.0.0 <http://192.168.0.0/255.0.0.0> =>
>>>>     error("Value contains unmasked 1-bits.")
>>>>     -192.168.0.0/32 <http://192.168.0.0/32>
>>>>     -192.168.0.0/255.255.255.255 <http://192.168.0.0/255.255.255.255>
>>>>     => 192.168.0.0/32 <http://192.168.0.0/32>
>>>>     -1.2.3.4:5 <http://1.2.3.4:5> => 1.2.3.4 : 5
>>>>     -
>>>>     -::
>>>>     -::1
>>>>     -ff00::1234 => ff00::1234
>>>>     -2001:db8:85a3::8a2e:370:7334
>>>>     -2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
>>>>     -2001:0db8:85a3:0000:0000:8a2e:0370:7334 =>
>>>>     2001:db8:85a3::8a2e:370:7334
>>>>     -::ffff:192.0.2.128
>>>>     -::ffff:c000:0280 => ::ffff:192.0.2.128
>>>>     -::1/::1
>>>>     -::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
>>>>     -::1/128
>>>>     -ff00::/8
>>>>     -ff00::/ff00:: => ff00::/8
>>>>     -
>>>>     -01:23:45:67:ab:cd
>>>>     -01:23:45:67:AB:CD => 01:23:45:67:ab:cd
>>>>     -fe:dc:ba:98:76:54
>>>>     -FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
>>>>     -01:00:00:00:00:00/01:00:00:00:00:00
>>>>     -ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>>>     -fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
>>>>     -ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains
>>>>     unmasked 1-bits.")
>>>>     -fe:x => error("Invalid numeric constant.")
>>>>     -00:01:02:03:04:x => error("Invalid numeric constant.")
>>>>     -
>>>>     -# Test that operators are tokenized as expected, even without
>>>>     white space.
>>>> -(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= >
>>>>     >= ! && || .. , ; = <-> -- :
>>>>     -& => error("`&' is only valid as part of `&&'.")
>>>>     -| => error("`|' is only valid as part of `||'.")
>>>>     -- => error("`-' is only valid as part of `--'.")
>>>>     -
>>>>     -^ => error("Invalid character `^' in input.")
>>>>     -])
>>>>     -AT_CAPTURE_FILE([input.txt])
>>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>>     -sed 's/.* => //' test-cases.txt > expout
>>>>     -AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -dnl The OVN expression parser needs to know what fields overlap
>>>>     with one
>>>>     -dnl another.  This test therefore verifies that all the smaller
>>>>     registers
>>>>     -dnl are defined as terms of subfields of the larger ones.
>>>>     -dnl
>>>>     -dnl When we add or remove registers this test needs to be
>>>>     updated, of course.
>>>>     -AT_SETUP([ovn -- registers])
>>>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
>>>>     -[[reg0 = xxreg0[96..127]
>>>>     -reg1 = xxreg0[64..95]
>>>>     -reg2 = xxreg0[32..63]
>>>>     -reg3 = xxreg0[0..31]
>>>>     -reg4 = xxreg1[96..127]
>>>>     -reg5 = xxreg1[64..95]
>>>>     -reg6 = xxreg1[32..63]
>>>>     -reg7 = xxreg1[0..31]
>>>>     -reg8 = xreg4[32..63]
>>>>     -reg9 = xreg4[0..31]
>>>>     -xreg0 = xxreg0[64..127]
>>>>     -xreg1 = xxreg0[0..63]
>>>>     -xreg2 = xxreg1[64..127]
>>>>     -xreg3 = xxreg1[0..63]
>>>>     -xreg4 = OXM_OF_PKT_REG4
>>>>     -xxreg0 = NXM_NX_XXREG0
>>>>     -xxreg1 = NXM_NX_XXREG1
>>>>     -]])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -dnl Check that the OVN conntrack field definitions are correct.
>>>>     -AT_SETUP([ovn -- conntrack fields])
>>>>     -AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
>>>>     -[[ct.dnat = ct_state[7]
>>>>     -ct.est = ct_state[1]
>>>>     -ct.inv = ct_state[4]
>>>>     -ct.new = ct_state[0]
>>>>     -ct.rel = ct_state[2]
>>>>     -ct.rpl = ct_state[3]
>>>>     -ct.snat = ct_state[6]
>>>>     -ct.trk = ct_state[5]
>>>>     -ct_label = NXM_NX_CT_LABEL
>>>>     -ct_label.blocked = ct_label[0]
>>>>     -ct_mark = NXM_NX_CT_MARK
>>>>     -ct_state = NXM_NX_CT_STATE
>>>>     -]])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- composition])
>>>>     -AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- expression parser])
>>>>     -dnl For lines without =>, input and expected output are 
>>>> identical.
>>>>     -dnl For lines with =>, input precedes => and expected output
>>>>     follows =>.
>>>>     -AT_DATA([test-cases.txt], [[
>>>>     -eth.type == 0x800
>>>>     -eth.type==0x800 => eth.type == 0x800
>>>>     -eth.type[0..15] == 0x800 => eth.type == 0x800
>>>>     -
>>>>     -vlan.present
>>>>     -vlan.present == 1 => vlan.present
>>>>     -!(vlan.present == 0) => vlan.present
>>>>     -!(vlan.present != 1) => vlan.present
>>>>     -!vlan.present
>>>>     -vlan.present == 0 => !vlan.present
>>>>     -vlan.present != 1 => !vlan.present
>>>>     -!(vlan.present == 1) => !vlan.present
>>>>     -!(vlan.present != 0) => !vlan.present
>>>>     -
>>>>     -eth.dst[0]
>>>>     -eth.dst[0] == 1 => eth.dst[0]
>>>>     -eth.dst[0] != 0 => eth.dst[0]
>>>>     -!(eth.dst[0] == 0) => eth.dst[0]
>>>>     -!(eth.dst[0] != 1) => eth.dst[0]
>>>>     -
>>>>     -!eth.dst[0]
>>>>     -eth.dst[0] == 0 => !eth.dst[0]
>>>>     -eth.dst[0] != 1 => !eth.dst[0]
>>>>     -!(eth.dst[0] == 1) => !eth.dst[0]
>>>>     -!(eth.dst[0] != 0) => !eth.dst[0]
>>>>     -
>>>>     -vlan.tci[12..15] == 0x3
>>>>     -vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
>>>>     -vlan.tci[12..15] != 0x3
>>>>     -vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
>>>>     -
>>>>     -!vlan.pcp => vlan.pcp == 0
>>>>     -!(vlan.pcp) => vlan.pcp == 0
>>>>     -vlan.pcp == 0x4
>>>>     -vlan.pcp != 0x4
>>>>     -vlan.pcp > 0x4
>>>>     -vlan.pcp >= 0x4
>>>>     -vlan.pcp < 0x4
>>>>     -vlan.pcp <= 0x4
>>>>     -!(vlan.pcp != 0x4) => vlan.pcp == 0x4
>>>>     -!(vlan.pcp == 0x4) => vlan.pcp != 0x4
>>>>     -!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
>>>>     -!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
>>>>     -!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
>>>>     -!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
>>>>     -0x4 == vlan.pcp => vlan.pcp == 0x4
>>>>     -0x4 != vlan.pcp => vlan.pcp != 0x4
>>>>     -0x4 < vlan.pcp => vlan.pcp > 0x4
>>>>     -0x4 <= vlan.pcp => vlan.pcp >= 0x4
>>>>     -0x4 > vlan.pcp => vlan.pcp < 0x4
>>>>     -0x4 >= vlan.pcp => vlan.pcp <= 0x4
>>>>     -!(0x4 != vlan.pcp) => vlan.pcp == 0x4
>>>>     -!(0x4 == vlan.pcp) => vlan.pcp != 0x4
>>>>     -!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
>>>>     -!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
>>>>     -!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
>>>>     -!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
>>>>     -
>>>>     -1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
>>>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>>>     -1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
>>>>     -1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
>>>>     -1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
>>>>     -4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
>>>>     -4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
>>>>     -4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
>>>>     -4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
>>>>     -!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
>>>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>>>     -!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
>>>>     -!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
>>>>     -!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
>>>>     -!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
>>>>     -!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
>>>>     -!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
>>>>     -!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
>>>>     -
>>>>     -vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 ||
>>>>     vlan.pcp == 0x3 || vlan.pcp == 0x4
>>>>     -vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp ==
>>>>     4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 ||
>>>>     vlan.pcp == 0x4
>>>>     -
>>>>     -vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 &&
>>>>     vlan.pcp != 0x3 && vlan.pcp != 0x4
>>>>     -vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp ==
>>>>     4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 &&
>>>>     vlan.pcp == 0x4
>>>>     -
>>>>     -vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 ||
>>>>     vlan.pcp != 0x4)
>>>>     -vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>>     == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3)
>>>>     && vlan.pcp == 0x4
>>>>     -vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp
>>>>     == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3)
>>>>     || vlan.pcp != 0x4)
>>>>     -
>>>>     -ip4.src == {10.0.0.0/8 <http://10.0.0.0/8>, 192.168.0.0/16
>>>>     <http://192.168.0.0/16>, 172.16.20.0/24 <http://172.16.20.0/24>,
>>>>     8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 ||
>>>>     ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
>>>>     -ip6.src == ::1 => ip6.src == 0x1
>>>>     -
>>>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304
>>>>     -ip4.src == ::1.2.3.4/::ffff:ffff <http://1.2.3.4/::ffff:ffff> =>
>>>>     ip4.src == 0x1020304
>>>>     -ip6.src == ::1 => ip6.src == 0x1
>>>>     -
>>>>     -1
>>>>     -0
>>>>     -!1 => 0
>>>>     -!0 => 1
>>>>     -
>>>>     -inport == "eth0"
>>>>     -!(inport != "eth0") => inport == "eth0"
>>>>     -
>>>> -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>>>
>>>>     => 0
>>>>     -
>>>>     -ip4.src == "eth0" => Integer field ip4.src is not compatible with
>>>>     string constant.
>>>>     -inport == 1 => String field inport is not compatible with integer
>>>>     constant.
>>>>     -ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational
>>>>     operator.
>>>>     -
>>>>     -ip4.src > {1, 2, 3} => Only == and != operators may be used with
>>>>     value sets.
>>>>     -eth.type > 0x800 => Only == and != operators may be used with
>>>>     nominal field eth.type.
>>>>     -vlan.present > 0 => Only == and != operators may be used with
>>>>     Boolean field vlan.present.
>>>>     -
>>>>     -inport != "eth0" => Nominal field inport may only be tested for
>>>>     equality (taking enclosing `!' operators into account).
>>>>     -!(inport == "eth0") => Nominal field inport may only be tested
>>>>     for equality (taking enclosing `!' operators into account).
>>>>     -eth.type != 0x800 => Nominal field eth.type may only be tested
>>>>     for equality (taking enclosing `!' operators into account).
>>>>     -!(eth.type == 0x800) => Nominal field eth.type may only be tested
>>>>     for equality (taking enclosing `!' operators into account).
>>>>     -inport = "eth0" => Syntax error at `=' expecting relational 
>>>> operator.
>>>>     -
>>>>     -123 == 123 => Syntax error at `123' expecting field name.
>>>>     -
>>>>     -$name => Syntax error at `$name' expecting address set name.
>>>>     -@name => Syntax error at `@name' expecting port group name.
>>>>     -
>>>>     -123 == xyzzy => Syntax error at `xyzzy' expecting field name.
>>>>     -xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
>>>>     -
>>>>     -inport[1] == 1 => Cannot select subfield of string field inport.
>>>>     -
>>>>     -eth.type[] == 1 => Syntax error at `@:>@' expecting small 
>>>> integer.
>>>>     -eth.type[::1] == 1 => Syntax error at `::1' expecting small 
>>>> integer.
>>>>     -eth.type[18446744073709551615] == 1 => Syntax error at
>>>>     `18446744073709551615' expecting small integer.
>>>>     -
>>>>     -eth.type[5!] => Syntax error at `!' expecting `@:>@'.
>>>>     -
>>>>     -eth.type[5..1] => Invalid bit range 5 to 1.
>>>>     -
>>>>     -eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field
>>>>     eth.type.
>>>>     -
>>>>     -eth.type[10] == 1 => Cannot select subfield of nominal field
>>>>     eth.type.
>>>>     -
>>>>     -eth.type => Explicit `!= 0' is required for inequality test of
>>>>     multibit field against 0.
>>>>     -
>>>>     -!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test
>>>>     of multibit field against 0.
>>>>     -
>>>>     -123 => Syntax error at end of input expecting relational 
>>>> operator.
>>>>     -
>>>>     -123 x => Syntax error at `x' expecting relational operator.
>>>>     -
>>>>     -{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
>>>>     -
>>>>     -eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
>>>>     -
>>>>     -(1 x) => Syntax error at `x' expecting `)'.
>>>>     -
>>>>     -!0x800 != eth.type => Missing parentheses around operand of !.
>>>>     -
>>>>     -eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => &&
>>>>     and || must be parenthesized when used together.
>>>>     -
>>>>     -eth.dst == {} => Syntax error at `}' expecting constant.
>>>>     -
>>>>     -eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and !=
>>>>     operators may be used with masked constants. Consider using
>>>>     subfields instead (e.g. eth.src[0..15] > 0x1111 in place of
>>>>     eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
>>>>     -
>>>>     -ip4.src == ::1 => 128-bit constant is not compatible with 32-bit
>>>>     field ip4.src.
>>>>     -
>>>>     -1 == eth.type == 2 => Range expressions must have the form `x <
>>>>     field < y' or `x > field > y', with each `<' optionally replaced
>>>>     by `<=' or `>' by `>=').
>>>>     -
>>>>     -eth.dst[40] x => Syntax error at `x' expecting end of input.
>>>>     -
>>>>     -ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at
>>>>     `$unknownset' expecting address set name.
>>>>     -eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at
>>>>     `badmac' expecting constant.
>>>>     -
>>>> -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
>>>>
>>>>     => Parentheses nested too deeply.
>>>>     -
>>>>     -ct_label > $set4 => Only == and != operators may be used to
>>>>     compare a field against an empty value set.
>>>>     -]])
>>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>>     -sed 's/.* => //' test-cases.txt > expout
>>>>     -AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], 
>>>> [expout])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- expression annotation])
>>>>     -dnl Input precedes =>, expected output follows =>.
>>>>     -dnl Empty lines and lines starting with # are ignored.
>>>>     -AT_DATA([test-cases.txt], [[
>>>>     -ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
>>>>     -ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
>>>>     -ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 ||
>>>>     eth.type == 0x86dd)
>>>>     -ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea)
>>>>     && (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304
>>>>     && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
>>>>     -
>>>>     -# Nested expressions over a single symbol should be annotated
>>>>     with symbol's
>>>>     -# prerequisites only once, at the top level.
>>>>     -tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1
>>>>     || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 &&
>>>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -
>>>>     -ip => eth.type == 0x800 || eth.type == 0x86dd
>>>>     -ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>>>     -ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
>>>>     -ip > 0 => Only == and != operators may be used with nominal 
>>>> field ip.
>>>>     -!ip => Nominal predicate ip may only be tested positively, e.g.
>>>>     `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>>>     -ip == 0 => Nominal predicate ip may only be tested positively,
>>>>     e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
>>>>     -
>>>>     -vlan.present => vlan.tci[12]
>>>>     -!vlan.present => !vlan.tci[12]
>>>>     -
>>>>     -!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
>>>>     -vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 &&
>>>>     vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
>>>>     -!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 &&
>>>>     xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
>>>>     -
>>>>     -ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type ==
>>>>     0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 
>>>> 0x86dd))
>>>>     -!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type
>>>>     != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>>>     0x86dd))
>>>>     -ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type ==
>>>>     0x86dd)
>>>>     -
>>>>     -bad_prereq != 0 => Error parsing expression `xyzzy' encountered
>>>>     as prerequisite or predicate of initial expression: Syntax error
>>>>     at `xyzzy' expecting field name.
>>>>     -self_recurse != 0 => Error parsing expression `self_recurse != 0'
>>>>     encountered as prerequisite or predicate of initial expression:
>>>>     Recursive expansion of symbol `self_recurse'.
>>>>     -mutual_recurse_1 != 0 => Error parsing expression
>>>>     `mutual_recurse_2 != 0' encountered as prerequisite or predicate
>>>>     of initial expression: Error parsing expression `mutual_recurse_1
>>>>     != 0' encountered as prerequisite or predicate of initial
>>>>     expression: Recursive expansion of symbol `mutual_recurse_1'.
>>>>     -mutual_recurse_2 != 0 => Error parsing expression
>>>>     `mutual_recurse_1 != 0' encountered as prerequisite or predicate
>>>>     of initial expression: Error parsing expression `mutual_recurse_2
>>>>     != 0' encountered as prerequisite or predicate of initial
>>>>     expression: Recursive expansion of symbol `mutual_recurse_2'.
>>>>     -]])
>>>>     -sed 's/ =>.*//' test-cases.txt > input.txt
>>>>     -sed 's/.* => //' test-cases.txt > expout
>>>>     -AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], 
>>>> [expout])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 1-term expression conversion])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], 
>>>> [0],
>>>>     -  [Tested converting all 1-terminal expressions with 2 numeric
>>>>     vars (each 3 bits) in terms of operators == != < <= > >= and 2
>>>>     string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2-term expression conversion])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], 
>>>> [0],
>>>>     -  [Tested converting 578 expressions of 2 terminals with 2
>>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>>>     and 2 string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 3-term expression conversion])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=convert
>>>>     --bits=2 3], [0],
>>>>     -  [Tested converting 67410 expressions of 3 terminals with 2
>>>>     numeric vars (each 2 bits) in terms of operators == != < <= > >=
>>>>     and 2 string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 3-term numeric expression simplification])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>>     --nvars=2 --svars=0 3], [0],
>>>>     -  [Tested simplifying 490770 expressions of 3 terminals with 2
>>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term string expression simplification])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>>     --nvars=0 --svars=4 4], [0],
>>>>     -  [Tested simplifying 21978 expressions of 4 terminals with 4
>>>>     string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 3-term mixed expression simplification])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=simplify
>>>>     --nvars=1 --svars=1 3], [0],
>>>>     -  [Tested simplifying 127890 expressions of 3 terminals with 1
>>>>     numeric vars (each 3 bits) in terms of operators == != < <= > >=
>>>>     and 1 string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- simplification special cases])
>>>>     -simplify() {
>>>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>>>     -}
>>>>     -AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
>>>>     -])
>>>>     -AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
>>>>     -])
>>>>     -AT_CHECK([simplify 'tcp.dst >= 0'], [0],
>>>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -])
>>>>     -AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
>>>>     -    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -])
>>>>     -AT_CHECK([simplify 'tcp.dst > 0'], [0],
>>>>     -    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] ||
>>>>     tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8]
>>>>     || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] ||
>>>>     tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 &&
>>>>     (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -]])
>>>>     -AT_CHECK([simplify 'tcp.dst < 65535'], [0],
>>>>     -    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3]
>>>>     || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] ||
>>>>     !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] ||
>>>>     !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) &&
>>>>     ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
>>>>     -]])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- is_chassis_resident simplification])
>>>>     -simplify() {
>>>>     -    echo "$1" | ovstest test-ovn simplify-expr
>>>>     -}
>>>>     -AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
>>>>     -])
>>>>     -AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
>>>>     -])
>>>>     -AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
>>>>     -])
>>>>     -AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term numeric expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=3 --svars=0 --bits=1 4], [0],
>>>>     -  [Tested normalizing 1874026 expressions of 4 terminals with 3
>>>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term string expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=0 --svars=3 --bits=1 4], [0],
>>>>     -  [Tested normalizing 11242 expressions of 4 terminals with 3
>>>>     string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term mixed expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=1 --bits=1 --svars=2 4], [0],
>>>>     -  [Tested normalizing 175978 expressions of 4 terminals with 1
>>>>     numeric vars (each 1 bits) in terms of operators == != < <= > >=
>>>>     and 2 string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 5-term numeric expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
>>>>     -  [Tested normalizing 1317600 expressions of 5 terminals with 3
>>>>     numeric vars (each 1 bits) in terms of operators ==.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 5-term string expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
>>>>     -  [Tested normalizing 368550 expressions of 5 terminals with 3
>>>>     string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 5-term mixed expression normalization])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=normalize
>>>>     --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
>>>>     -  [Tested normalizing 216000 expressions of 5 terminals with 1
>>>>     numeric vars (each 1 bits) in terms of operators == and 1 
>>>> string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term numeric expressions to flows])
>>>>     -AT_KEYWORDS([expression])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2
>>>>     --svars=0 --bits=2 --relops='==' 4], [0],
>>>>     -  [Tested converting to flows 175978 expressions of 4 terminals
>>>>     with 2 numeric vars (each 2 bits) in terms of operators ==.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term string expressions to flows])
>>>>     -AT_KEYWORDS([expression])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0
>>>>     --svars=4 4], [0],
>>>>     -  [Tested converting to flows 21978 expressions of 4 terminals
>>>>     with 4 string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4-term mixed expressions to flows])
>>>>     -AT_KEYWORDS([expression])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1
>>>>     --bits=2 --svars=1 --relops='==' 4], [0],
>>>>     -  [Tested converting to flows 48312 expressions of 4 terminals
>>>>     with 1 numeric vars (each 2 bits) in terms of operators == and 1
>>>>     string vars.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 3-term numeric expressions to flows])
>>>>     -AT_KEYWORDS([expression])
>>>>     -AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3
>>>>     --svars=0 --bits=3 --relops='==' 3], [0],
>>>>     -  [Tested converting to flows 41328 expressions of 3 terminals
>>>>     with 3 numeric vars (each 3 bits) in terms of operators ==.
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- converting expressions to flows -- string 
>>>> fields])
>>>>     -AT_KEYWORDS([expression])
>>>>     -expr_to_flow () {
>>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>>     -}
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
>>>>     -ip,reg14=0x5
>>>>     -ipv6,reg14=0x5
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
>>>>     -ip,reg14=0x6
>>>>     -ipv6,reg14=0x6
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no 
>>>> flows)
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2",
>>>>     "LOCAL"}'], [0],
>>>>     -[reg14=0x5
>>>>     -reg14=0x6
>>>>     -reg14=0xfffe
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} &&
>>>>     ip'], [0], [dnl
>>>>     -ip,reg14=0x5
>>>>     -ip,reg14=0x6
>>>>     -ipv6,reg14=0x5
>>>>     -ipv6,reg14=0x6
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'],
>>>>     [0], [dnl
>>>>     -(no flows)
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- converting expressions to flows -- address 
>>>> sets])
>>>>     -AT_KEYWORDS([expression])
>>>>     -expr_to_flow () {
>>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>>     -}
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2,
>>>>     10.0.0.3}'], [0], [dnl
>>>>     -ip,nw_src=10.0.0.1
>>>>     -ip,nw_src=10.0.0.2
>>>>     -ip,nw_src=10.0.0.3
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
>>>>     -ip,nw_src=10.0.0.1
>>>>     -ip,nw_src=10.0.0.2
>>>>     -ip,nw_src=10.0.0.3
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
>>>>     -ip,nw_src=1.2.3.4
>>>>     -ip,nw_src=10.0.0.1
>>>>     -ip,nw_src=10.0.0.2
>>>>     -ip,nw_src=10.0.0.3
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20
>>>>     <http://1.2.0.0/20>, 5.5.5.0/24 <http://5.5.5.0/24>, $set1}'],
>>>>     [0], [dnl
>>>>     -ip,nw_src=1.2.0.0/20 <http://1.2.0.0/20>
>>>>     -ip,nw_src=10.0.0.1
>>>>     -ip,nw_src=10.0.0.2
>>>>     -ip,nw_src=10.0.0.3
>>>>     -ip,nw_src=5.5.5.0/24 <http://5.5.5.0/24>
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
>>>>     -ipv6,ipv6_src=::1
>>>>     -ipv6,ipv6_src=::2
>>>>     -ipv6,ipv6_src=::3
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
>>>>     -ipv6,ipv6_src=::1
>>>>     -ipv6,ipv6_src=::2
>>>>     -ipv6,ipv6_src=::3
>>>>     -ipv6,ipv6_src=::4
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01,
>>>>     00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
>>>>     -dl_src=00:00:00:00:00:01
>>>>     -dl_src=00:00:00:00:00:02
>>>>     -dl_src=00:00:00:00:00:03
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
>>>>     -dl_src=00:00:00:00:00:01
>>>>     -dl_src=00:00:00:00:00:02
>>>>     -dl_src=00:00:00:00:00:03
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3,
>>>>     ba:be:be:ef:de:ad, $set3}'], [0], [dnl
>>>>     -dl_src=00:00:00:00:00:01
>>>>     -dl_src=00:00:00:00:00:02
>>>>     -dl_src=00:00:00:00:00:03
>>>>     -dl_src=ba:be:be:ef:de:ad
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
>>>>     -(no flows)
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
>>>>     -ip,nw_src=1.2.3.4
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src ==
>>>>     {$set4}'], [0], [dnl
>>>>     -ip,nw_src=1.2.3.4
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
>>>>     -
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8 <http://1.0.0.0/8>,
>>>>     $set4}'], [0], [dnl
>>>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 <http://1.0.0.0/8>
>>>>     && ip4.src != {$set4}'], [0], [dnl
>>>>     -ip,nw_src=0.0.0.0/1.0.0.0 <http://0.0.0.0/1.0.0.0>
>>>>     -ip,nw_src=128.0.0.0/1 <http://128.0.0.0/1>
>>>>     -ip,nw_src=16.0.0.0/16.0.0.0 <http://16.0.0.0/16.0.0.0>
>>>>     -ip,nw_src=2.0.0.0/2.0.0.0 <http://2.0.0.0/2.0.0.0>
>>>>     -ip,nw_src=32.0.0.0/32.0.0.0 <http://32.0.0.0/32.0.0.0>
>>>>     -ip,nw_src=4.0.0.0/4.0.0.0 <http://4.0.0.0/4.0.0.0>
>>>>     -ip,nw_src=64.0.0.0/64.0.0.0 <http://64.0.0.0/64.0.0.0>
>>>>     -ip,nw_src=8.0.0.0/8.0.0.0 <http://8.0.0.0/8.0.0.0>
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- converting expressions to flows -- port groups])
>>>>     -AT_KEYWORDS([expression])
>>>>     -expr_to_flow () {
>>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>>     -}
>>>>     -AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
>>>>     -reg15=0x11
>>>>     -reg15=0x12
>>>>     -reg15=0x13
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
>>>>     -(no flows)
>>>>     -])
>>>>     -AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], 
>>>> [dnl
>>>>     -reg15=0x11
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- converting expressions to flows -- conjunction])
>>>>     -AT_KEYWORDS([conjunction])
>>>>     -expr_to_flow () {
>>>>     -    echo "$1" | ovstest test-ovn expr-to-flows | sort
>>>>     -}
>>>>     -
>>>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
>>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>>     -conj_id=1,ip
>>>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>>>     -ip,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/2)
>>>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>>>     -])
>>>>     -
>>>>     -lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
>>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>>     -ct_state=+est+trk,ct_label=0x1/0x1,ip
>>>>     -ct_state=+est+trk,ct_label=0x1/0x1,ipv6
>>>>     -ct_state=-est+trk,ip
>>>>     -ct_state=-est+trk,ipv6
>>>>     -])
>>>>     -
>>>>     -lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>>     -ip4.dst == {20.0.0.1, 20.0.0.2}"
>>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>>     -conj_id=1,ip
>>>>     -ip,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/2)
>>>>     -ip,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/2)
>>>>     -ip,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/2)
>>>>     -ip,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/2)
>>>>     -ip,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/2)
>>>>     -])
>>>>     -
>>>>     -lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
>>>>     -ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
>>>>     -tcp.dst >= 1000 && tcp.dst <= 1010"
>>>>     -
>>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>>     -conj_id=1,tcp
>>>>     -tcp,nw_dst=20.0.0.1 <http://20.0.0.1>: conjunction(1, 0/3)
>>>>     -tcp,nw_dst=20.0.0.2 <http://20.0.0.2>: conjunction(1, 0/3)
>>>>     -tcp,nw_dst=20.0.0.3 <http://20.0.0.3>: conjunction(1, 0/3)
>>>>     -tcp,nw_src=10.0.0.1 <http://10.0.0.1>: conjunction(1, 1/3)
>>>>     -tcp,nw_src=10.0.0.2 <http://10.0.0.2>: conjunction(1, 1/3)
>>>>     -tcp,nw_src=10.0.0.3 <http://10.0.0.3>: conjunction(1, 1/3)
>>>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
>>>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
>>>>     -tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
>>>>     -tcp,tp_dst=1000: conjunction(1, 2/3)
>>>>     -tcp,tp_dst=1001: conjunction(1, 2/3)
>>>>     -tcp,tp_dst=1010: conjunction(1, 2/3)
>>>>     -])
>>>>     -
>>>>     -lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
>>>>     -((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 
>>>> && \
>>>>     -tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
>>>>     -|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
>>>>     -
>>>>     -AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
>>>>     -conj_id=1,tcp
>>>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
>>>>     -ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
>>>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
>>>>     -ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
>>>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
>>>>     -ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
>>>>     -tcp,nw_dst=20.0.0.4 <http://20.0.0.4>: conjunction(1, 0/4)
>>>>     -tcp,nw_dst=20.0.0.7 <http://20.0.0.7>: conjunction(1, 0/4)
>>>>     -tcp,nw_dst=20.0.0.8 <http://20.0.0.8>: conjunction(1, 0/4)
>>>>     -tcp,nw_src=10.0.0.4 <http://10.0.0.4>: conjunction(1, 1/4)
>>>>     -tcp,nw_src=10.0.0.5 <http://10.0.0.5>: conjunction(1, 1/4)
>>>>     -tcp,nw_src=10.0.0.6 <http://10.0.0.6>: conjunction(1, 1/4)
>>>>     -tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=1000: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=1001: conjunction(1, 2/4)
>>>>     -tcp,tp_dst=2000: conjunction(1, 2/4)
>>>>     -tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
>>>>     -tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
>>>>     -tcp,tp_src=1000: conjunction(1, 3/4)
>>>>     -tcp,tp_src=1001: conjunction(1, 3/4)
>>>>     -tcp,tp_src=2000: conjunction(1, 3/4)
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- action parsing])
>>>>     -dnl Unindented text is input (a set of OVN logical actions).
>>>>     -dnl Indented text is expected output.
>>>>     -AT_DATA([test-cases.txt],
>>>>     -[[# drop
>>>>     -drop;
>>>>     -    encodes as drop
>>>>     -drop; next;
>>>>     -    Syntax error at `next' expecting end of input.
>>>>     -next; drop;
>>>>     -    Syntax error at `drop' expecting action.
>>>>     -
>>>>     -# output
>>>>     -output;
>>>>     -    encodes as resubmit(,64)
>>>>     -
>>>>     -# next
>>>>     -next;
>>>>     -    encodes as resubmit(,19)
>>>>     -next(11);
>>>>     -    formats as next;
>>>>     -    encodes as resubmit(,19)
>>>>     -next(0);
>>>>     -    encodes as resubmit(,8)
>>>>     -next(23);
>>>>     -    encodes as resubmit(,31)
>>>>     -
>>>>     -next();
>>>>     -    Syntax error at `)' expecting "pipeline" or "table".
>>>>     -next(10;
>>>>     -    Syntax error at `;' expecting `)'.
>>>>     -next(24);
>>>>     -    "next" action cannot advance beyond table 23.
>>>>     -
>>>>     -next(table=11);
>>>>     -    formats as next;
>>>>     -    encodes as resubmit(,19)
>>>>     -next(pipeline=ingress);
>>>>     -    formats as next;
>>>>     -    encodes as resubmit(,19)
>>>>     -next(table=11, pipeline=ingress);
>>>>     -    formats as next;
>>>>     -    encodes as resubmit(,19)
>>>>     -next(pipeline=ingress, table=11);
>>>>     -    formats as next;
>>>>     -    encodes as resubmit(,19)
>>>>     -
>>>>     -next(pipeline=egress);
>>>>     -    "next" action cannot advance from ingress to egress pipeline
>>>>     (use "output" action instead)
>>>>     -
>>>>     -next(table=10);
>>>>     -    formats as next(10);
>>>>     -    encodes as resubmit(,18)
>>>>     -
>>>>     -# Loading a constant value.
>>>>     -tcp.dst=80;
>>>>     -    formats as tcp.dst = 80;
>>>>     -    encodes as set_field:80->tcp_dst
>>>>     -    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type
>>>>     == 0x86dd)
>>>>     -eth.dst[40] = 1;
>>>>     -    encodes as 
>>>> set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
>>>>     -vlan.pcp = 2;
>>>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>>>     -    has prereqs vlan.tci[12]
>>>>     -vlan.tci[13..15] = 2;
>>>>     -    encodes as set_field:0x4000/0xe000->vlan_tci
>>>>     -inport = "";
>>>>     -    encodes as set_field:0->reg14
>>>>     -ip.ttl=4;
>>>>     -    formats as ip.ttl = 4;
>>>>     -    encodes as set_field:4->nw_ttl
>>>>     -    has prereqs eth.type == 0x800 || eth.type == 0x86dd
>>>>     -outport="eth0"; next; outport="LOCAL"; next;
>>>>     -    formats as outport = "eth0"; next; outport = "LOCAL"; next;
>>>>     -    encodes as
>>>> set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19) 
>>>>
>>>>     -
>>>>     -inport[1] = 1;
>>>>     -    Cannot select subfield of string field inport.
>>>>     -ip.proto[1] = 1;
>>>>     -    Cannot select subfield of nominal field ip.proto.
>>>>     -eth.dst[40] == 1;
>>>>     -    Syntax error at `==' expecting `=' or `<->'.
>>>>     -ip = 1;
>>>>     -    Predicate symbol ip used where lvalue required.
>>>>     -ip.proto = 6;
>>>>     -    Field ip.proto is not modifiable.
>>>>     -inport = {"a", "b"};
>>>>     -    Syntax error at `{' expecting constant.
>>>>     -inport = {};
>>>>     -    Syntax error at `{' expecting constant.
>>>>     -bad_prereq = 123;
>>>>     -    Error parsing expression `xyzzy' encountered as prerequisite
>>>>     or predicate of initial expression: Syntax error at `xyzzy'
>>>>     expecting field name.
>>>>     -self_recurse = 123;
>>>>     -    Error parsing expression `self_recurse != 0' encountered as
>>>>     prerequisite or predicate of initial expression: Error parsing
>>>>     expression `self_recurse != 0' encountered as prerequisite or
>>>>     predicate of initial expression: Recursive expansion of symbol
>>>>     `self_recurse'.
>>>>     -vlan.present = 0;
>>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>>     -
>>>>     -# Moving one field into another.
>>>>     -reg0=reg1;
>>>>     -    formats as reg0 = reg1;
>>>>     -    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
>>>>     -vlan.pcp = reg0[0..2];
>>>>     -    encodes as 
>>>> move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
>>>>     -    has prereqs vlan.tci[12]
>>>>     -reg0[10] = vlan.pcp[1];
>>>>     -    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
>>>>     -    has prereqs vlan.tci[12]
>>>>     -outport = inport;
>>>>     -    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
>>>>     -
>>>>     -reg0[0] = vlan.present;
>>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>>     -reg0 = reg1[0..10];
>>>>     -    Can't assign 11-bit value to 32-bit destination.
>>>>     -inport = reg0;
>>>>     -    Can't assign integer field (reg0) to string field (inport).
>>>>     -inport = big_string;
>>>>     -    String fields inport and big_string are incompatible for
>>>>     assignment.
>>>>     -ip.proto = reg0[0..7];
>>>>     -    Field ip.proto is not modifiable.
>>>>     -
>>>>     -# Exchanging fields.
>>>>     -reg0 <-> reg1;
>>>>     -    encodes as
>>>> push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127] 
>>>>
>>>>     -vlan.pcp <-> reg0[0..2];
>>>>     -    encodes as
>>>> push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15] 
>>>>
>>>>     -    has prereqs vlan.tci[12]
>>>>     -reg0[10] <-> vlan.pcp[1];
>>>>     -    encodes as
>>>> push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106] 
>>>>
>>>>     -    has prereqs vlan.tci[12]
>>>>     -outport <-> inport;
>>>>     -    encodes as
>>>> push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[] 
>>>>
>>>>     -
>>>>     -reg0[0] <-> vlan.present;
>>>>     -    Predicate symbol vlan.present used where lvalue required.
>>>>     -reg0 <-> reg1[0..10];
>>>>     -    Can't exchange 32-bit field with 11-bit field.
>>>>     -inport <-> reg0;
>>>>     -    Can't exchange string field (inport) with integer field 
>>>> (reg0).
>>>>     -inport <-> big_string;
>>>>     -    String fields inport and big_string are incompatible for
>>>>     exchange.
>>>>     -ip.proto <-> reg0[0..7];
>>>>     -    Field ip.proto is not modifiable.
>>>>     -reg0[0..7] <-> ip.proto;
>>>>     -    Field ip.proto is not modifiable.
>>>>     -
>>>>     -# TTL decrement.
>>>>     -ip.ttl--;
>>>>     -    encodes as dec_ttl
>>>>     -    has prereqs ip
>>>>     -ip.ttl
>>>>     -    Syntax error at end of input expecting `--'.
>>>>     -
>>>>     -# load balancing.
>>>>     -ct_lb;
>>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>>>     -    has prereqs ip
>>>>     -ct_lb();
>>>>     -    formats as ct_lb;
>>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
>>>>     -    has prereqs ip
>>>>     -ct_lb(192.168.1.2:80 <http://192.168.1.2:80>, 192.168.1.3:80
>>>>     <http://192.168.1.3:80>);
>>>>     -    encodes as group:1
>>>>     -    has prereqs ip
>>>>     -ct_lb(192.168.1.2, 192.168.1.3, );
>>>>     -    formats as ct_lb(192.168.1.2, 192.168.1.3);
>>>>     -    encodes as group:2
>>>>     -    has prereqs ip
>>>>     -ct_lb(fd0f::2, fd0f::3, );
>>>>     -    formats as ct_lb(fd0f::2, fd0f::3);
>>>>     -    encodes as group:3
>>>>     -    has prereqs ip
>>>>     -
>>>>     -ct_lb(192.168.1.2:);
>>>>     -    Syntax error at `)' expecting port number.
>>>>     -ct_lb(192.168.1.2:123456 <http://192.168.1.2:123456>);
>>>>     -    Syntax error at `123456' expecting port number.
>>>>     -ct_lb(foo);
>>>>     -    Syntax error at `foo' expecting IP address.
>>>>     -ct_lb([192.168.1.2]);
>>>>     -    Syntax error at `192.168.1.2' expecting IPv6 address.
>>>>     -
>>>>     -# ct_next
>>>>     -ct_next;
>>>>     -    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
>>>>     -    has prereqs ip
>>>>     -
>>>>     -# ct_commit
>>>>     -ct_commit;
>>>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>>>     -    has prereqs ip
>>>>     -ct_commit();
>>>>     -    formats as ct_commit;
>>>>     -    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_mark=1);
>>>>     -    formats as ct_commit(ct_mark=0x1);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_mark=1/1);
>>>>     -    formats as ct_commit(ct_mark=0x1/0x1);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_label=1);
>>>>     -    formats as ct_commit(ct_label=0x1);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_label=1/1);
>>>>     -    formats as ct_commit(ct_label=0x1/0x1);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_mark=1, ct_label=2);
>>>>     -    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label)) 
>>>>
>>>>     -    has prereqs ip
>>>>     -
>>>>     -ct_commit(ct_label=0x01020304050607080910111213141516);
>>>>     -    formats as 
>>>> ct_commit(ct_label=0x1020304050607080910111213141516);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label)) 
>>>>
>>>>     -    has prereqs ip
>>>> -ct_commit(ct_label=0x181716151413121110090807060504030201);
>>>>     -    formats as
>>>>     ct_commit(ct_label=0x16151413121110090807060504030201);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label)) 
>>>>
>>>>     -    has prereqs ip
>>>> -ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000); 
>>>>
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label)) 
>>>>
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_label=18446744073709551615);
>>>>     -    formats as ct_commit(ct_label=0xffffffffffffffff);
>>>>     -    encodes as
>>>> ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label)) 
>>>>
>>>>     -    has prereqs ip
>>>>     -ct_commit(ct_label=18446744073709551616);
>>>>     -    Decimal constants must be less than 2**64.
>>>>     -
>>>>     -# ct_dnat
>>>>     -ct_dnat;
>>>>     -    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
>>>>     -    has prereqs ip
>>>>     -ct_dnat(192.168.1.2);
>>>>     -    encodes as
>>>> ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
>>>>     -    has prereqs ip
>>>>     -
>>>>     -ct_dnat(192.168.1.2, 192.168.1.3);
>>>>     -    Syntax error at `,' expecting `)'.
>>>>     -ct_dnat(foo);
>>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>>     -ct_dnat(foo, bar);
>>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>>     -ct_dnat();
>>>>     -    Syntax error at `)' expecting IPv4 address.
>>>>     -
>>>>     -# ct_snat
>>>>     -ct_snat;
>>>>     -    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
>>>>     -    has prereqs ip
>>>>     -ct_snat(192.168.1.2);
>>>>     -    encodes as
>>>> ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
>>>>     -    has prereqs ip
>>>>     -
>>>>     -ct_snat(192.168.1.2, 192.168.1.3);
>>>>     -    Syntax error at `,' expecting `)'.
>>>>     -ct_snat(foo);
>>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>>     -ct_snat(foo, bar);
>>>>     -    Syntax error at `foo' expecting IPv4 address.
>>>>     -ct_snat();
>>>>     -    Syntax error at `)' expecting IPv4 address.
>>>>     -
>>>>     -# ct_clear
>>>>     -ct_clear;
>>>>     -    encodes as ct_clear
>>>>     -
>>>>     -# clone
>>>>     -clone { ip4.dst = 255.255.255.255; output; }; next;
>>>>     -    encodes as
>>>> clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
>>>>     -    has prereqs eth.type == 0x800
>>>>     -
>>>>     -# arp
>>>>     -arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip4
>>>>     -arp { };
>>>>     -    formats as arp { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.00.00.00.00.00)
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -# get_arp
>>>>     -get_arp(outport, ip4.dst);
>>>>     -    encodes as
>>>> push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[] 
>>>>
>>>>     -    has prereqs eth.type == 0x800
>>>>     -get_arp(inport, reg0);
>>>>     -    encodes as
>>>> push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] 
>>>>
>>>>     -
>>>>     -get_arp;
>>>>     -    Syntax error at `;' expecting `('.
>>>>     -get_arp();
>>>>     -    Syntax error at `)' expecting field name.
>>>>     -get_arp(inport);
>>>>     -    Syntax error at `)' expecting `,'.
>>>>     -get_arp(inport ip4.dst);
>>>>     -    Syntax error at `ip4.dst' expecting `,'.
>>>>     -get_arp(inport, ip4.dst;
>>>>     -    Syntax error at `;' expecting `)'.
>>>>     -get_arp(inport, eth.dst);
>>>>     -    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is
>>>>     required.
>>>>     -get_arp(inport, outport);
>>>>     -    Cannot use string field outport where numeric field is 
>>>> required.
>>>>     -get_arp(reg0, ip4.dst);
>>>>     -    Cannot use numeric field reg0 where string field is required.
>>>>     -
>>>>     -# put_arp
>>>>     -put_arp(inport, arp.spa, arp.sha);
>>>>     -    encodes as
>>>> push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[] 
>>>>
>>>>     -    has prereqs eth.type == 0x806 && eth.type == 0x806
>>>>     -
>>>>     -# put_dhcp_opts
>>>>     -reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) 
>>>>
>>>>     -reg2[5] =
>>>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org 
>>>>
>>>> <http://ovn.org>",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot"); 
>>>>
>>>>     -    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router
>>>>     = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name =
>>>>     "ovn.org <http://ovn.org>", wpad = "https://example.org",
>>>>     bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix =
>>>>     "/tftpboot");
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause) 
>>>>
>>>>     -reg0[15] =
>>>> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1 
>>>>
>>>> <http://30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1>},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5}); 
>>>>
>>>>     -    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4,
>>>>     router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400,
>>>>     ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8,
>>>>     7.7.7.7}, classless_static_route = {30.0.0.0/24
>>>>     <http://30.0.0.0/24>, 10.0.0.4, 40.0.0.0/16 <http://40.0.0.0/16>,
>>>>     10.0.0.6, 0.0.0.0/0 <http://0.0.0.0/0>, 10.0.0.1}, ethernet_encap
>>>>     = 1, router_discovery = 0, tftp_server_address = {10.0.0.4,
>>>>     10.0.0.5});
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause) 
>>>>
>>>>     -
>>>>     -reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
>>>>     -    Cannot use 2-bit field reg1[0..1] where 1-bit field is 
>>>> required.
>>>>     -reg1[0] = put_dhcp_opts();
>>>>     -    put_dhcp_opts requires offerip to be specified.
>>>>     -reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
>>>>     -    Syntax error at `x' expecting DHCPv4 option name.
>>>>     -reg1[0] = put_dhcp_opts(router = 10.0.0.1);
>>>>     -    put_dhcp_opts requires offerip to be specified.
>>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
>>>>     -    Syntax error at `"hi"'.
>>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
>>>>     -    Syntax error at `xyzzy' expecting DHCPv4 option name.
>>>>     -reg1[0] = put_dhcp_opts(offerip="xyzzy");
>>>>     -    DHCPv4 option offerip requires numeric value.
>>>>     -reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>>>>     -    DHCPv4 option domain_name requires string value.
>>>>     -
>>>>     -# nd_ns
>>>>     -nd_ns { nd.target = xxreg0; output; };
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -
>>>>     -nd_ns { };
>>>>     -    formats as nd_ns { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.09.00.00.00.00)
>>>>     -    has prereqs ip6
>>>>     -
>>>>     -# nd_na
>>>>     -nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc;
>>>>     outport = inport; inport = ""; /* Allow sending out inport. */
>>>>     output; };
>>>>     -    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>>>     12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>>
>>>>     -    has prereqs nd_ns
>>>>     -# nd_na_router
>>>>     -nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll =
>>>>     12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending
>>>>     out inport. */ output; };
>>>>     -    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll
>>>>     = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00) 
>>>>
>>>>     -    has prereqs nd_ns
>>>>     -
>>>>     -# get_nd
>>>>     -get_nd(outport, ip6.dst);
>>>>     -    encodes as
>>>> push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[] 
>>>>
>>>>     -    has prereqs eth.type == 0x86dd
>>>>     -get_nd(inport, xxreg0);
>>>>     -    encodes as
>>>> push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[] 
>>>>
>>>>     -get_nd;
>>>>     -    Syntax error at `;' expecting `('.
>>>>     -get_nd();
>>>>     -    Syntax error at `)' expecting field name.
>>>>     -get_nd(inport);
>>>>     -    Syntax error at `)' expecting `,'.
>>>>     -get_nd(inport ip6.dst);
>>>>     -    Syntax error at `ip6.dst' expecting `,'.
>>>>     -get_nd(inport, ip6.dst;
>>>>     -    Syntax error at `;' expecting `)'.
>>>>     -get_nd(inport, eth.dst);
>>>>     -    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is
>>>>     required.
>>>>     -get_nd(inport, outport);
>>>>     -    Cannot use string field outport where numeric field is 
>>>> required.
>>>>     -get_nd(xxreg0, ip6.dst);
>>>>     -    Cannot use numeric field xxreg0 where string field is 
>>>> required.
>>>>     -
>>>>     -# put_nd
>>>>     -put_nd(inport, nd.target, nd.sll);
>>>>     -    encodes as
>>>> push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[] 
>>>>
>>>>     -    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) &&
>>>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>>>     eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd &&
>>>>     ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>>>     ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) &&
>>>>     icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a &&
>>>>     (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 &&
>>>>     eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 ||
>>>>     eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 ||
>>>>     eth.type == 0x86dd)
>>>>     -
>>>>     -# put_dhcpv6_opts
>>>>     -reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
>>>>     00:00:00:00:10:02);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause) 
>>>>
>>>>     -reg1[0] = put_dhcpv6_opts();
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>>>
>>>>     -reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
>>>>     -    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1,
>>>>     ae70::2});
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>>>
>>>>     -reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc,
>>>>     dns_server={ae70::1,ae89::2});
>>>>     -    formats as reg1[0] = put_dhcpv6_opts(server_id =
>>>>     12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause) 
>>>>
>>>>     -reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org
>>>>     <http://ovn.org>");
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause) 
>>>>
>>>>     -reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
>>>>     -    Syntax error at `x' expecting DHCPv6 option name.
>>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
>>>>     -    Syntax error at `"hi"'.
>>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
>>>>     -    Syntax error at `xyzzy' expecting DHCPv6 option name.
>>>>     -reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
>>>>     -    DHCPv6 option ia_addr requires numeric value.
>>>>     -reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, 
>>>> domain_search=ae70::1);
>>>>     -    DHCPv6 option domain_search requires string value.
>>>>     -
>>>>     -# set_queue
>>>>     -set_queue(0);
>>>>     -    encodes as set_queue:0
>>>>     -set_queue(61440);
>>>>     -    encodes as set_queue:61440
>>>>     -set_queue(65535);
>>>>     -    Queue ID 65535 for set_queue is not in valid range 0 to 
>>>> 61440.
>>>>     -
>>>>     -# dns_lookup
>>>>     -reg1[0] = dns_lookup();
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause) 
>>>>
>>>>     -    has prereqs udp
>>>>     -reg1[0] = dns_lookup("foo");
>>>>     -    dns_lookup doesn't take any parameters
>>>>     -
>>>>     -# set_meter
>>>>     -set_meter(0);
>>>>     -    Rate 0 for set_meter is not in valid.
>>>>     -set_meter(1);
>>>>     -    encodes as meter:1
>>>>     -set_meter(100, 1000);
>>>>     -    encodes as meter:2
>>>>     -set_meter(100, 1000, );
>>>>     -    Syntax error at `,' expecting `)'.
>>>>     -set_meter(4294967295, 4294967295);
>>>>     -    encodes as meter:3
>>>>     -
>>>>     -# log
>>>>     -log(verdict=allow, severity=warning);
>>>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
>>>>     -log(name="test1", verdict=drop, severity=info);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
>>>>     -log(verdict=drop, severity=info, meter="meter1");
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
>>>>     -log(name="test1", verdict=drop, severity=info, meter="meter1");
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4) 
>>>>
>>>>     -log(verdict=drop);
>>>>     -    formats as log(verdict=drop, severity=info);
>>>>     -    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
>>>>     -log(verdict=bad_verdict, severity=info);
>>>>     -    Syntax error at `bad_verdict' unknown verdict.
>>>>     -log(verdict=drop, severity=bad_severity);
>>>>     -    Syntax error at `bad_severity' unknown severity.
>>>>     -log(severity=notice);
>>>>     -    Syntax error at `;' expecting verdict.
>>>>     -
>>>>     -# put_nd_ra_opts
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>>     = aef0::/64, slla = ae:01:02:03:04:05);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla =
>>>>     ae:01:02:03:04:10, mtu = 1450);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>>>     ae:01:02:03:04:06, prefix = aef0::/64);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>>     = aef0::/64);
>>>>     -    slla option not present
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>>>     ae:01:02:03:04:10);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu =
>>>>     1450, prefix = aef0::/64, prefix = bef0::/64, slla =
>>>>     ae:01:02:03:04:10);
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla =
>>>>     ae:01:02:03:04:10);
>>>>     -    prefix option needs to be set when address mode is
>>>>     slaac/dhcpv6_stateless.
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla =
>>>>     ae:01:02:03:04:10);
>>>>     -    prefix option needs to be set when address mode is
>>>>     slaac/dhcpv6_stateless.
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix =
>>>>     aef0::/64, slla = ae:01:02:03:04:10);
>>>>     -    Syntax error at `dhcpv6_stateless' expecting constant.
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix
>>>>     = aef0::, slla = ae:01:02:03:04:10);
>>>>     -    Invalid value for "prefix" option
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla =
>>>>     ae:01:02:03:04:10);
>>>>     -    Invalid value for "addr_mode" option
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla
>>>>     = ae:01:02:03:04:10);
>>>>     -    IPv6 ND RA option mtu requires numeric value.
>>>>     -reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4,
>>>>     slla = ae:01:02:03:04:10);
>>>>     -    Invalid value for "mtu" option
>>>>     -
>>>>     -# icmp4
>>>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -icmp4 { };
>>>>     -    formats as icmp4 { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -# icmp4 with icmp4.frag_mtu
>>>>     -icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>>>     output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -# icmp4_error
>>>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -icmp4_error { };
>>>>     -    formats as icmp4_error { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -# icmp4_error with icmp4.frag_mtu
>>>>     -icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500;
>>>>     output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip4
>>>>     -
>>>>     -icmp4.frag_mtu = 1500;
>>>>     -    encodes as
>>>>     controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
>>>>     -
>>>>     -# icmp6
>>>>     -icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs ip6
>>>>     -
>>>>     -icmp6 { };
>>>>     -    formats as icmp6 { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
>>>>     -    has prereqs ip6
>>>>     -
>>>>     -# tcp_reset
>>>>     -tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64) 
>>>>
>>>>     -    has prereqs tcp
>>>>     -
>>>>     -tcp_reset { };
>>>>     -    formats as tcp_reset { drop; };
>>>>     -    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
>>>>     -    has prereqs tcp
>>>>     -
>>>>     -# trigger_event
>>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer =
>>>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>>>     -    encodes as
>>>> controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63) 
>>>>
>>>>     -
>>>>     -# Testing invalid vip results in extra error messages from
>>>>     socket-util.c
>>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>>     <http://10.0.0.1:80>", protocol = "sctp", load_balancer =
>>>>     "12345678-abcd-9876-fedc-11119f8e7d6c");
>>>>     -    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
>>>>     -trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80
>>>>     <http://10.0.0.1:80>", protocol = "tcp", load_balancer = "bacon");
>>>>     -    Load balancer 'bacon' is not a UUID
>>>>     -
>>>>     -# IGMP
>>>>     -igmp;
>>>>     -    encodes as controller(userdata=00.00.00.10.00.00.00.00)
>>>>     -
>>>>     -# Contradictionary prerequisites (allowed but not useful):
>>>>     -ip4.src = ip6.src[0..31];
>>>>     -    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
>>>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>>>     -ip4.src <-> ip6.src[0..31];
>>>>     -    encodes as
>>>> push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[] 
>>>>
>>>>     -    has prereqs eth.type == 0x800 && eth.type == 0x86dd
>>>>     -
>>>>     -# check_pkt_larger
>>>>     -reg0[0] = check_pkt_larger(1500);
>>>>     -    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
>>>>     -
>>>>     -reg0 = check_pkt_larger(1500);
>>>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>>>     required.
>>>>     -
>>>>     -reg0 = check_pkt_larger(foo);
>>>>     -    Cannot use 32-bit field reg0[0..31] where 1-bit field is
>>>>     required.
>>>>     -
>>>>     -reg0[0] = check_pkt_larger(foo);
>>>>     -    Syntax error at `foo' expecting `;'.
>>>>     -
>>>>     -# Miscellaneous negative tests.
>>>>     -;
>>>>     -    Syntax error at `;'.
>>>>     -xyzzy;
>>>>     -    Syntax error at `xyzzy' expecting action.
>>>>     -next; 123;
>>>>     -    Syntax error at `123'.
>>>>     -next; xyzzy;
>>>>     -    Syntax error at `xyzzy' expecting action.
>>>>     -next
>>>>     -    Syntax error at end of input expecting `;'.
>>>>     -]])
>>>>     -sed '/^[[      ]]/d' test-cases.txt > input.txt
>>>>     -cp test-cases.txt expout
>>>>     -AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], 
>>>> [expout])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_BANNER([OVN end-to-end tests])
>>>>     -
>>>>     -# 3 hypervisors, one logical switch, 3 logical ports per 
>>>> hypervisor
>>>>     -AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
>>>>     -AT_KEYWORDS([ovnarp])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Create hypervisors hv[123].
>>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>>     -# Add all of the vifs to a single logical switch lsw0.
>>>>     -# Turn on port security on all the vifs except vif[123]1.
>>>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2 3; do
>>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>>     -        if test $j = 1; then
>>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>>>     -        else
>>>>     -            if test $j = 3; then
>>>>     -                ip_addrs="192.168.0.$i$j
>>>>     fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
>>>>     -            else
>>>>     -                ip_addrs="192.168.0.$i$j"
>>>>     -            fi
>>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>>     "f0:00:00:00:00:$i$j $ip_addrs"
>>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>>     f0:00:00:00:00:$i$j
>>>>     -        fi
>>>>     -    done
>>>>     -done
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>>>     inport == "lp11"' drop
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>>>     outport == "lp33"' drop
>>>>     -ovn-nbctl create Address_Set name=set1
>>>> addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\" 
>>>>
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>>>     eth.src == $set1 && outport == "lp33"' drop
>>>>     -
>>>>     -get_lsp_uuid () {
>>>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>>>     -}
>>>>     -
>>>>     -ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid
>>>>     lp22`,`get_lsp_uuid lp33`
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 &&
>>>>     outport == @pg1' drop
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Make sure there is no attempt to adding duplicated flows by
>>>>     ovn-controller
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv${1%?}
>>>>     -}
>>>>     -
>>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>>     for vif11.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>>     -    local
>>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>>     -
>>>>     -    if test X$reply_ha = X; then
>>>>     -        # Expect to receive the broadcast ARP on the other
>>>>     logical switch ports
>>>>     -        # if no reply is expected.
>>>>     -        local i j
>>>>     -        for i in 1 2 3; do
>>>>     -            for j in 1 2 3; do
>>>>     -                if test $i$j != $inport; then
>>>>     -                    echo $request >> $i$j.expected
>>>>     -                fi
>>>>     -            done
>>>>     -        done
>>>>     -    else
>>>>     -        # Expect to receive the reply, if any.
>>>>     -        local
>>>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>>
>>>>     -        echo $reply >> $inport.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send packets between all pairs of source and destination ports:
>>>>     -#
>>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>>> switch port
>>>>     -#    (except that packets destined to their input ports are 
>>>> dropped).
>>>>     -#
>>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>>     ports
>>>>     -#    except the input port.
>>>>     -#
>>>>     -# 3. When port security is turned on, the switch drops packets
>>>>     from the wrong
>>>>     -#    MAC address.
>>>>     -#
>>>>     -# 4. The switch drops all packets with a VLAN tag.
>>>>     -#
>>>>     -# 5. The switch drops all packets with a multicast source
>>>>     address.  (This only
>>>>     -#    affects behavior when port security is turned off, since
>>>>     otherwise port
>>>>     -#    security would drop the packet anyway.)
>>>>     -#
>>>>     -# 6. The switch delivers packets with an unknown destination to
>>>>     logical
>>>>     -#    switch ports with "unknown" among their MAC addresses 
>>>> (and port
>>>>     -#    security disabled).
>>>>     -#
>>>>     -# 7. The switch drops unicast packets that violate an ACL.
>>>>     -#
>>>>     -# 8. The switch drops multicast and broadcast packets that
>>>>     violate an ACL.
>>>>     -#
>>>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>>>     except for
>>>>     -#    requests from a port for the port's own IP.
>>>>     -#
>>>>     -# 10. No response to ARP requests for unknown IPs.
>>>>     -
>>>>     -for is in 1 2 3; do
>>>>     -    for js in 1 2 3; do
>>>>     -        s=$is$js
>>>>     -        bcast=
>>>>     -        unknown=
>>>>     -        bacl2=
>>>>     -        bacl3=
>>>>     -        for id in 1 2 3; do
>>>>     -            for jd in 1 2 3; do
>>>>     -                d=$id$jd
>>>>     -
>>>>     -                if test $d != $s; then unicast=$d; else 
>>>> unicast=; fi
>>>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>>>     $unicast     #1
>>>>     -
>>>>     -                if test $d != $s && test $js = 1; then
>>>>     -                    impersonate=$d
>>>>     -                else
>>>>     -                    impersonate=
>>>>     -                fi
>>>>     -                test_packet $s f000000000$d f00000000055 55$d
>>>>     $impersonate #3
>>>>     -
>>>>     -                if test $d != $s && test $s != 11; then acl2=$d;
>>>>     else acl2=; fi
>>>>     -                if test $d != $s && test $d != 33; then acl3=$d;
>>>>     else acl3=; fi
>>>>     -                if test $d = $s || (test $js = 1 && test $d =
>>>>     33); then
>>>>     -                    # Source of 11, 21, or 31 and dest of 33
>>>>     should be dropped
>>>>     -                    # due to the 4th ACL that uses 
>>>> address_set(set1).
>>>>     -                    acl4=
>>>>     -                else
>>>>     -                    acl4=$d
>>>>     -                fi
>>>>     -                if test $d = $s || test $d = 22 || test $d = 
>>>> 33; then
>>>>     -                    # dest of 22 and 33 should be dropped
>>>>     -                    # due to the 5th ACL that uses 
>>>> port_group(pg1).
>>>>     -                    acl5=
>>>>     -                else
>>>>     -                    acl5=$d
>>>>     -                fi
>>>>     -                test_packet $s f000000000$d f000000000$s 1234
>>>>         #7, acl1
>>>>     -                test_packet $s f000000000$d f000000000$s 1235
>>>>     $acl2  #7, acl2
>>>>     -                test_packet $s f000000000$d f000000000$s 1236
>>>>     $acl3  #7, acl3
>>>>     -                test_packet $s f000000000$d f000000000$s 1237
>>>>     $acl4  #7, acl4
>>>>     -                test_packet $s f000000000$d f000000000$s 1238
>>>>     $acl5  #7, acl5
>>>>     -
>>>>     -                test_packet $s f000000000$d f00000000055
>>>>     810000091234      #4
>>>>     -                test_packet $s f000000000$d 0100000000$s $s$d
>>>>               #5
>>>>     -
>>>>     -                if test $d != $s && test $jd = 1; then
>>>>     -                    unknown="$unknown $d"
>>>>     -                fi
>>>>     -                bcast="$bcast $unicast"
>>>>     -                bacl2="$bacl2 $acl2"
>>>>     -                bacl3="$bacl3 $acl3"
>>>>     -
>>>>     -                sip=`ip_to_hex 192 168 0 $is$js`
>>>>     -                tip=`ip_to_hex 192 168 0 $id$jd`
>>>>     -                tip_unknown=`ip_to_hex 11 11 11 11`
>>>>     -                if test $d != $s; then
>>>>     -                    reply_ha=f000000000$d
>>>>     -                else
>>>>     -                    reply_ha=
>>>>     -                fi
>>>>     -                test_arp $s f000000000$s $sip $tip $reply_ha
>>>>              #9
>>>>     -                test_arp $s f000000000$s $sip $tip_unknown
>>>>              #10
>>>>     -
>>>>     -                if test $jd = 3; then
>>>>     -                    # lsp[123]3 has an additional ip
>>>>     192.169.0.[123]3.
>>>>     -                    tip=`ip_to_hex 192 169 0 $id$jd`
>>>>     -                    test_arp $s f000000000$s $sip $tip $reply_ha
>>>>              #9
>>>>     -                fi
>>>>     -            done
>>>>     -        done
>>>>     -
>>>>     -        # Broadcast and multicast.
>>>>     -        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast
>>>>              #2
>>>>     -        test_packet $s 010000000000 f000000000$s ${s}ff $bcast
>>>>              #2
>>>>     -        if test $js = 1; then
>>>>     -            bcast_impersonate=$bcast
>>>>     -        else
>>>>     -            bcast_impersonate=
>>>>     -        fi
>>>>     -        test_packet $s 010000000000 f00000000044 44ff
>>>>     $bcast_impersonate   #3
>>>>     -
>>>>     -        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown
>>>>              #6
>>>>     -
>>>>     -        test_packet $s ffffffffffff f000000000$s 1234
>>>>     #8, acl1
>>>>     -        test_packet $s ffffffffffff f000000000$s 1235 $bacl2
>>>>        #8, acl2
>>>>     -        test_packet $s ffffffffffff f000000000$s 1236 $bacl3
>>>>        #8, acl3
>>>>     -        test_packet $s 010000000000 f000000000$s 1234
>>>>     #8, acl1
>>>>     -        test_packet $s 010000000000 f000000000$s 1235 $bacl2
>>>>        #8, acl2
>>>>     -        test_packet $s 010000000000 f000000000$s 1236 $bacl3
>>>>        #8, acl3
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# set address for lp13 with invalid characters.
>>>>     -# lp13 should be configured with only 192.168.0.13.
>>>>     -ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13
>>>>     invalid 192.169.0.13"
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 11`
>>>>     -tip=`ip_to_hex 192 168 0 13`
>>>>     -test_arp 11 f00000000011  $sip $tip f00000000013
>>>>     -
>>>>     -tip=`ip_to_hex 192 169 0 13`
>>>>     -#arp request for 192.169.0.13 should be flooded
>>>>     -test_arp 11 f00000000011  $sip $tip
>>>>     -
>>>>     -# dump information and flows with counters
>>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv3 dump ------"
>>>>     -as hv3 ovs-vsctl show
>>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], 
>>>> [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 2 hypervisors, one logical switch, 2 logical ports per 
>>>> hypervisor
>>>>     -# logical ports bound to chassis encap-ip.
>>>>     -AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
>>>>     -AT_KEYWORDS([ovnarp])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Create hypervisors hv[12].
>>>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2; do
>>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>>     -        ip_addrs="192.168.0.$i$j"
>>>>     -        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j
>>>>     $ip_addrs"
>>>>     -        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j
>>>>     f0:00:00:00:00:$i$j
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -get_lsp_uuid () {
>>>>     -    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
>>>>     -}
>>>>     -
>>>>     -# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just
>>>>     do it
>>>>     -# explictly
>>>>     -
>>>>     -# For Chassis hv1
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp11], [0], [dnl
>>>>     -encap               : [[]]
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp12], [0], [dnl
>>>>     -encap               : [[]]
>>>>     -])
>>>>     -
>>>>     -# For Chassis hv2
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp21], [0], [dnl
>>>>     -encap               : [[]]
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp22], [0], [dnl
>>>>     -encap               : [[]]
>>>>     -])
>>>>     -
>>>>     -# Bind the ports to the encap-ip
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        as hv$i
>>>>     -        ovs-vsctl set Interface vif$i$j
>>>>     external-ids:encap-ip=192.168.0.$i
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -sleep 1
>>>>     -
>>>>     -# dump port bindings; since we have vxlan and geneve tunnels, we
>>>>     expect the
>>>>     -# ports to be bound to geneve tunnels.
>>>>     -
>>>>     -# For Chassis 1
>>>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>>>     encap chassis_name=hv1 type=geneve ip=192.168.0.1`
>>>>     -
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp11], [0], [dnl
>>>>     -encap               : ${encap_rec}
>>>>     -])
>>>>     -
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp12], [0], [dnl
>>>>     -encap               : ${encap_rec}
>>>>     -])
>>>>     -
>>>>     -# For Chassis 2
>>>>     -encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find
>>>>     encap chassis_name=hv2 type=geneve ip=192.168.0.2`
>>>>     -
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp21], [0], [dnl
>>>>     -encap               : ${encap_rec}
>>>>     -])
>>>>     -
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding
>>>>     lp22], [0], [dnl
>>>>     -encap               : ${encap_rec}
>>>>     -])
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Make sure there is no attempt to adding duplicated flows by
>>>>     ovn-controller
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
>>>>     -AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv${1%?}
>>>>     -}
>>>>     -
>>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>>     for vif11.
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send packets between all pairs of source and destination ports:
>>>>     -#
>>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>>> switch port
>>>>     -#    (except that packets destined to their input ports are 
>>>> dropped).
>>>>     -
>>>>     -for is in 1 2; do
>>>>     -    for js in 1 2; do
>>>>     -        s=$is$js
>>>>     -        bcast=
>>>>     -        unknown=
>>>>     -        bacl2=
>>>>     -        bacl3=
>>>>     -        for id in 1 2 3; do
>>>>     -            for jd in 1 2 3; do
>>>>     -                d=$id$jd
>>>>     -
>>>>     -                if test $d != $s; then unicast=$d; else 
>>>> unicast=; fi
>>>>     -                test_packet $s f000000000$d f000000000$s $s$d
>>>>     $unicast     #1
>>>>     -            done
>>>>     -        done
>>>>     -
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# dump information and flows with counters
>>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv3 dump ------"
>>>>     -as hv3 ovs-vsctl show
>>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], 
>>>> [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Create a logical switch and some logical ports.
>>>>     -# Turn on port security on all lports except ls1.
>>>>     -# Make ls1 a destination for unknown MACs.
>>>>     -# Add some ACLs for Ethertypes 1234, 1235, 1236.
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -ovn-sbctl chassis-add hv0 geneve 127.0.0.1
>>>>     -for i in 1 2 3; do
>>>>     -    ovn-nbctl lsp-add lsw0 lp$i
>>>>     -done
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -for i in 1 2 3; do
>>>>     -    ovn-sbctl lsp-bind lp$i hv0
>>>>     -    if test $i = 1; then
>>>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>>>     192.168.0.$i" unknown
>>>>     -    else
>>>>     -        if test $i = 3; then
>>>>     -           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64
>>>>     192.169.0.$i"
>>>>     -        else
>>>>     -           ip_addrs="192.168.0.$i"
>>>>     -        fi
>>>>     -        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i
>>>>     $ip_addrs"
>>>>     -        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
>>>>     -    fi
>>>>     -done
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 &&
>>>>     inport == "lp1"' drop
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 &&
>>>>     outport == "lp3"' drop
>>>>     -ovn-nbctl create Address_Set name=set1
>>>>     addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 &&
>>>>     eth.src == $set1 && outport == "lp3"' drop
>>>>     -
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -on_exit 'kill `cat ovn-trace.pid`'
>>>>     -ovn-trace --detach --pidfile --no-chdir
>>>>     -
>>>>     -# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 11
>>>>     for vif11.
>>>>     -test_packet() {
>>>>     -    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
>>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst &&
>>>>     eth.src==$eth_src"
>>>>     -    while :; do
>>>>     -        case $1 in # (
>>>>     -            -vlan) uflow="$uflow && vlan.vid == 1234"; shift 
>>>> ;; # (
>>>>     -            -eth) uflow="$uflow && eth.type == 0x$2"; shift;
>>>>     shift ;; # (
>>>>     -            *) break ;;
>>>>     -        esac
>>>>     -    done
>>>>     -    for outport; do
>>>>     -        echo "output(\"lp$outport\");"
>>>>     -    done > expout
>>>>     -
>>>>     -    AT_CAPTURE_FILE([trace])
>>>>     -    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" |
>>>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>>>     -}
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>>     -
>>>>     -    local request="inport == \"lp$inport\"
>>>>     -                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src 
>>>> == $sha
>>>>     -                   && arp.op == 1 && arp.sha == $sha && arp.spa
>>>>     == $spa
>>>>     -                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa ==
>>>>     $tpa"
>>>>     -
>>>>     -    if test -z "$reply_ha"; then
>>>>     -        reply=
>>>>     -        local i
>>>>     -        for i in 1 2 3; do
>>>>     -            if test $i != $inport; then
>>>>     -                reply="${reply}output(\"lp$i\");
>>>>     -"
>>>>     -            fi
>>>>     -        done
>>>>     -    else
>>>>     -        reply="\
>>>>     -eth.dst = $sha;
>>>>     -eth.src = $reply_ha;
>>>>     -arp.op = 2;
>>>>     -arp.tha = $sha;
>>>>     -arp.sha = $reply_ha;
>>>>     -arp.tpa = $spa;
>>>>     -arp.spa = $tpa;
>>>>     -output(\"lp$inport\");
>>>>     -"
>>>>     -    fi
>>>>     -
>>>>     -    AT_CAPTURE_FILE([trace])
>>>>     -    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0
>>>>     "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
>>>>     -}
>>>>     -
>>>>     -# Send packets between all pairs of source and destination ports:
>>>>     -#
>>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>>> switch port
>>>>     -#    (except that packets destined to their input ports are 
>>>> dropped).
>>>>     -#
>>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>>     ports
>>>>     -#    except the input port.
>>>>     -#
>>>>     -# 3. When port security is turned on, the switch drops packets
>>>>     from the wrong
>>>>     -#    MAC address.
>>>>     -#
>>>>     -# 4. The switch drops all packets with a VLAN tag.
>>>>     -#
>>>>     -# 5. The switch drops all packets with a multicast source
>>>>     address.  (This only
>>>>     -#    affects behavior when port security is turned off, since
>>>>     otherwise port
>>>>     -#    security would drop the packet anyway.)
>>>>     -#
>>>>     -# 6. The switch delivers packets with an unknown destination to
>>>>     logical
>>>>     -#    switch ports with "unknown" among their MAC addresses 
>>>> (and port
>>>>     -#    security disabled).
>>>>     -#
>>>>     -# 7. The switch drops unicast packets that violate an ACL.
>>>>     -#
>>>>     -# 8. The switch drops multicast and broadcast packets that
>>>>     violate an ACL.
>>>>     -#
>>>>     -# 9. OVN generates responses to ARP requests for known IPs,
>>>>     except for
>>>>     -#    requests from a port for the port's own IP.
>>>>     -#
>>>>     -# 10. No response to ARP requests for unknown IPs.
>>>>     -
>>>>     -for s in 1 2 3; do
>>>>     -    bcast=
>>>>     -    unknown=
>>>>     -    bacl2=
>>>>     -    bacl3=
>>>>     -    for d in 1 2 3; do
>>>>     -        echo
>>>>     -        echo "lp$s -> lp$d"
>>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s
>>>>     $unicast      #1
>>>>     -
>>>>     -        if test $d != $s && test $s = 1; then
>>>>     -            impersonate=$d
>>>>     -        else
>>>>     -            impersonate=
>>>>     -        fi
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>>>     $impersonate   #3
>>>>     -
>>>>     -        if test $d != $s && test $s != 1; then acl2=$d; else
>>>>     acl2=; fi
>>>>     -        if test $d != $s && test $d != 3; then acl3=$d; else
>>>>     acl3=; fi
>>>>     -        if test $d = $s || ( (test $s = 1 || test $s = 2) && test
>>>>     $d = 3); then
>>>>     -            # Source of 1 or 2 and dest of 3 should be dropped
>>>>     -            # due to the 4th ACL that uses address_set(set1).
>>>>     -            acl4=
>>>>     -        else
>>>>     -            acl4=$d
>>>>     -        fi
>>>>     -
>>>>     -        #7, acl1 to acl4:
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>>     1234
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>>     1235 $acl2
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>>     1236 $acl3
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth
>>>>     1237 $acl4
>>>>     -
>>>>     -        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55
>>>>     -vlan          #4
>>>>     -        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s
>>>>              #5
>>>>     -
>>>>     -        if test $d != $s && test $d = 1; then
>>>>     -            unknown="$unknown $d"
>>>>     -        fi
>>>>     -        bcast="$bcast $unicast"
>>>>     -        bacl2="$bacl2 $acl2"
>>>>     -        bacl3="$bacl3 $acl3"
>>>>     -
>>>>     -        sip=192.168.0.$s
>>>>     -        tip=192.168.0.$d
>>>>     -        tip_unknown=11.11.11.11
>>>>     -        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else
>>>>     reply_ha=; fi
>>>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>>>              #9
>>>>     -        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown
>>>>            #10
>>>>     -
>>>>     -        if test $d = 3; then
>>>>     -            # lp3 has an additional ip 192.169.0.[123]3.
>>>>     -            tip=192.169.0.$d
>>>>     -            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha
>>>>              #9
>>>>     -        fi
>>>>     -    done
>>>>     -
>>>>     -    # Broadcast and multicast.
>>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast
>>>>              #2
>>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast
>>>>              #2
>>>>     -    if test $s = 1; then
>>>>     -       bcast_impersonate=$bcast
>>>>     -    else
>>>>     -       bcast_impersonate=
>>>>     -    fi
>>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44
>>>>     $bcast_impersonate  #3
>>>>     -
>>>>     -    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown
>>>>              #6
>>>>     -
>>>>     -    #8, acl1 to acl3:
>>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
>>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235
>>>>     $bacl2
>>>>     -    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236
>>>>     $bacl3
>>>>     -
>>>>     -    #8, acl1 to acl3:
>>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
>>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235
>>>>     $bacl2
>>>>     -    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236
>>>>     $bacl3
>>>>     -done
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 2 hypervisors, 4 logical ports per HV
>>>>     -# 2 locally attached networks (one flat, one vlan tagged over
>>>>     same device)
>>>>     -# 2 ports per HV on each network
>>>>     -AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# In this test cases we create 3 switches, all connected to same
>>>>     -# physical network (through br-phys on each HV). Each switch has
>>>>     -# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first 
>>>> digit
>>>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>>>     -# lp23 means VIF 3 on hv2.
>>>>     -#
>>>>     -# Each switch's VLAN tag and their logical switch ports are:
>>>>     -#   - ls1:
>>>>     -#       - untagged
>>>>     -#       - ports: lp11, lp12, lp21, lp22
>>>>     -#
>>>>     -#   - ls2:
>>>>     -#       - tagged with VLAN 101
>>>>     -#       - ports: lp13, lp14, lp23, lp24
>>>>     -#   - ls3:
>>>>     -#       - untagged
>>>>     -#       - ports: lp15, lp25
>>>>     -#
>>>>     -# Note: a localnet port is created for each switch to connect to
>>>>     -# physical network.
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    ls_name=ls$i
>>>>     -    ovn-nbctl ls-add $ls_name
>>>>     -    ln_port_name=ln$i
>>>>     -    if test $i -eq 2; then
>>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>>>     -    else
>>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name
>>>>     -    fi
>>>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>>>     -done
>>>>     -
>>>>     -# lsp_to_ls LSP
>>>>     -#
>>>>     -# Prints the name of the logical switch that contains LSP.
>>>>     -lsp_to_ls () {
>>>>     -    case $1 in dnl (
>>>>     -        lp?[[12]]) echo ls1 ;; dnl (
>>>>     -        lp?[[34]]) echo ls2 ;; dnl (
>>>>     -        lp?5) echo ls3 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2 3 4 5; do
>>>>     -        ovs-vsctl add-port br-int vif$i$j -- \
>>>>     -            set Interface vif$i$j external-ids:iface-id=lp$i$j \
>>>>     - options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>>     - options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>>     -                                  ofport-request=$i$j
>>>>     -
>>>>     -        lsp_name=lp$i$j
>>>>     -        ls_name=$(lsp_to_ls $lsp_name)
>>>>     -
>>>>     -        ovn-nbctl lsp-add $ls_name $lsp_name
>>>>     -        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
>>>>     -        ovn-nbctl lsp-set-port-security $lsp_name 
>>>> f0:00:00:00:00:$i$j
>>>>     -
>>>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` =
>>>>     xup])
>>>>     -    done
>>>>     -done
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -ovn-sbctl dump-flows
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -# XXX This is now the 3rd copy of these functions in this file 
>>>> ...
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv${1%?}
>>>>     -}
>>>>     -#
>>>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is
>>>>     specified as
>>>>     -# logical switch port numbers, e.g. 11 for vif11.
>>>>     -#
>>>>     -# EOUT is the end-to-end output port, that is, where the packet
>>>>     will end up
>>>>     -# after possibly bouncing through one or more localnet ports.
>>>>     LOUT is the
>>>>     -# logical output port, which might be a localnet port, as seen by
>>>>     ovn-trace
>>>>     -# (which doesn't know what localnet ports are connected to and
>>>>     therefore can't
>>>>     -# figure out the end-to-end answer).
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2 3 4 5; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
>>>>     -    echo "$@"
>>>>     -
>>>>     -    # First try tracing the packet.
>>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>>>     eth.src==$src && eth.type==0x$eth"
>>>>     -    if test $lout != drop; then
>>>>     -        echo "output(\"$lout\");"
>>>>     -    fi > expout
>>>>     -    AT_CAPTURE_FILE([trace])
>>>>     -    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" |
>>>>     tee trace | sed '1,/Minimal trace/d'], [0], [expout])
>>>>     -
>>>>     -    # Then actually send a packet, for an end-to-end test.
>>>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    if test $eout != drop; then
>>>>     -        echo $packet >> ${eout#lp}.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -# lp11 and lp21 are on the same network (phys, untagged)
>>>>     -# and on different hypervisors
>>>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>>>     -
>>>>     -# lp11 and lp12 are on the same network (phys, untagged)
>>>>     -# and on the same hypervisor
>>>>     -test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
>>>>     -test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
>>>>     -
>>>>     -# lp13 and lp23 are on the same network (phys, VLAN 101)
>>>>     -# and on different hypervisors
>>>>     -test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
>>>>     -test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
>>>>     -
>>>>     -# lp13 and lp14 are on the same network (phys, VLAN 101)
>>>>     -# and on the same hypervisor
>>>>     -test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
>>>>     -test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
>>>>     -
>>>>     -# lp11 and lp15 are on the same network (phys, untagged),
>>>>     -# same hypervisor, and on different switches
>>>>     -test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
>>>>     -test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
>>>>     -
>>>>     -# lp11 and lp25 are on the same network (phys, untagged),
>>>>     -# different hypervisors, and on different switches
>>>>     -test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
>>>>     -test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
>>>>     -
>>>>     -# Ports that should not be able to communicate
>>>>     -test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
>>>>     -test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
>>>>     -test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
>>>>     -test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
>>>>     -test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
>>>>     -test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
>>>>     -test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
>>>>     -test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
>>>>     -
>>>>     -# Dump a bunch of info helpful for debugging if there's a 
>>>> failure.
>>>>     -
>>>>     -echo "------ OVN dump ------"
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2 3 4 5; do
>>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], 
>>>> [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
>>>>     -AT_KEYWORDS([vtep])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Configure the Northbound database
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp-vtep
>>>>     -ovn-nbctl lsp-set-type lp-vtep vtep
>>>>     -ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep
>>>>     vtep-logical-switch=lsw0
>>>>     -ovn-nbctl lsp-set-addresses lp-vtep unknown
>>>>     -
>>>>     -# lpr, lr and lrp1 are used for the ARP request handling test 
>>>> only.
>>>>     -ovn-nbctl lsp-add lsw0 lpr
>>>>     -ovn-nbctl lr-add lr
>>>>     -ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl set Logical_Switch_Port lpr type=router \
>>>>     -                             options:router-port=lrp1 \
>>>>     -    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
>>>>     -
>>>>     -
>>>>     -net_add n1               # Network to connect hv1, hv2, and vtep
>>>>     -net_add n2               # Network to connect vtep and hv3
>>>>     -
>>>>     -# Create hypervisor hv1 connected to n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>>     -
>>>>     -# Create hypervisor hv2 connected to n1
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>>>     -
>>>>     -
>>>>     -# Start the vtep emulator with a leg in both networks
>>>>     -sim_add vtep
>>>>     -as vtep
>>>>     -
>>>>     -ovsdb-tool create "$ovs_base"/vtep/vtep.db
>>>>     "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
>>>>     -ovs-appctl -t ovsdb-server ovsdb-server/add-db
>>>>     "$ovs_base"/vtep/vtep.db
>>>>     -
>>>>     -ovs-vsctl add-br br-phys
>>>>     -net_attach n1 br-phys
>>>>     -
>>>>     -mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
>>>>     -arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
>>>>     -ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24
>>>>     <http://192.168.0.3/24> >/dev/null || return 1
>>>>     -ovs-appctl ovs/route/add 192.168.0.3/24 <http://192.168.0.3/24>
>>>>     br-phys >/dev/null || return 1
>>>>     -
>>>>     -ovs-vsctl add-br br-vtep
>>>>     -net_attach n2 br-vtep
>>>>     -
>>>>     -vtep-ctl add-ps br-vtep
>>>>     -vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
>>>>     -vtep-ctl add-ls lsw0
>>>>     -
>>>>     -start_daemon ovs-vtep br-vtep
>>>>     -start_daemon ovn-controller-vtep
>>>>     --vtep-db=unix:"$ovs_base"/vtep/db.sock
>>>>     --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -
>>>>     -OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode
>>>>     lsw0 |
>>>>     -               grep -- source`"])
>>>>     -# It takes more time for the update to be processed by ovs-vtep.
>>>>     -sleep 1
>>>>     -
>>>>     -# Add hv3 on the other side of the vtep
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -net_attach n2 br-phys
>>>>     -
>>>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>>>     ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 1
>>>>     for vif1.
>>>>     -for i in 1 2 3; do
>>>>     -    : > $i.expected
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>>>     -    hv=hv$inport
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# Send packets between all pairs of source and destination ports:
>>>>     -#
>>>>     -# 1. Unicast packets are delivered to exactly one logical 
>>>> switch port
>>>>     -#    (except that packets destined to their input ports are 
>>>> dropped).
>>>>     -#
>>>>     -# 2. Broadcast and multicast are delivered to all logical switch
>>>>     ports
>>>>     -#    except the input port.
>>>>     -#
>>>>     -# 3. The switch delivers packets with an unknown destination to
>>>>     logical
>>>>     -#    switch ports with "unknown" among their MAC addresses 
>>>> (and port
>>>>     -#    security disabled).
>>>>     -for s in 1 2 3; do
>>>>     -    bcast=
>>>>     -    unknown=
>>>>     -    for d in 1 2 3; do
>>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>>>     $unicast       #1
>>>>     -
>>>>     -        # The vtep (vif3) is the only one configured for 
>>>> "unknown"
>>>>     -        if test $d != $s && test $d = 3; then
>>>>     -            unknown="$unknown $d"
>>>>     -        fi
>>>>     -        bcast="$bcast $unicast"
>>>>     -    done
>>>>     -
>>>>     -    # Broadcast and multicast.
>>>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>>>            #2
>>>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>>>            #2
>>>>     -
>>>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>>>            #3
>>>>     -done
>>>>     -
>>>>     -# ARP request should not be responded to by logical switch router
>>>>     -# type arp responder on HV1 and HV2 and should reach directly to
>>>>     -# vif1 and vif2
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -sha=f00000000003
>>>>     -spa=`ip_to_hex 192 168 1 2`
>>>>     -tpa=`ip_to_hex 192 168 1 1`
>>>> -request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -as hv3 ovs-appctl netdev-dummy/receive vif3 $request
>>>>     -echo $request >> 1.expected
>>>>     -echo $request >> 2.expected
>>>>     -
>>>>     -# dump information with counters
>>>>     -echo "------ OVN dump ------"
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv3 dump ------"
>>>>     -as hv3 ovs-vsctl show
>>>>     -# note: hv3 has no logical port bind, thus it should not have 
>>>> br-int
>>>>     -AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
>>>>     -[ovs-ofctl: br-int is not a bridge or a socket
>>>>     -])
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>>>     -done
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1],[hv2],[vtep])
>>>>     -OVN_CLEANUP_VSWITCH([hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# Similar test to "hardware GW"
>>>>     -AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Configure the Northbound database
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp-gw
>>>>     -ovn-nbctl lsp-set-type lp-gw l2gateway
>>>>     -ovn-nbctl lsp-set-options lp-gw network_name=physnet1
>>>>     l2gateway-chassis=hv_gw
>>>>     -ovn-nbctl lsp-set-addresses lp-gw unknown
>>>>     -
>>>>     -net_add n1               # Network to connect hv1, hv2, and gw
>>>>     -net_add n2               # Network to connect gw and hv3
>>>>     -
>>>>     -# Create hypervisor hv1 connected to n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>>     -
>>>>     -# Create hypervisor hv2 connected to n1
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>>     external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap
>>>>     options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
>>>>     -
>>>>     -# Create hypervisor hv_gw connected to n1 and n2
>>>>     -# connect br-phys bridge to n1; connect hv-gw bridge to n2
>>>>     -sim_add hv_gw
>>>>     -as hv_gw
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl add-br br-phys2
>>>>     -net_attach n2 br-phys2
>>>>     -ovs-vsctl set open .
>>>>     external_ids:ovn-bridge-mappings="physnet1:br-phys2"
>>>>     -
>>>>     -# Add hv3 on the other side of the GW
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -net_attach n2 br-phys
>>>>     -ovs-vsctl add-port br-phys vif3 -- set Interface vif3
>>>>     options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap
>>>>     ofport-request=1
>>>>     -
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# test_packet INPORT DST SRC ETHTYPE OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
>>>>     -for i in 1 2 3; do
>>>>     -    : > $i.expected
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
>>>>     -    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
>>>>     -    hv=hv$inport
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# Send packets between all pairs of source and destination ports:
>>>>     -#
>>>>     -# 1. Unicast packets are delivered to exactly one lport (except
>>>>     that packets
>>>>     -#    destined to their input ports are dropped).
>>>>     -#
>>>>     -# 2. Broadcast and multicast are delivered to all lports except
>>>>     the input port.
>>>>     -#
>>>>     -# 3. The lswitch delivers packets with an unknown destination to
>>>>     lports with
>>>>     -#    "unknown" among their MAC addresses (and port security
>>>>     disabled).
>>>>     -for s in 1 2 3 ; do
>>>>     -    bcast=
>>>>     -    unknown=
>>>>     -    for d in 1 2 3 ; do
>>>>     -        if test $d != $s; then unicast=$d; else unicast=; fi
>>>>     -        test_packet $s f0000000000$d f0000000000$s 00$s$d
>>>>     $unicast       #1
>>>>     -
>>>>     -        # The vtep (vif3) is the only one configured for 
>>>> "unknown"
>>>>     -        if test $d != $s && test $d = 3; then
>>>>     -            unknown="$unknown $d"
>>>>     -        fi
>>>>     -        bcast="$bcast $unicast"
>>>>     -    done
>>>>     -
>>>>     -    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast
>>>>            #2
>>>>     -    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast
>>>>            #3
>>>>     -    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown
>>>>            #4
>>>>     -done
>>>>     -
>>>>     -echo "------ ovn-nbctl show ------"
>>>>     -ovn-nbctl show
>>>>     -echo "------ ovn-sbctl show ------"
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -echo "------ hv1 ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -echo "------ hv1 br-int ------"
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -echo "------ hv1 br-phys ------"
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>>     -
>>>>     -echo "------ hv2 ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -echo "------ hv2 br-int ------"
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -echo "------ hv2 br-phys ------"
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>>     -
>>>>     -echo "------ hv_gw ------"
>>>>     -as hv_gw ovs-vsctl show
>>>>     -echo "------ hv_gw br-phys ------"
>>>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>>     -echo "------ hv_gw br-phys2 ------"
>>>>     -as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
>>>>     -
>>>>     -echo "------ hv3 ------"
>>>>     -as hv3 ovs-vsctl show
>>>>     -echo "------ hv3 br-phys ------"
>>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
>>>>     -done
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 3 hypervisors, 3 logical switches with 3 logical ports each, 1
>>>>     logical router
>>>>     -AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -#
>>>>     -# Three logical switches ls1, ls2, ls3.
>>>>     -# One logical router lr0 connected to ls[123],
>>>>     -# with nine subnets, three per logical switch:
>>>>     -#
>>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>>> <http://192.168.11.0/24>
>>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>>> <http://192.168.12.0/24>
>>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>>> <http://192.168.13.0/24>
>>>>     -#    ...
>>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>>> <http://192.168.33.0/24>
>>>>     -#
>>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>>     first two
>>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>>     -for i in 1 2 3; do
>>>>     -    ovn-nbctl ls-add ls$i
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            # Add "unknown" to MAC addresses for lp?11, so
>>>>     packets for
>>>>     -            # MAC-IP bindings discovered via ARP later have
>>>>     somewhere to go.
>>>>     -            if test $j$k = 11; then unknown=unknown; else
>>>>     unknown=; fi
>>>>     -
>>>>     -            ovn-nbctl \
>>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" 
>>>> $unknown
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>>     192.168.$i$j.254/24
>>>>     -        ovn-nbctl \
>>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>>     type=router \
>>>>     -  options:router-port=lrp$i$j \
>>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl set Logical_Switch_Port lrp33-attachment \
>>>>     -    addresses='"00:00:00:00:ff:33 192.168.33.254"'
>>>>     -
>>>>     -# Physical network:
>>>>     -#
>>>>     -# Three hypervisors hv[123].
>>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>>     lp?13 on hv3.
>>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>>     on hv3.
>>>>     -# lp?3[123] all on hv3.
>>>>     -
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    case $1 in dnl (
>>>>     -        ?11) echo 1 ;; dnl (
>>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its
>>>>     logical router
>>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>>     -vif_to_lrp() {
>>>>     -    echo ${1%?}
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its 
>>>> logical
>>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>>     -vif_to_ls() {
>>>>     -    echo ${1%??}
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -done
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            hv=`vif_to_hv $i$j$k`
>>>>     -                as hv$hv ovs-vsctl \
>>>>     -                -- add-port br-int vif$i$j$k \
>>>>     -                -- set Interface vif$i$j$k \
>>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>>     -                    ofport-request=$i$j$k
>>>>     -        done
>>>>     -    done
>>>>     -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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>>>     for vif123.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            : > $i$j$k.expected
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    in_ls=`vif_to_ls $inport`
>>>>     -    in_lrp=`vif_to_lrp $inport`
>>>>     -    for outport; do
>>>>     -        out_ls=`vif_to_ls $outport`
>>>>     -        if test $in_ls = $out_ls; then
>>>>     -            # Ports on the same logical switch receive exactly
>>>>     the same packet.
>>>>     -            echo $packet
>>>>     -        else
>>>>     -            # Routing decrements TTL and updates source and 
>>>> dest MAC
>>>>     -            # (and checksum).
>>>>     -            out_lrp=`vif_to_lrp $outport`
>>>>     -            echo
>>>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -        fi >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>>     -    local
>>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>>     -    as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $request
>>>>     -
>>>>     -    # Expect to receive the broadcast ARP on the other logical
>>>>     switch ports if
>>>>     -    # IP address is not configured to the switch patch port.
>>>>     -    local i=`vif_to_ls $inport`
>>>>     -    local j k
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            # 192.168.33.254 is configured to the switch patch
>>>>     port for lrp33,
>>>>     -            # so no ARP flooding expected for it.
>>>>     -            if test $i$j$k != $inport && test $tpa != `ip_to_hex
>>>>     192 168 33 254`; then
>>>>     -                echo $request >> $i$j$k.expected
>>>>     -            fi
>>>>     -        done
>>>>     -    done
>>>>     -
>>>>     -    # Expect to receive the reply, if any.
>>>>     -    if test X$reply_ha != X; then
>>>>     -        lrp=`vif_to_lrp $inport`
>>>>     -        local
>>>> reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>>
>>>>     -        echo $reply >> $inport.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>>     -as hv1 ovn-sbctl list port_binding
>>>>     -as hv1 ovn-sbctl list datapath_binding
>>>>     -as hv1 ovn-sbctl dump-flows
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Send IP packets between all pairs of source and destination 
>>>> ports:
>>>>     -#
>>>>     -# 1. Unicast IP packets are delivered to exactly one logical
>>>>     switch port
>>>>     -#    (except that packets destined to their input ports are 
>>>> dropped).
>>>>     -#
>>>>     -# 2. Broadcast IP packets are delivered to all logical switch 
>>>> ports
>>>>     -#    except the input port.
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -for is in 1 2 3; do
>>>>     -  for js in 1 2 3; do
>>>>     -    for ks in 1 2 3; do
>>>>     -      bcast=
>>>>     -      s=$is$js$ks
>>>>     -      smac=f00000000$s
>>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>>     -      for id in 1 2 3; do
>>>>     -          for jd in 1 2 3; do
>>>>     -              for kd in 1 2 3; do
>>>>     -                d=$id$jd$kd
>>>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>>>     -                if test $is = $id; then dmac=f00000000$d; else
>>>>     dmac=00000000ff$is$js; fi
>>>>     -                if test $d != $s; then unicast=$d; else 
>>>> unicast=; fi
>>>>     -
>>>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>>>     -
>>>>     -                if test $id = $is && test $d != $s; then
>>>>     bcast="$bcast $d"; fi
>>>>     -              done
>>>>     -          done
>>>>     -        done
>>>>     -      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
>>>>     -      done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -: > mac_bindings.expected
>>>>     -
>>>>     -# 3. Send an IP packet from every logical port to every other 
>>>> subnet,
>>>>     -#    to an IP address that does not have a static IP-MAC binding.
>>>>     -#    This should generate a broadcast ARP request for the 
>>>> destination
>>>>     -#    IP address in the destination subnet.
>>>>     -#    Moreover generate an ARP reply for each of the IP addresses
>>>>     ARPed
>>>>     -for is in 1 2 3; do
>>>>     -  for js in 1 2 3; do
>>>>     -    for ks in 1 2 3; do
>>>>     -      s=$is$js$ks
>>>>     -      smac=f00000000$s
>>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>>     -      for id in 1 2 3; do
>>>>     -        for jd in 1 2 3; do
>>>>     -          if test $is$js = $id$jd; then
>>>>     -            continue
>>>>     -          fi
>>>>     -
>>>>     -          # Send the packet.
>>>>     -          dmac=00000000ff$is$js
>>>>     -          # Calculate a 4th octet for the destination that is
>>>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP 
>>>> addresses
>>>>     -          # that have static MAC bindings, and fits in the range
>>>>     -          # 0-255.
>>>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>>>     -          test_ip $s $smac $dmac $sip $dip
>>>>     -
>>>>     -          # Every LP on the destination subnet's lswitch should
>>>>     -          # receive the ARP request.
>>>>     -          lrmac=00000000ff$id$jd
>>>>     -          lrip=`ip_to_hex 192 168 $id$jd 254`
>>>>     -
>>>> arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip} 
>>>>
>>>>     -          for jd2 in 1 2 3; do
>>>>     -            for kd in 1 2 3; do
>>>>     -              echo $arp >> $id$jd2$kd.expected
>>>>     -            done
>>>>     -          done
>>>>     -
>>>>     -          hmac=8000000000$o4
>>>>     -          rmac=00000000ff$id$jd
>>>>     -          echo
>>>> ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 
>>>>
>>>>     >> ${id}11.expected
>>>>     -
>>>>     -          host_mac=8000000000$o4
>>>>     -          lrmac=00000000ff$id$jd
>>>>     -
>>>>     -
>>>> arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip} 
>>>>
>>>>     -
>>>>     -          hv=hv`vif_to_hv ${id}${jd}1`
>>>>     -          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1
>>>>     $arp_reply
>>>>     -
>>>>     -          host_ip_pretty=192.168.$id$jd.$o4
>>>>     -          host_mac_pretty=80:00:00:00:00:$o4
>>>>     -          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >>
>>>>     mac_bindings.expected
>>>>     -        done
>>>>     -      done
>>>>     -    done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -# Test router replies to ARP requests from all source ports:
>>>>     -#
>>>>     -# 4. Router replies to query for its MAC address from port's own
>>>>     IP address.
>>>>     -#
>>>>     -# 5. Router replies to query for its MAC address from any random
>>>>     IP address
>>>>     -#    in its subnet.
>>>>     -#
>>>>     -# 6. No reply to query for IP address other than router IP.
>>>>     -#
>>>>     -# 7. No reply to query from another subnet.
>>>>     -for i in 1 2 3; do
>>>>     -  for j in 1 2 3; do
>>>>     -    for k in 1 2 3; do
>>>>     -      smac=f00000000$i$j$k               # Source MAC
>>>>     -      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
>>>>     -      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
>>>>     -      rmac=00000000ff$i$j                # Router MAC
>>>>     -      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in 
>>>> subnet
>>>>     -      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in
>>>>     subnet
>>>>     -
>>>>     -      test_arp $i$j$k $smac $sip        $rip $rmac     #4
>>>>     -      test_arp $i$j$k $smac $otherip    $rip $rmac     #5
>>>>     -      test_arp $i$j$k $smac $sip        $otherip    #6
>>>>     -
>>>>     -      # When rip is 192.168.33.254, ARP request from externalip
>>>>     won't be
>>>>     -      # filtered, because 192.168.33.254 is configured to switch
>>>>     peer port
>>>>     -      # for lrp33.
>>>>     -      lrp33_rsp=
>>>>     -      if test $i = 3 && test $j = 3; then
>>>>     -        lrp33_rsp=$rmac
>>>>     -      fi
>>>>     -      test_arp $i$j$k $smac $externalip $rip $lrp33_rsp #7
>>>>     -
>>>>     -      # MAC binding should be learned from ARP request.
>>>>     -      host_mac_pretty=f0:00:00:00:0$i:$j$k
>>>>     -
>>>>     -      host_ip_pretty=192.168.$i$j.$k
>>>>     -      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>>>     mac_bindings.expected
>>>>     -
>>>>     -      # mac_binding is learned and overwritten so only the last
>>>>     one remains.
>>>>     -      if test $k = 3; then
>>>>     -          # lrp33 will not learn from ARP request, because
>>>>     192.168.33.254 is
>>>>     -          # configured to switch peer port for lrp33.
>>>>     -          if test $i != 3 || test $j != 3; then
>>>>     -              host_ip_pretty=192.168.$i$j.55
>>>>     -              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >>
>>>>     mac_bindings.expected
>>>>     -          fi
>>>>     -      fi
>>>>     -
>>>>     -    done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -
>>>>     -# Allow some time for packet forwarding.
>>>>     -# XXX This can be improved.
>>>>     -sleep 1
>>>>     -
>>>>     -# 8. Send an IP packet from every logical port to every other
>>>>     subnet.  These
>>>>     -#    are the same packets already sent as #3, but now the
>>>>     destinations' IP-MAC
>>>>     -#    bindings have been discovered via ARP, so instead of
>>>>     provoking an ARP
>>>>     -#    request, these packets now get routed to their destinations
>>>>     (which don't
>>>>     -#    have static MAC bindings, so they go to the port we've
>>>>     designated as
>>>>     -#    accepting "unknown" MACs.)
>>>>     -for is in 1 2 3; do
>>>>     -  for js in 1 2 3; do
>>>>     -    for ks in 1 2 3; do
>>>>     -      s=$is$js$ks
>>>>     -      smac=f00000000$s
>>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>>     -      for id in 1 2 3; do
>>>>     -        for jd in 1 2 3; do
>>>>     -          if test $is$js = $id$jd; then
>>>>     -            continue
>>>>     -          fi
>>>>     -
>>>>     -          # Send the packet.
>>>>     -          dmac=00000000ff$is$js
>>>>     -          # Calculate a 4th octet for the destination that is
>>>>     -          # unique per $s, avoids the .1 .2 .3 and .254 IP 
>>>> addresses
>>>>     -          # that have static MAC bindings, and fits in the range
>>>>     -          # 0-255.
>>>>     -          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
>>>>     -          dip=`ip_to_hex 192 168 $id$jd $o4`
>>>>     -          test_ip $s $smac $dmac $sip $dip
>>>>     -
>>>>     -          # Expect the packet egress.
>>>>     -          host_mac=8000000000$o4
>>>>     -          outport=${id}11
>>>>     -          out_lrp=$id$jd
>>>>     -          echo
>>>> ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 
>>>>
>>>>     >> $outport.expected
>>>>     -        done
>>>>     -      done
>>>>     -    done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -ovn-sbctl -f csv -d bare --no-heading \
>>>>     -    -- --columns=logical_port,ip,mac list mac_binding > 
>>>> mac_bindings
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>>     -                              [$i$j$k.expected])
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# Check the MAC bindings against those expected.
>>>>     -AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort <
>>>>     mac_bindings.expected`
>>>>     -])
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IP relocation using GARP request])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -#
>>>>     -# Two logical switches ls1, ls2.
>>>>     -# One logical router lr0 connected to ls[12],
>>>>     -# with 2 subnets, 1 per logical switch:
>>>>     -#
>>>>     -#    lrp1 on ls1 for subnet 192.168.1.1/24 
>>>> <http://192.168.1.1/24>
>>>>     -#    lrp2 on ls2 for subnet 192.168.2.1/24 
>>>> <http://192.168.2.1/24>
>>>>     -#
>>>>     -# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
>>>>     -# VIFs' fixed IP addresses are 192.168.[12].1[12].
>>>>     -#
>>>>     -# There is a secondary IP 192.168.1.100 that is unknown in NB and
>>>>     learned
>>>>     -# through ARP only, and it can move between lp11 and lp12.
>>>>     -#
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2 ; do
>>>>     -    ovn-nbctl ls-add ls$i
>>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 
>>>> 192.168.$i.1/24
>>>>     -    ovn-nbctl \
>>>>     -        -- lsp-add ls$i lrp$i-attachment \
>>>>     -        -- set Logical_Switch_Port lrp$i-attachment type=router \
>>>>     -                         options:router-port=lrp$i \
>>>>     -                         addresses=router
>>>>     -    for j in 1 2; do
>>>>     -        ovn-nbctl \
>>>>     -            -- lsp-add ls$i lp$i$j \
>>>>     -            -- lsp-set-addresses lp$i$j \
>>>>     -               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# Physical network:
>>>>     -# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located, e.g. "vif_to_hv 12" yields 2.
>>>>     -vif_to_hv() {
>>>>     -    echo ${1#?}
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its
>>>>     logical router
>>>>     -# port, e.g. "vif_to_lrp 12" yields 1.
>>>>     -vif_to_lrp() {
>>>>     -    echo ${1%?}
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its 
>>>> logical
>>>>     -# switch, e.g. "vif_to_ls 12" yields 1.
>>>>     -vif_to_ls() {
>>>>     -    echo ${1%?}
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -done
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        hv=`vif_to_hv $i$j`
>>>>     -            as hv$hv ovs-vsctl \
>>>>     -                -- add-port br-int vif$i$j \
>>>>     -                -- set Interface vif$i$j \
>>>>     -                    external-ids:iface-id=lp$i$j \
>>>>     - options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
>>>>     - options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
>>>>     -                    ofport-request=$i$j
>>>>     -    done
>>>>     -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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 12
>>>>     for vif12.
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    in_ls=`vif_to_ls $inport`
>>>>     -    in_lrp=`vif_to_lrp $inport`
>>>>     -    for outport; do
>>>>     -        out_ls=`vif_to_ls $outport`
>>>>     -        if test $in_ls = $out_ls; then
>>>>     -            # Ports on the same logical switch receive exactly
>>>>     the same packet.
>>>>     -            echo $packet
>>>>     -        else
>>>>     -            # Routing decrements TTL and updates source and 
>>>> dest MAC
>>>>     -            # (and checksum).
>>>>     -            out_lrp=`vif_to_lrp $outport`
>>>>     -            echo
>>>> f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -        fi >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
>>>>     -    local
>>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>>     -
>>>>     -    # Expect to receive the broadcast ARP on the other logical
>>>>     switch ports if
>>>>     -    # IP address is not configured to the switch patch port.
>>>>     -    local i=`vif_to_ls $inport`
>>>>     -    local j
>>>>     -    for j in 1 2; do
>>>>     -        if test $i$j != $inport; then
>>>>     -            echo $request >> $i$j$k.expected
>>>>     -        fi
>>>>     -    done
>>>>     -
>>>>     -    # Expect to receive the reply, if any.
>>>>     -    if test X$reply_ha != X; then
>>>>     -        lrp=`vif_to_lrp $inport`
>>>>     -        local
>>>> reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>>
>>>>     -        echo $reply >> $inport.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# lp11 send GARP request to announce ownership of 192.168.1.100.
>>>>     -
>>>>     -sha=f00000000011
>>>>     -spa=`ip_to_hex 192 168 1 100`
>>>>     -tpa=$spa
>>>>     -test_arp 11 $sha $spa $tpa
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>>     ip="192.168.1.100" | wc -l` -gt 0])
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>>>     to lp11.
>>>>     -
>>>>     -smac=f00000000021
>>>>     -dmac=00000000ff02
>>>>     -sip=`ip_to_hex 192 168 2 11`
>>>>     -dip=`ip_to_hex 192 168 1 100`
>>>>     -test_ip 21 $smac $dmac $sip $dip 11
>>>>     -
>>>>     -# lp12 send GARP request to announce ownership of 192.168.1.100.
>>>>     -
>>>>     -sha=f00000000012
>>>>     -test_arp 12 $sha $spa $tpa
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" |
>>>>     grep f0:00:00:00:00:12])
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -# give to the hv the time to send queued ip packets
>>>>     -sleep 1
>>>>     -
>>>>     -# Send an IP packet from lp21 to 192.168.1.100, which should go
>>>>     to lp12.
>>>>     -
>>>>     -test_ip 21 $smac $dmac $sip $dip 12
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2; do
>>>>     -    for j in 1 2; do
>>>>     -        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
>>>>     -                          [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 3 hypervisors, one logical switch, 3 logical ports per 
>>>> hypervisor
>>>>     -AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Create hypervisors hv[123].
>>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>>     -# Add all of the vifs to a single logical switch lsw0.
>>>>     -# Turn off port security on vifs vif[123]1
>>>>     -# Turn on l2 port security on vifs vif[123]2
>>>>     -# Turn of l2 and l3 port security on vifs vif[123]3
>>>>     -# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2 3; do
>>>>     -        ovs-vsctl add-port br-int vif$i$j -- set Interface
>>>>     vif$i$j external-ids:iface-id=lp$i$j
>>>>     options:tx_pcap=hv$i/vif$i$j-tx.pcap
>>>>     options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
>>>>     -        ovn-nbctl lsp-add lsw0 lp$i$j
>>>>     -        if test $j = 1; then
>>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
>>>>     -        elif test $j = 2; then
>>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j"
>>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>>     f0:00:00:00:00:$i$j
>>>>     -        else
>>>>     -            extra_addr="f0:00:00:00:0$i:$i$j
>>>>     fe80::ea2a:eaff:fe28:$i$j"
>>>>     -            ovn-nbctl lsp-set-addresses lp$i$j
>>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>>>     -            ovn-nbctl lsp-set-port-security lp$i$j
>>>>     "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
>>>>     -        fi
>>>>     -    done
>>>>     -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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv${1%?}
>>>>     -}
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -#
>>>>     -# This shell function causes an ip packet to be received on 
>>>> INPORT.
>>>>     -# The packet's content has Ethernet destination DST and source 
>>>> SRC
>>>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>>>     digits).
>>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>>     should
>>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>>     switch
>>>>     -# port numbers, e.g. 11 for vif11.
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 
>>>> reply_ha=$7
>>>>     -    local
>>>> request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $request
>>>>     -    if test $drop != 1; then
>>>>     -        if test X$reply_ha = X; then
>>>>     -            # Expect to receive the broadcast ARP on the other
>>>>     logical switch ports
>>>>     -            # if no reply is expected.
>>>>     -            local i j
>>>>     -            for i in 1 2 3; do
>>>>     -                for j in 1 2 3; do
>>>>     -                    if test $i$j != $inport; then
>>>>     -                        echo $request >> $i$j.expected
>>>>     -                    fi
>>>>     -                done
>>>>     -            done
>>>>     -        else
>>>>     -            # Expect to receive the reply, if any.
>>>>     -            local
>>>> reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>>
>>>>     -            echo $reply >> $inport.expected
>>>>     -        fi
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -# This function is similar to test_ip() except that it sends
>>>>     -# ipv6 packet
>>>>     -test_ipv6() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE
>>>>     OUTPORT...
>>>>     -# This function is similar to test_ipv6() except it specifies the
>>>>     ICMPv6 type
>>>>     -# of the test packet
>>>>     -test_icmpv6() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     icmp_type=$6
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000 
>>>>
>>>>     -    shift; shift; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# no port security
>>>>     -sip=`ip_to_hex 192 168 0 12`
>>>>     -tip=`ip_to_hex 192 168 0 13`
>>>>     -# the arp packet should be allowed even if lp[123]1 is
>>>>     -# not configured with mac f00000000023 and ip 192.168.0.12
>>>>     -for i in 1 2 3; do
>>>>     -    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 
>>>> f00000000013
>>>>     -    for j in 1 2 3; do
>>>>     -        if test $i != $j; then
>>>>     -            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip
>>>>     $tip ${j}1
>>>>     -        fi
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# l2 port security
>>>>     -sip=`ip_to_hex 192 168 0 12`
>>>>     -tip=`ip_to_hex 192 168 0 13`
>>>>     -
>>>>     -# arp packet should be allowed since lp22 is configured with
>>>>     -# mac f00000000022
>>>>     -test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
>>>>     -
>>>>     -# arp packet should not be allowed since lp32 is not 
>>>> configured with
>>>>     -# mac f00000000021
>>>>     -test_arp 32 f00000000021 f00000000021 $sip $tip 1
>>>>     -
>>>>     -# arp packet with sha set to f00000000021 should not be allowed
>>>>     -# for lp12
>>>>     -test_arp 12 f00000000012 f00000000021 $sip $tip 1
>>>>     -
>>>>     -# ip packets should be allowed and received since lp[123]2 do not
>>>>     -# have l3 port security
>>>>     -sip=`ip_to_hex 192 168 0 55`
>>>>     -tip=`ip_to_hex 192 168 0 66`
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        if test $i != $j; then
>>>>     -            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip
>>>>     $tip ${j}2
>>>>     -        fi
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# ipv6 packets should be received by lp[123]2
>>>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>>>     -sip=fe800000000000000000000000000000
>>>>     -tip=ff020000000000000000000000000000
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip 
>>>> ${i}2
>>>>     -done
>>>>     -
>>>>     -
>>>>     -# l2 and l3 port security
>>>>     -sip=`ip_to_hex 192 168 0 13`
>>>>     -tip=`ip_to_hex 192 168 0 22`
>>>>     -# arp packet should be allowed since lp13 is configured with
>>>>     -# f00000000013 and 192.168.0.13
>>>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>>>     -
>>>>     -# the arp packet should be dropped because lp23 is not configured
>>>>     -# with mac f00000000022
>>>>     -sip=`ip_to_hex 192 168 0 13`
>>>>     -tip=`ip_to_hex 192 168 0 22`
>>>>     -test_arp 23 f00000000022 f00000000022 $sip $tip 1
>>>>     -
>>>>     -# the arp packet should be dropped because lp33 is not configured
>>>>     -# with ip 192.168.0.55
>>>>     -spa=`ip_to_hex 192 168 0 55`
>>>>     -tpa=`ip_to_hex 192 168 0 22`
>>>>     -test_arp 33 f00000000031 f00000000031 $spa $tpa 1
>>>>     -
>>>>     -# ip packets should not be received by lp[123]3 since
>>>>     -# l3 port security is enabled
>>>>     -sip=`ip_to_hex 192 168 0 55`
>>>>     -tip=`ip_to_hex 192 168 0 66`
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# ipv6 packets should be dropped for lp[123]3 since
>>>>     -# it is configured with only ipv4 address
>>>>     -sip=fe800000000000000000000000000000
>>>>     -tip=ff020000000000000000000000000000
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
>>>>     -done
>>>>     -
>>>>     -# ipv6 packets should not be received by lp[123]3 with mac
>>>>     f000000000$[123]3
>>>>     -# lp[123]1 can send ipv6 traffic as there is no port security
>>>>     -for i in 1 2 3; do
>>>>     -    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
>>>>     -done
>>>>     -
>>>>     -# lp13 has extra port security with mac f0000000113 and ipv6 addr
>>>>     -# fe80::ea2a:eaff:fe28:0012
>>>>     -
>>>>     -# ipv4 packet should be dropped for lp13 with mac f0000000113
>>>>     -sip=`ip_to_hex 192 168 0 13`
>>>>     -tip=`ip_to_hex 192 168 0 23`
>>>>     -test_ip 13 f00000000113 f00000000023 $sip $tip
>>>>     -
>>>>     -# ipv6 packet should be received by lp[123]3 with mac
>>>>     f00000000${i}${i}3
>>>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
>>>>     -# lp11 can send ipv6 traffic as there is no port security
>>>>     -sip=ee800000000000000000000000000000
>>>>     -for i in 1 2 3; do
>>>>     -    tip=fe80000000000000ea2aeafffe2800${i}3
>>>>     -    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
>>>>     -done
>>>>     -
>>>>     -
>>>>     -# ipv6 packet should not be received by lp33 with mac f0000000333
>>>>     -# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
>>>>     -# configured with fe80::ea2a:eaff:fe28:0033
>>>>     -# lp11 can send ipv6 traffic as there is no port security
>>>>     -
>>>>     -sip=ee800000000000000000000000000000
>>>>     -tip=fe80000000000000ea2aeafffe280023
>>>>     -test_ipv6 11 f00000000011 f00000000333 $sip $tip
>>>>     -
>>>>     -# ipv6 packet should be allowed for lp[123]3 with mac
>>>>     f0000000${i}${i}3
>>>>     -# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
>>>>     -# and should be dropped for any other ip6.src
>>>>     -# lp21 can receive ipv6 traffic as there is no port security
>>>>     -
>>>>     -tip=ee800000000000000000000000000000
>>>>     -for i in 1 2 3; do
>>>>     -    sip=fe80000000000000ea2aeafffe2800${i}3
>>>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
>>>>     -
>>>>     -    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
>>>>     -    sip=00000000000000000000000000000000
>>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>>     ff020000000000000000000000160000 83 21
>>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>>     ff020000000000000000000000160000 8f 21
>>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>>     ff0200000000000000ea2aeafffe2800 87 21
>>>>     -    # Traffic to non-multicast traffic should be dropped
>>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip 
>>>> $tip 83
>>>>     -    # Traffic of other ICMPv6 types should be dropped
>>>>     -    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip
>>>>     ff020000000000000000000000160000 80
>>>>     -
>>>>     -    # should be dropped
>>>>     -    sip=ae80000000000000ea2aeafffe2800aa
>>>>     -    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
>>>>     -done
>>>>     -
>>>>     -# configure lsp13 to send and received IPv4 packets with an
>>>>     address range
>>>>     -ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13
>>>>     192.168.0.13 20.0.0.4/24 <http://20.0.0.4/24> 10.0.0.0/24
>>>>     <http://10.0.0.0/24>"
>>>>     -
>>>>     -sleep 2
>>>>     -
>>>>     -sip=`ip_to_hex 10 0 0 13`
>>>>     -tip=`ip_to_hex 192 168 0 22`
>>>>     -# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
>>>>     -test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
>>>>     -
>>>>     -sip=`ip_to_hex 10 0 0 14`
>>>>     -tip=`ip_to_hex 192 168 0 23`
>>>>     -# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
>>>>     -# with dst ip 192.168.0.23 should be allowed
>>>>     -test_ip 13 f00000000013 f00000000023 $sip $tip 23
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 10 0 0 15`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 10.0.0.15 should be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 20 0 0 4`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 20.0.0.4 should be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 20 0 0 5`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 20.0.0.5 should not be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 20 0 0 255`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 20.0.0.255 should be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 192 168 0 255`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 192.168.0.255 should not be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip
>>>>     -
>>>>     -sip=`ip_to_hex 192 168 0 33`
>>>>     -tip=`ip_to_hex 224 0 0 4`
>>>>     -# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to 
>>>> lsp13
>>>>     -# with dst ip 224.0.0.4  should be received by lsp13
>>>>     -test_ip 33 f00000000033 f00000000013 $sip $tip 13
>>>>     -
>>>>     -#dump information including flow counters
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl dump-flows -- list multicast_group
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -echo "------ hv3 dump ------"
>>>>     -as hv3 ovs-vsctl show
>>>>     -as hv3 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], 
>>>> [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>>>     -# network. R1 has a switchs ls1 (191.168.1.0/24
>>>>     <http://191.168.1.0/24>) connected to it.
>>>>     -# R2 has ls2 (172.16.1.0/24 <http://172.16.1.0/24>) connected 
>>>> to it.
>>>>     -
>>>>     -ls1_lp1_mac="f0:00:00:01:02:03"
>>>>     -rp_ls1_mac="00:00:00:01:02:03"
>>>>     -rp_ls2_mac="00:00:00:01:02:04"
>>>>     -ls2_lp1_mac="f0:00:00:01:02:04"
>>>>     -
>>>>     -ls1_lp1_ip="192.168.1.2"
>>>>     -ls2_lp1_ip="172.16.1.2"
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lr-add R2
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>>>     type=router \
>>>>     -  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
>>>>     -
>>>>     -# Connect ls2 to R2
>>>>     -ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>>>     type=router \
>>>>     -  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
>>>>     -
>>>>     -# Connect R1 to R2
>>>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>>>     <http://20.0.0.1/24> peer=R2_R1
>>>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>>>     <http://20.0.0.2/24> peer=R1_R2
>>>>     -
>>>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.2
>>>>     -ovn-nbctl lr-route-add R2 "0.0.0.0/0 <http://0.0.0.0/0>" 20.0.0.1
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
>>>>     -
>>>>     -# Create logical port ls2-lp1 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Packet to send.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>>>     eth.dst==$rp_ls1_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>>>     ip4.dst==$ls2_lp1_ip &&
>>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Packet to Expect
>>>>     -# The TTL should be decremented by 2.
>>>>     -packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
>>>>     -        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip &&
>>>>     ip4.dst==$ls2_lp1_ip &&
>>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $packet | ovstest test-ovn expr-to-packets > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# Disable the ls2-lp1 port.
>>>>     -ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
>>>>     -grep "reg0 == 172.16.1.2" | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# Generate the packet destined for ls2-lp1 and it should not be
>>>>     delivered.
>>>>     -# Packet to send.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac &&
>>>>     eth.dst==$rp_ls1_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip &&
>>>>     ip4.dst==$ls2_lp1_ip &&
>>>>     -        udp && udp.src==53 && udp.dst==4369"
>>>>     -
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -# The 2nd packet sent shound not be received.
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
>>>>     -AT_KEYWORDS([router-admin-state])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR - R1 has switch ls1 with two subnets attached to it
>>>>     (191.168.1.0/24 <http://191.168.1.0/24>
>>>>     -# and 172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24> 172.16.1.1/24
>>>>     -ovn-nbctl <http://172.16.1.1/24-ovn-nbctl> lsp-add ls1 rp-ls1 --
>>>>     set Logical_Switch_Port rp-ls1 type=router \
>>>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     -          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03
>>>>     192.168.1.2"
>>>>     -
>>>>     -# Create logical port ls1-lp2 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>>     -          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 
>>>> 172.16.1.2"
>>>>     -
>>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>>     -    set interface vif2 external-ids:iface-id=ls1-lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Send ip packets between the two ports.
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Packet to send.
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>     -
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -
>>>>     -#Disable router R1
>>>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>     -
>>>>     -# Packet to Expect
>>>>     -expect_src_mac="000000010203"
>>>>     -expect_dst_mac="f00000010204"
>>>>     -echo
>>>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
>>>>     -AT_KEYWORDS([router-admin-state])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>>     <http://191.168.1.0/24>) connected to it,
>>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1
>>>>     type=router \
>>>>     -          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
>>>>     -
>>>>     -# Connect ls2 to R1
>>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2
>>>>     type=router \
>>>>     -          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port ls2-lp1 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Send ip packets between the two ports.
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Packet to send.
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>     -
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -#Disable router R1
>>>>     -ovn-nbctl set Logical_Router R1 enabled=false
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Allow some time for the disabling of logical router R1 to
>>>>     propagate.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
>>>>     -
>>>>     -# Packet to Expect
>>>>     -expect_src_mac="000000010204"
>>>>     -expect_dst_mac="f00000010204"
>>>>     -echo
>>>> "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static 
>>>> routes])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other as peers
>>>>     in 20.0.0.0/24 <http://20.0.0.0/24>
>>>>     -# network. R1 has switchess foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>)
>>>>     -# connected to it.
>>>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and bob
>>>>     (172.16.2.0/24 <http://172.16.2.0/24>) connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lr-add R2
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add bob
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -          type=router options:router-port=alice
>>>>     addresses=\"00:00:00:01:02:04\"
>>>>     -
>>>>     -# Connect bob to R2
>>>>     -ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
>>>>     <http://172.16.2.1/24>
>>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob
>>>>     type=router \
>>>>     -          options:router-port=bob addresses=\"00:00:00:01:02:05\"
>>>>     -
>>>>     -# Connect R1 to R2
>>>>     -ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24
>>>>     <http://20.0.0.1/24> peer=R2_R1
>>>>     -ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24
>>>>     <http://20.0.0.2/24> peer=R1_R2
>>>>     -
>>>>     -#install static routes
>>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -ovn-nbctl lr-route-add R2 172.16.2.0/24 <http://172.16.2.0/24>
>>>>     20.0.0.2 R1_R2
>>>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     20.0.0.1
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Create logical port bob1 in bob
>>>>     -ovn-nbctl lsp-add bob bob1 \
>>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -# Send ip packets between foo1 and bob1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump ----------"
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Packet to Expect at bob1
>>>>     -src_mac="000000010205"
>>>>     -dst_mac="f00000010205"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 2 2`
>>>>     -echo
>>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Packet to Expect at alice1
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="f00000010204"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>>     -echo
>>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send gratuitous arp on localnet])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0
>>>>     -
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>>     snoopvif options:tx_pcap=hv/snoopvif-tx.pcap
>>>>     options:rxq_pcap=hv/snoopvif-rx.pcap])
>>>>     -
>>>>     -# Create a vif.
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>>>     "f0:00:00:00:00:01 192.168.1.2"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>>>     "f0:00:00:00:00:01"])
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>>> network_name=physnet1])
>>>>     -
>>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>>>     localvif1 external_ids:iface-id=localvif1])
>>>>     -
>>>>     -# Wait for packet to be received.
>>>>     -echo
>>>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>>>
>>>>     > expected
>>>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>>>     -
>>>>     -# Check GARP packet when restart openflow connection.
>>>>     -as hv
>>>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect"
>>>>     hv/ovn-controller.log])
>>>>     -
>>>>     -as hv
>>>>     -start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>>>     -vofproto_dpif -vunixctl
>>>>     -
>>>>     -# Wait for packet to be received.
>>>>     -echo
>>>> "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" 
>>>>
>>>>     > expected
>>>>     -OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
>>>>     -
>>>>     -# Delete the localnet ports.
>>>>     -AT_CHECK([ovs-vsctl del-port localvif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-del ln_port])
>>>>     -
>>>>     -OVN_CLEANUP([hv])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>>     LS "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>>>     -# connected to it. R2 has alice (172.16.1.0/24
>>>>     <http://172.16.1.0/24>) and R3 has bob (10.32.1.0/24
>>>>     <http://10.32.1.0/24>)
>>>>     -# connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lr-add R2
>>>>     -ovn-nbctl lr-add R3
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add bob
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect bob to R3
>>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
>>>>     <http://10.32.1.1/24>
>>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>>     -    type=router options:router-port=bob
>>>>     addresses=\"00:00:03:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Connect R3 to join
>>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>>     <http://20.0.0.3/24>
>>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>>> r3-join \
>>>>     -    type=router options:router-port=R3_join
>>>>     addresses='"00:00:04:01:02:05"'
>>>>     -
>>>>     -#install static routes
>>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -ovn-nbctl lr-route-add R1 10.32.1.0/24 <http://10.32.1.0/24> 
>>>> 20.0.0.3
>>>>     -
>>>>     -ovn-nbctl lr-route-add R2 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     20.0.0.1
>>>>     -ovn-nbctl lr-route-add R2 10.32.1.0/24 <http://10.32.1.0/24> 
>>>> 20.0.0.3
>>>>     -
>>>>     -ovn-nbctl lr-route-add R3 192.168.1.0/24 <http://192.168.1.0/24>
>>>>     20.0.0.1
>>>>     -ovn-nbctl lr-route-add R3 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Create logical port bob1 in bob
>>>>     -ovn-nbctl lsp-add bob bob1 \
>>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=bob1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>>     -
>>>>     -# Send ip packets between foo1 and bob1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -echo "----------------------------"
>>>>     -
>>>>     -# Packet to Expect at bob1
>>>>     -src_mac="000003010203"
>>>>     -dst_mac="f00000010205"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 10 32 1 2`
>>>>     -echo
>>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Packet to Expect at alice1
>>>>     -src_mac="000002010203"
>>>>     -dst_mac="f00000010204"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>>     -echo
>>>> "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>>> 10.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 
>>>> 20.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>>     10.0.0.6 20.0.0.4"
>>>>     -
>>>>     -ovn-nbctl ls-add ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 
>>>> 40.0.0.4"
>>>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03
>>>>     30.0.0.6 40.0.0.4"
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
>>>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 
>>>> 30.0.0.7"
>>>>     -
>>>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>>>     <http://10.0.0.0/24> \
>>>>     -options="\"server_id\"=\"10.0.0.1\"
>>>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
>>>>     -
>>>>     -d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24
>>>>     <http://30.0.0.0/24> \
>>>>     -options="\"server_id\"=\"30.0.0.1\"
>>>>     \"server_mac\"=\"ff:10:00:00:00:02\" \
>>>>     -\"lease_time\"=\"3600\"")"
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>>     -    ofport-request=3
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>>>     -    ofport-request=4
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -sleep 2
>>>>     -
>>>>     -as hv1 ovs-vsctl show
>>>>     -
>>>>     -# This shell function sends a DHCP request packet
>>>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
>>>>     -test_dhcp() {
>>>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5
>>>>     request_ip=$6 use_ip=$7
>>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>>     -    if test $use_ip != 0; then
>>>>     -        src_ip=$1
>>>>     -        dst_ip=$2
>>>>     -        shift; shift;
>>>>     -    else
>>>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>>>     -    fi
>>>>     -    if test $request_ip != 0; then
>>>>     -        ip_len=0120
>>>>     -        udp_len=010b
>>>>     -    else
>>>>     -        ip_len=011a
>>>>     -        udp_len=0106
>>>>     -    fi
>>>>     -    local
>>>> request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip} 
>>>>
>>>>     -    # udp header and dhcp header
>>>>     -    request=${request}00440043${udp_len}0000
>>>>     -
>>>> request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac} 
>>>>
>>>>     -    # client hardware padding
>>>>     -    request=${request}00000000000000000000
>>>>     -    # server hostname
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # boot file name
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # dhcp magic cookie
>>>>     -    request=${request}63825363
>>>>     -    # dhcp message type
>>>>     -    request=${request}3501${dhcp_type}
>>>>     -    # dhcp unknown option
>>>>     -    request=${request}d70701020304050607
>>>>     -    # dhcp pad option
>>>>     -    request=${request}00
>>>>     -    if test $request_ip != 0; then
>>>>     -        # dhcp requested ip
>>>>     -        request=${request}3204${request_ip}
>>>>     -    fi
>>>>     -    # dhcp end option
>>>>     -    request=${request}ff
>>>>     -
>>>>     -    for port in $inport "$@"; do
>>>>     -        : >> $port.expected
>>>>     -    done
>>>>     -    if test $offer_ip != 0; then
>>>>     -        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3
>>>>     expected_dhcp_opts=$4
>>>>     -        # total IP length will be the IP length of the request 
>>>> packet
>>>>     -        # (which is 272 in our case) + 8 (padding bytes) +
>>>>     (expected_dhcp_opts / 2)
>>>>     -        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>>>     -        udp_len=`expr $ip_len - 20`
>>>>     -        ip_len=$(printf "%x" $ip_len)
>>>>     -        udp_len=$(printf "%x" $udp_len)
>>>>     -        # $ip_len var will be in 3 digits i.e 134. So adding a
>>>>     '0' before $ip_len
>>>>     -        local
>>>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>>>
>>>>     -        # udp header and dhcp header.
>>>>     -        # $udp_len var will be in 3 digits. So adding a '0'
>>>>     before $udp_len
>>>>     -
>>>> reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
>>>>     -        # your ip address; 0 for NAK
>>>>     -        if test $dhcp_reply_type = 06; then
>>>>     -            reply=${reply}00000000
>>>>     -        else
>>>>     -            reply=${reply}${offer_ip}
>>>>     -        fi
>>>>     -        # next server ip address, relay agent ip address, client
>>>>     mac address
>>>>     -        reply=${reply}0000000000000000${src_mac}
>>>>     -        # client hardware padding
>>>>     -        reply=${reply}00000000000000000000
>>>>     -        # server hostname
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -        # boot file name
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -        # dhcp magic cookie
>>>>     -        reply=${reply}63825363
>>>>     -
>>>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>>>
>>>>     -        echo $reply >> $inport.expected
>>>>     -    else
>>>>     -        for outport; do
>>>>     -            echo $request >> $outport.expected
>>>>     -        done
>>>>     -    fi
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport 
>>>> $request
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Send DHCPDISCOVER.
>>>>     -offer_ip=`ip_to_hex 10 0 0 4`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -request_ip=0
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0
>>>>     ff1000000001 $server_ip 02 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap > 1.packets
>>>>     -cat 1.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 1.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>>     to receive
>>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>>     easier to test.
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the
>>>>     offered IP
>>>>     -# address in the Requested IP Address option.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -request_ip=$offer_ip
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>>>     ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a
>>>>     mismatched IP in
>>>>     -# the Requested IP Address option, expect a DHCPNAK.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -request_ip=`ip_to_hex 10 0 0 7`
>>>>     -expected_dhcp_opts=""
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0
>>>>     ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 3.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by
>>>>     ovn-controller
>>>>     -# but should be resumed without the reply.
>>>>     -# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet
>>>>     twice,
>>>>     -# one from ovn-controller and the other from "ovs-ofctl resume."
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -offer_ip=0
>>>>     -request_ip=0
>>>>     -test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
>>>>     -
>>>>     -# NXT_RESUMEs should be 4.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# vif1-tx.pcap should have received the DHCPv4 (invalid) request
>>>>     packet
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4
>>>>     options defined.
>>>>     -# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet
>>>>     once.
>>>>     -
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
>>>>     -
>>>>     -# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not
>>>>     defined for
>>>>     -# this lport.
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
>>>>     -
>>>>     -# NXT_RESUMEs should be 4.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
>>>>     -#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
>>>>     -
>>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>>>     set to 10.0.0.6
>>>>     -# and ip4.dst set to 10.0.0.1.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=$offer_ip
>>>>     -request_ip=0
>>>>     -src_ip=$offer_ip
>>>>     -dst_ip=$server_ip
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 5.
>>>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src
>>>>     set to 10.0.0.6
>>>>     -# and ip4.dst set to 255.255.255.255.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=$offer_ip
>>>>     -request_ip=0
>>>>     -src_ip=$offer_ip
>>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>>     $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 6.
>>>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state with a
>>>>     mismatched IP in the
>>>>     -# ciaddr, expect a DHCPNAK.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=`ip_to_hex 10 0 0 7`
>>>>     -request_ip=0
>>>>     -src_ip=$offer_ip
>>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>>     -expected_dhcp_opts=""
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 7.
>>>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST in the RENEWING/REBINDING state without a
>>>>     specifyied ciaddr,
>>>>     -# expect a DHCPNAK.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -request_ip=0
>>>>     -src_ip=$offer_ip
>>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>>     -expected_dhcp_opts=""
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1
>>>>     $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 8.
>>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set
>>>>     to 10.0.0.4.
>>>>     -# The packet should not be received by ovn-controller.
>>>>     -ciaddr=`ip_to_hex 0 0 0 0`
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 4`
>>>>     -test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
>>>>     -
>>>>     -# NXT_RESUMEs should be 8.
>>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# vif1-tx.pcap should have received the DHCPv4 request packet
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>>>     10.0.0.4 ae70::4"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 
>>>> ae70::5"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp3 \
>>>>     --- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 
>>>> ae70::22"
>>>>     -
>>>>     -d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
>>>>     -
>>>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>>     -options="\"dhcpv6_stateless\"=\"true\"
>>>>     \"server_id\"=\"00:00:00:10:00:01\"")"
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
>>>>     -
>>>>     -ovn-nbctl ls-add ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
>>>>     -ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 
>>>> be70::3"
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp2 \
>>>>     --- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
>>>>     -ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 
>>>> be70::4"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>>     -    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>>     -    ofport-request=3
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif4 -- \
>>>>     -    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
>>>>     -    options:tx_pcap=hv1/vif4-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif4-rx.pcap \
>>>>     -    ofport-request=4
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif5 -- \
>>>>     -    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
>>>>     -    options:tx_pcap=hv1/vif5-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif5-rx.pcap \
>>>>     -    ofport-request=5
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -sleep 2
>>>>     -
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -# This shell function sends a DHCPv6 request packet
>>>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>>>     OUTPORT...
>>>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>>>     DHCPv6
>>>>     -# packet should be received twice (one from ovn-controller and
>>>>     the other
>>>>     -# from the "ovs-ofctl monitor br-int resume"
>>>>     -test_dhcpv6() {
>>>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>>>     -    if test $msg_code != 0b; then
>>>>     -        req_len=2a
>>>>     -    else
>>>>     -        req_len=1a
>>>>     -    fi
>>>>     -    local
>>>> request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
>>>>     -    # dst ip ff02::1:2
>>>>     -    request=${request}ff020000000000000000000000010002
>>>>     -    # udp header and dhcpv6 header
>>>>     - request=${request}0222022300${req_len}ffff${msg_code}010203
>>>>     -    # Client identifier
>>>>     -    request=${request}0001000a00030001${src_mac}
>>>>     -    # Add IA-NA (Identity Association for Non Temporary Address)
>>>>     if msg_code
>>>>     -    # is not 11 (information request packet)
>>>>     -    if test $msg_code != 0b; then
>>>>     - request=${request}0003000c0102030400000e1000001518
>>>>     -    fi
>>>>     -    shift; shift; shift; shift; shift;
>>>>     -    if test $offer_ip != 0; then
>>>>     -        local server_mac=000000100001
>>>>     -        local server_lla=fe80000000000000020000fffe100001
>>>>     -        local reply_code=07
>>>>     -        if test $msg_code = 01; then
>>>>     -            reply_code=02
>>>>     -        fi
>>>>     -        local msg_len=54
>>>>     -        if test $offer_ip = 1; then
>>>>     -            msg_len=28
>>>>     -        fi
>>>>     -        local
>>>> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla} 
>>>>
>>>>     -        # udp header and dhcpv6 header
>>>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>>>     -        # Client identifier
>>>>     -        reply=${reply}0001000a00030001${src_mac}
>>>>     -        # IA-NA
>>>>     -        if test $offer_ip != 1; then
>>>>     -
>>>> reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff 
>>>>
>>>>     -        fi
>>>>     -        # Server identifier
>>>>     -        reply=${reply}0002000a00030001${server_mac}
>>>>     -        echo $reply | trim_zeros >> $inport.expected
>>>>     -    else
>>>>     -        for outport; do
>>>>     -            echo $request | trim_zeros >> $outport.expected
>>>>     -        done
>>>>     -    fi
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport 
>>>> $request
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -src_mac=f00000000001
>>>>     -src_lla=fe80000000000000f20000fffe000001
>>>>     -offer_ip=ae700000000000000000000000000004
>>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>>     -
>>>>     -# NXT_RESUMEs should be 1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>>>     -# cat 1.expected | trim_zeros > expout
>>>>     -cat 1.expected | cut -c -120 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
>>>>     -# Skipping the UDP checksum
>>>>     -cat 1.expected | cut -c 125- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
>>>>     -
>>>>     -rm  1.expected
>>>>     -
>>>>     -# Send invalid packet on ls1-lp2. ovn-controller should resume
>>>>     the packet
>>>>     -# without any modifications and the packet should be received by
>>>>     ls1-lp1.
>>>>     -# ls1-lp1 will receive the packet twice, one from the
>>>>     ovn-controller after the
>>>>     -# resume and the other from ovs-ofctl monitor resume.
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -
>>>>     -src_mac=f00000000002
>>>>     -src_lla=fe80000000000000f20000fffe000002
>>>>     -offer_ip=ae700000000000000000000000000005
>>>>     -# Set invalid msg_type
>>>>     -
>>>>     -test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
>>>>     -
>>>>     -# NXT_RESUMEs should be 2.
>>>> ��   -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# vif2-tx.pcap should not have received the DHCPv6 reply packet
>>>>     -rm 2.packets
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap | trim_zeros > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>>     -
>>>>     -# vif1-tx.pcap should have received the DHCPv6 (invalid) request
>>>>     packet
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap | trim_zeros > 1.packets
>>>>     -cat 1.expected > expout
>>>>     -AT_CHECK([cat 1.packets], [0], [expout])
>>>>     -
>>>>     -# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on
>>>>     this port.
>>>>     -# There should be no DHCPv6 reply from ovn-controller and the
>>>>     request packet
>>>>     -# should be received by ls2-lp2.
>>>>     -
>>>>     -src_mac=f00000000003
>>>>     -src_lla=fe80000000000000f20000fffe000003
>>>>     -test_dhcpv6 3 $src_mac $src_lla 01 0 4
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 only.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# vif3-tx.pcap should not have received the DHCPv6 reply packet
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif3-tx.pcap | trim_zeros > 3.packets
>>>>     -AT_CHECK([cat 3.packets], [0], [])
>>>>     -
>>>>     -# vif4-tx.pcap should have received the DHCPv6 request packet
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif4-tx.pcap | trim_zeros > 4.packets
>>>>     -cat 4.expected > expout
>>>>     -AT_CHECK([cat 4.packets], [0], [expout])
>>>>     -
>>>>     -# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless
>>>>     mode for this port.
>>>>     -# The DHCPv6 reply shouldn't contain offer_ip.
>>>>     -src_mac=f00000000022
>>>>     -src_lla=fe80000000000000f20000fffe000022
>>>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>>>     -test_dhcpv6 5 $src_mac $src_lla 01 1 5
>>>>     -
>>>>     -# NXT_RESUMEs should be 3.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif5-tx.pcap | trim_zeros > 5.packets
>>>>     -# Skipping the UDP checksum
>>>>     -cat 5.expected | cut -c 1-120,125- > expout
>>>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>>>     -
>>>>     -# Send DHCPv6 information request (code 11) on ls1-lp3. The
>>>>     DHCPv6 reply
>>>>     -# shouldn't contain offer_ip
>>>>     -src_mac=f00000000022
>>>>     -src_lla=fe80000000000000f20000fffe000022
>>>>     -reset_pcap_file hv1-vif5 hv1/vif5
>>>>     -rm -f 5.expected
>>>>     -test_dhcpv6 5 $src_mac $src_lla 0b 1 5
>>>>     -
>>>>     -# NXT_RESUMEs should be 4.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif5-tx.pcap |
>>>>     -trim_zeros > 5.packets
>>>>     -# Skipping the UDP checksum
>>>>     -cat 5.expected | cut -c 1-120,125- > expout
>>>>     -AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>>> "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>)
>>>>     -# connected to it. R2 has alice (172.16.1.0/24
>>>>     <http://172.16.1.0/24>) connected to it.
>>>>     -# R2 is a gateway router.
>>>>     -
>>>>     -
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -
>>>>     -#install static routes
>>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>>     -ip_prefix=172.16.1.0/24 <http://172.16.1.0/24> nexthop=20.0.0.2
>>>>     -- add Logical_Router \
>>>>     -R1 static_routes @lrt
>>>>     -
>>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>>>     -- add Logical_Router \
>>>>     -R2 static_routes @lrt
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 2
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list chassis
>>>>     -ovn-sbctl list encap
>>>>     -echo "---------------------"
>>>>     -
>>>>     -# Packet to Expect at alice1
>>>>     -src_mac="000002010203"
>>>>     -dst_mac="f00000010204"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>>     -
>>>>     -echo "------ hv1 dump after packet 1 ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump after packet 1 ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -echo "----------------------------"
>>>>     -
>>>>     -echo $expected > expected
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Delete the router and re-create it. Things should work as 
>>>> before.
>>>>     -ovn-nbctl  lr-del R2
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -
>>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>>     -ip_prefix=192.168.1.0/24 <http://192.168.1.0/24> nexthop=20.0.0.1
>>>>     -- add Logical_Router \
>>>>     -R2 static_routes @lrt
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -sleep 1
>>>>     -
>>>>     -# Send the packet again.
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -echo "------ hv1 dump after packet 2 ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump after packet 2 ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -echo "----------------------------"
>>>>     -
>>>>     -echo $expected >> expected
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
>>>>     -AT_KEYWORDS([router-icmp-reply])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>>     <http://191.168.1.0/24>) connected to it,
>>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>>     -    type=router options:router-port=ls1
>>>>     addresses=\"00:00:00:01:02:f1\"
>>>>     -
>>>>     -# Connect ls2 to R1
>>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>>     -    type=router options:router-port=ls2
>>>>     addresses=\"00:00:00:01:02:f2\"
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port ls2-lp1 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -for i in 1 2; do
>>>>     -    : > vif$i.expected
>>>>     -done
>>>>     -# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>>     IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an 
>>>> ICMPv4
>>>>     -# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
>>>>     -# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and 
>>>> EXP_ICMP_CHKSUM are
>>>>     -# provided, then it should be the ip and icmp checksums of the 
>>>> packet
>>>>     -# responded; otherwise, no reply is expected.
>>>>     -# In the absence of an ip checksum calculation helpers, this 
>>>> relies
>>>>     -# on the caller to provide the checksums for the ip and icmp 
>>>> headers.
>>>>     -# XXX This should be more systematic.
>>>>     -#
>>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>>     -# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
>>>>     -# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
>>>>     -test_ipv4_icmp_request() {
>>>>     -    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5
>>>>     ip_chksum=$6 icmp_chksum=$7
>>>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>>>     -    shift; shift; shift; shift; shift; shift; shift
>>>>     -    shift; shift
>>>>     -
>>>>     -    # Use ttl to exercise section 4.2.2.9 of RFC1812
>>>>     -    local ip_ttl=01
>>>>     -    local icmp_id=5fbf
>>>>     -    local icmp_seq=0001
>>>>     -    local icmp_data=$(seq 1 56 | xargs printf "%02x")
>>>>     -    local icmp_type_code_request=0800
>>>>     -    local
>>>> icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>>>
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload} 
>>>>
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    if test X$exp_icmp_chksum != X; then
>>>>     -        # Expect to receive the reply, if any. In same port where
>>>>     packet was sent.
>>>>     -        # Note: src and dst fields are expected to be reversed.
>>>>     -        local icmp_type_code_response=0000
>>>>     -        local reply_icmp_ttl=fe
>>>>     -        local
>>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data} 
>>>>
>>>>     -        local
>>>> reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>>>
>>>>     -        echo $reply >> vif$inport.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -# Send ping packet to router's ip addresses, from each of the 2
>>>>     logical ports.
>>>>     -rtr_l1_ip=$(ip_to_hex 192 168 1 1)
>>>>     -rtr_l2_ip=$(ip_to_hex 172 16 1 1)
>>>>     -l1_ip=$(ip_to_hex 192 168 1 2)
>>>>     -l2_ip=$(ip_to_hex 172 16 1 2)
>>>>     -
>>>>     -# Ping router ip address that is on same subnet as the logical 
>>>> port
>>>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>>>     -
>>>>     -# Ping router ip address that is on the other side of the logical
>>>>     ports
>>>>     -test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip
>>>>     $rtr_l2_ip 0000 8510 02ff 8d10
>>>>     -test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip
>>>>     $rtr_l1_ip 0000 8510 02ff 8d10
>>>>     -
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list logical_flow
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for inport in 1 2; do
>>>>     -    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap],
>>>>     [vif$inport.expected])
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS,
>>>>     1 LR])
>>>>     -AT_KEYWORDS([policy-based-routing])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>>     <http://191.168.1.0/24>) connected to it,
>>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -ovn-nbctl ls-add ls3
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>>     -    type=router options:router-port=ls1
>>>>     addresses=\"00:00:00:01:02:f1\"
>>>>     -
>>>>     -# Connect ls2 to R1
>>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>>     -    type=router options:router-port=ls2
>>>>     addresses=\"00:00:00:01:02:f2\"
>>>>     -
>>>>     -# Connect ls3 to R1
>>>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
>>>>     <http://20.20.1.1/24>
>>>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>>>     -    type=router options:router-port=ls3
>>>>     addresses=\"00:00:00:01:02:f3\"
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port ls2-lp1 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Create logical port ls3-lp1 in ls3
>>>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
>>>>     -
>>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add pbr-hv
>>>>     -as pbr-hv
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ls1_ro_mac=00:00:00:01:02:f1
>>>>     -ls1_ro_ip=192.168.1.1
>>>>     -
>>>>     -ls2_ro_mac=00:00:00:01:02:f2
>>>>     -ls2_ro_ip=172.16.1.1
>>>>     -
>>>>     -ls3_ro_mac=00:00:00:01:02:f3
>>>>     -
>>>>     -ls1_p1_mac=00:00:00:01:02:03
>>>>     -ls1_p1_ip=192.168.1.2
>>>>     -
>>>>     -ls2_p1_mac=00:00:00:01:02:04
>>>>     -ls2_p1_ip=172.16.1.2
>>>>     -
>>>>     -ls3_p1_mac=00:00:00:01:02:05
>>>>     -
>>>>     -# Create a drop policy
>>>>     -ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24
>>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>>     <http://172.16.1.0/24>" drop
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>>>     "192.168.1.0" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>>     ip4.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Check if packet hit the drop policy
>>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24> actions=drop" | \
>>>>     -    grep "priority=10" | \
>>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Expected to drop the packet.
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>>>     -rcvd_packet=`cat vif2.packets`
>>>>     -AT_FAIL_IF([rcvd_packet = ""])
>>>>     -
>>>>     -# Override drop policy with allow
>>>>     -ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24
>>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>>     <http://172.16.1.0/24>" allow
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep
>>>>     "192.168.1.0" | wc -l], [0], [dnl
>>>>     -2
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>>     ip4.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Check if packet hit the allow policy
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>>     -    grep "192.168.1.0" | \
>>>>     -    grep "priority=20" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>>>     ip4.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -# Override allow policy with reroute
>>>>     -ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24
>>>>     <http://192.168.1.0/24> && ip4.dst==172.16.1.0/24
>>>>     <http://172.16.1.0/24>" reroute 20.20.1.2
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>>     -    grep "192.168.1.0" | \
>>>>     -    grep "priority=30" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip &&
>>>>     ip4.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -echo "southbound flows"
>>>>     -
>>>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>>>     -echo "ovs flows"
>>>>     -ovs-ofctl dump-flows br-int
>>>>     -# Check if packet hit the allow policy
>>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>>     -    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24
>>>>     <http://192.168.1.0/24,nw_dst=172.16.1.0/24>" | \
>>>>     -    grep "priority=30" | \
>>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -echo "packet hit reroute policy"
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>>>     -       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip &&
>>>>     ip4.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>>>     -
>>>>     -OVN_CLEANUP([pbr-hv])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1
>>>>     lport/LS, 1 LR])
>>>>     -AT_KEYWORDS([policy-based-routing])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR - R1 has switch ls1 (191.168.1.0/24
>>>>     <http://191.168.1.0/24>) connected to it,
>>>>     -# and has switch ls2 (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -ovn-nbctl ls-add ls3
>>>>     -
>>>>     -# Connect ls1 to R1
>>>>     -ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
>>>>     -ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
>>>>     -    type=router options:router-port=ls1
>>>>     addresses=\"00:00:00:01:02:f1\"
>>>>     -
>>>>     -# Connect ls2 to R1
>>>>     -ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
>>>>     -ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
>>>>     -    type=router options:router-port=ls2
>>>>     addresses=\"00:00:00:01:02:f2\"
>>>>     -
>>>>     -# Connect ls3 to R1
>>>>     -ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
>>>>     -ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
>>>>     -    type=router options:router-port=ls3
>>>>     addresses=\"00:00:00:01:02:f3\"
>>>>     -
>>>>     -# Create logical port ls1-lp1 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
>>>>     -
>>>>     -# Create logical port ls2-lp1 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2-lp1 \
>>>>     --- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
>>>>     -
>>>>     -# Create logical port ls3-lp1 in ls3
>>>>     -ovn-nbctl lsp-add ls3 ls3-lp1 \
>>>>     --- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
>>>>     -
>>>>     -# Create one hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add pbr-hv
>>>>     -as pbr-hv
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif1 -- \
>>>>     -    set interface vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif2 -- \
>>>>     -    set interface vif2 external-ids:iface-id=ls2-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int vif3 -- \
>>>>     -    set interface vif3 external-ids:iface-id=ls3-lp1 \
>>>>     -    options:tx_pcap=pbr-hv/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ls1_ro_mac=00:00:00:01:02:f1
>>>>     -ls1_ro_ip=2001::1
>>>>     -
>>>>     -ls2_ro_mac=00:00:00:01:02:f2
>>>>     -ls2_ro_ip=2002::1
>>>>     -
>>>>     -ls3_ro_mac=00:00:00:01:02:f3
>>>>     -
>>>>     -ls1_p1_mac=00:00:00:01:02:03
>>>>     -ls1_p1_ip=2001::2
>>>>     -
>>>>     -ls2_p1_mac=00:00:00:01:02:04
>>>>     -ls2_p1_ip=2002::2
>>>>     -
>>>>     -ls3_p1_mac=00:00:00:01:02:05
>>>>     -
>>>>     -# Create a drop policy
>>>>     -ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 &&
>>>>     ip6.dst==2002::/64" drop
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>>>     | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>>     ip6.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Check if packet hit the drop policy
>>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
>>>>     -    grep "priority=10" | \
>>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Expected to drop the packet.
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     pbr-hv/vif2-tx.pcap > vif2.packets
>>>>     -rcvd_packet=`cat vif2.packets`
>>>>     -AT_FAIL_IF([rcvd_packet = ""])
>>>>     -
>>>>     -# Override drop policy with allow
>>>>     -ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 &&
>>>>     ip6.dst==2002::/64" allow
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001"
>>>>     | wc -l], [0], [dnl
>>>>     -2
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>>     ip6.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Check if packet hit the allow policy
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>>     -    grep "2001" | \
>>>>     -    grep "priority=20" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
>>>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>>>     ip6.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -# Override allow policy with reroute
>>>>     -ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 &&
>>>>     ip6.dst==2002::/64" reroute 2003::2
>>>>     -
>>>>     -# Check logical flow
>>>>     -AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
>>>>     -    grep "2001" | \
>>>>     -    grep "priority=30" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -# Send packet.
>>>>     -packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac &&
>>>>     eth.dst==$ls1_ro_mac &&
>>>>     -       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip &&
>>>>     ip6.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -echo "southbound flows"
>>>>     -
>>>>     -ovn-sbctl dump-flows | grep lr_in_policy
>>>>     -echo "ovs flows"
>>>>     -ovs-ofctl dump-flows br-int
>>>>     -# Check if packet hit the allow policy
>>>>     -AT_CHECK([ovs-ofctl dump-flows br-int | \
>>>>     -    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
>>>>     -    grep "priority=30" | \
>>>>     -    grep "n_packets=1" | wc -l], [0], [dnl
>>>>     -1
>>>>     -])
>>>>     -echo "packet hit reroute policy"
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
>>>>     -       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip &&
>>>>     ip6.dst==$ls2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > 3.expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
>>>>     -
>>>>     -OVN_CLEANUP([pbr-hv])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 1 hypervisor, 1 port
>>>>     -# make sure that the port state is properly set to up and back 
>>>> down
>>>>     -# when created and deleted.
>>>>     -AT_SETUP([ovn -- port state up and down])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl lsp-add ls1 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1 ovs-vsctl add-br br-phys
>>>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>>     -
>>>>     -as hv1 ovs-vsctl del-port br-int vif1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# 1 hypervisor, 1 port
>>>>     -# make sure that the OF rules created to support a datapath are
>>>>     added/cleared
>>>>     -# when logical switch is created and removed.
>>>>     -AT_SETUP([ovn -- datapath rules added/removed])
>>>>     -AT_KEYWORDS([cleanup])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1 ovs-vsctl add-br br-phys
>>>>     -as hv1 ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -# This shell function checks if OF rules in br-int have clauses
>>>>     -# related to OVN datapaths. The caller determines if it should 
>>>> find
>>>>     -# a match in the output, or not.
>>>>     -#
>>>>     -# EXPECT_DATAPATH param determines whether flows that refer to
>>>>     -#                 datapath to should be present or not. 0 means
>>>>     -#                 they should not be.
>>>>     -# STAGE_INFO param is a simple string to help identify the stage
>>>>     -#            in the test when this function was invoked.
>>>>     -test_datapath_in_of_rules() {
>>>>     -    local expect_datapath=$1 stage_info=$2
>>>>     -    echo "------ ovn-nbctl show ${stage_info} ------"
>>>>     -    ovn-nbctl show
>>>>     -    echo "------ ovn-sbctl show ${stage_info} ------"
>>>>     -    ovn-sbctl show
>>>>     -    echo "------ OF rules ${stage_info} ------"
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
>>>>     -    # if there is a datapath mentioned in the output, check 
>>>> for the
>>>>     -    # magic keyword that represents one, based on the exit 
>>>> status of
>>>>     -    # a quiet grep
>>>>     -    if test $expect_datapath != 0; then
>>>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [0], 
>>>> [ignore-nolog])
>>>>     -    else
>>>>     -       AT_CHECK([grep -q -i 'metadata=' stdout], [1], 
>>>> [ignore-nolog])
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -test_datapath_in_of_rules 0 "before ls+port create"
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl lsp-add ls1 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 unknown
>>>>     -
>>>>     -as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>>     -
>>>>     -test_datapath_in_of_rules 1 "after port is bound"
>>>>     -
>>>>     -as hv1 ovs-vsctl del-port br-int vif1
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
>>>>     -
>>>>     -ovn-nbctl lsp-set-addresses lp1
>>>>     -ovn-nbctl lsp-del lp1
>>>>     -ovn-nbctl ls-del ls1
>>>>     -
>>>>     -# wait for earlier changes to take effect
>>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>>     -
>>>>     -# ensure OF rules are no longer present. There used to be a 
>>>> bug here.
>>>>     -test_datapath_in_of_rules 0 "after lport+ls removal"
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- nd_na ])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -#TODO: since patch port for IPv6 logical router port is not ready
>>>>     not,
>>>>     -#  so we are not going to test vifs on different lswitches 
>>>> cases. Try
>>>>     -#  to update for that once relevant stuff implemented.
>>>>     -
>>>>     -# In this test cases we create 1 lswitch, it has 2 VIF ports 
>>>> attached
>>>>     -# with. NS packet we test, from one VIF for another VIF, will be
>>>>     replied
>>>>     -# by local ovn-controller, but not by target VIF.
>>>>     -
>>>>     -# Create hypervisors and logical switch lsw0.
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
>>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap
>>>>     options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
>>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3
>>>>     fd81:ce49:a948:0:f816:3eff:fe94:598"
>>>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98
>>>>     192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
>>>>     -
>>>>     -# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
>>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>>     external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap
>>>>     options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
>>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4
>>>>     fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae
>>>>     192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
>>>>     -
>>>>     -# Add ACL rule for ICMPv6 on lsw0
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  
>>>> allow-related
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>>>     icmp6'  allow-related
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>>>     icmp6'  allow-related
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv1${1%?}
>>>>     -}
>>>>     -for i in 1 2; do
>>>>     -    : > $i.expected
>>>>     -done
>>>>     -
>>>>     -# Complete Neighbor Solicitation packet and Neighbor
>>>>     Advertisement packet
>>>>     -# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
>>>>     -# vif2 will not receive NS packet, since ovn-controller will
>>>>     reply for it.
>>>> -ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598 
>>>>
>>>> -na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae 
>>>>
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
>>>>     -echo $na_packet >> 1.expected
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 show br-int
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- address sets modification/removal smoke test])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -row=`ovn-nbctl create Address_Set name=set1 
>>>> addresses=\"1.1.1.1\"`
>>>>     -ovn-nbctl set Address_Set $row name=set1
>>>>     addresses=\"1.1.1.1,1.1.1.2\"
>>>>     -ovn-nbctl destroy Address_Set $row
>>>>     -
>>>>     -sleep 1
>>>>     -
>>>>     -# A bug previously existed in the address set support code
>>>>     -# that caused ovn-controller to crash after an address set
>>>>     -# was updated and then removed.  This test case ensures
>>>>     -# that ovn-controller is at least still running after
>>>>     -# creating, updating, and deleting an address set.
>>>>     -AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ipam])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Add a port to a switch that does not have a subnet set, then
>>>>     set the
>>>>     -# subnet which should result in an address being allocated for
>>>>     the port.
>>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>>>     subnet=192.168.1.0/24
>>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>>     get Logical-Switch-Port p0 dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -# Add 9 more ports to sw0, addresses should all be unique.
>>>>     -for n in `seq 1 9`; do
>>>>     -    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses
>>>>     "p$n" dynamic
>>>>     -done
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p1
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:04 192.168.1.3"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p2
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:05 192.168.1.4"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p3
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:06 192.168.1.5"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p4
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:07 192.168.1.6"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p5
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:08 192.168.1.7"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p6
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:09 192.168.1.8"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p7
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:0a 192.168.1.9"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p8
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:0b 192.168.1.10"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p9
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:0c 192.168.1.11"
>>>>     -])
>>>>     -
>>>>     -# Trying similar tests with a second switch. MAC addresses should
>>>>     be unique
>>>>     -# across both switches but IP's only need to be unique within the
>>>>     same switch.
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw1 other_config
>>>>     subnet=192.168.1.0/24
>>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>>     get Logical-Switch-Port p10 dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:0d 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -for n in `seq 11 19`; do
>>>>     -    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses
>>>>     "p$n" dynamic
>>>>     -done
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p11
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:0e 192.168.1.3"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p12
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:0f 192.168.1.4"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p13
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:10 192.168.1.5"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p14
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:11 192.168.1.6"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p15
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:12 192.168.1.7"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p16
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:13 192.168.1.8"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p17
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:14 192.168.1.9"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p18
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:15 192.168.1.10"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p19
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:16 192.168.1.11"
>>>>     -])
>>>>     -
>>>>     -# Change a port's address to test for multiple ip's for a single
>>>>     address entry
>>>>     -# and addresses set by the user.
>>>>     -ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2
>>>>     192.168.1.12 192.168.1.14"
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p20
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:18 192.168.1.13"
>>>>     -])
>>>>     -
>>>>     -# Test for logical router port address management.
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
>>>>     -network="192.168.1.1/24 <http://192.168.1.1/24>"
>>>>     mac=\"0a:00:00:a8:01:19\" \
>>>>     --- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
>>>>     --- set Logical_Switch_Port rp-sw0 type=router 
>>>> options:router-port=sw0
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p21
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:1a 192.168.1.15"
>>>>     -])
>>>>     -
>>>>     -# Test for address reuse after logical port is deleted.
>>>>     -ovn-nbctl lsp-del p0
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p23
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:03 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -# Test for multiple addresses to one logical port.
>>>>     -ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
>>>>     -"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p26
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:17 192.168.1.16"
>>>>     -])
>>>>     -
>>>>     -# Test for exhausting subnet address space.
>>>>     -ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config
>>>>     subnet=172.16.1.0/30
>>>>     -ovn-nbctl <http://172.16.1.0/30-ovn-nbctl> --wait=sb lsp-add sw2
>>>>     p27 -- lsp-set-addresses p27 dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p27
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:10:01:03 172.16.1.2"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p28
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:00:00:01"
>>>>     -])
>>>>     -
>>>>     -# Test that address management does not add duplicate MAC for
>>>>     lsp/lrp peers.
>>>>     -ovn-nbctl create Logical_Router name=R2
>>>>     -ovn-nbctl ls-add sw3
>>>>     -ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
>>>>     -"0a:00:00:a8:01:18"
>>>>     -ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
>>>>     -network="192.168.2.1/24 <http://192.168.2.1/24>"
>>>>     mac=\"0a:00:00:a8:01:18\" \
>>>>     --- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
>>>>     --- set Logical_Switch_Port rp-sw3 type=router 
>>>> options:router-port=sw3
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 
>>>> dynamic
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p30
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:1d 192.168.1.17"
>>>>     -])
>>>>     -
>>>>     -# Test static MAC address with dynamically allocated IP
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
>>>>     -"fe:dc:ba:98:76:54 dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>>     dynamic_addresses], [0],
>>>>     -     ["fe:dc:ba:98:76:54 192.168.1.18"
>>>>     -])
>>>>     -
>>>>     -# Update the static MAC address with dynamically allocated IP and
>>>>     check
>>>>     -# if the MAC address is updated in
>>>>     'Logical_Switch_Port.dynamic_adddresses'
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 
>>>> dynamic"
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>>     dynamic_addresses], [0],
>>>>     -     ["fe:dc:ba:98:76:55 192.168.1.18"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:1e 192.168.1.18"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 
>>>> dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p31
>>>>     dynamic_addresses], [0],
>>>>     -     ["fe:dc:ba:98:76:56 192.168.1.18"
>>>>     -])
>>>>     -
>>>>     -
>>>>     -# Test the exclude_ips from the IPAM list
>>>>     -ovn-nbctl --wait=sb set logical_switch sw0 \
>>>>     -other_config:exclude_ips="192.168.1.19 192.168.1.21
>>>>     192.168.1.23..192.168.1.50"
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
>>>>     -"dynamic"
>>>>     -# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p32
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:1e 192.168.1.20"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
>>>>     -"dynamic"
>>>>     -# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p33
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:1f 192.168.1.22"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
>>>>     -"dynamic"
>>>>     -# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is
>>>>     excluded.
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p34
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:34 192.168.1.51"
>>>>     -])
>>>>     -
>>>>     -# Now clear the exclude_ips list. 192.168.1.19 should be 
>>>> assigned.
>>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>>     other_config:exclude_ips="invalid"
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
>>>>     -"dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p35
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:20 192.168.1.19"
>>>>     -])
>>>>     -
>>>>     -# Set invalid data in exclude_ips list. It should be ignored.
>>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>>     other_config:exclude_ips="182.168.1.30"
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
>>>>     -"dynamic"
>>>>     -# 192.168.1.21 should be assigned as that's the next free one.
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:21 192.168.1.21"
>>>>     -])
>>>>     -
>>>>     -# Clear the dynamic addresses assignment request.
>>>>     -ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p36
>>>>     dynamic_addresses], [0],
>>>>     -         [[[]]
>>>>     -])
>>>>     -
>>>>     -# Set IPv6 prefix
>>>>     -ovn-nbctl --wait=sb set Logical-switch sw0
>>>>     other_config:ipv6_prefix="aef0::"
>>>>     -ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
>>>>     -"dynamic"
>>>>     -
>>>>     -# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6
>>>>     should be
>>>>     -# - aef0::800:ff:fe00:26 (EUI64)
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p37
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb ls-add sw4
>>>>     -ovn-nbctl --wait=sb set Logical-switch sw4
>>>>     other_config:ipv6_prefix="bef0::" \
>>>>     --- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
>>>>     <http://192.168.2.0/30>
>>>>     -ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
>>>>     -"dynamic"
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p38
>>>>     dynamic_addresses], [0],
>>>>     -     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
>>>>     -"f0:00:00:00:10:12 dynamic"
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p39
>>>>     dynamic_addresses], [0],
>>>>     -     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
>>>>     -])
>>>>     -
>>>>     -# Test the case where IPv4 addresses are exhausted and IPv6
>>>>     prefix is set
>>>>     -# p40 should not have an IPv4 address since the pool is exhausted
>>>>     -ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
>>>>     -"dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p40
>>>>     dynamic_addresses], [0],
>>>>     -         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
>>>>     -])
>>>>     -
>>>>     -# Test dynamic changes on switch ports.
>>>>     -#
>>>>     -ovn-nbctl --wait=sb ls-add sw5
>>>>     -ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
>>>>     -"dynamic"
>>>>     -# p41 will start with nothing
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         [[[]]
>>>>     -])
>>>>     -
>>>>     -# Set a subnet. Now p41 should have an ipv4 address, too
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>>>     subnet=192.168.1.0/24
>>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>>>     -         ["0a:00:00:a8:01:22 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -# Clear the other_config. The IPv4 address should be gone
>>>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         [[[]]
>>>>     -])
>>>>     -
>>>>     -# Set an IPv6 prefix. Now p41 should have an IPv6 address.
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>>>     other_config:ipv6_prefix="aef0::"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
>>>>     -])
>>>>     -
>>>>     -# Change the MAC address to a static one. The IPv6 address should
>>>>     update.
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b 
>>>> dynamic"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
>>>>     -])
>>>>     -
>>>>     -# Change the IPv6 prefix. The IPv6 address should update.
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw5
>>>>     other_config:ipv6_prefix="bef0::"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
>>>>     -])
>>>>     -
>>>>     -# Clear the other_config. The IPv6 address should be gone
>>>>     -ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         [[[]]
>>>>     -])
>>>>     -
>>>>     -# Set the subnet again. Now p41 should get the IPv4 address 
>>>> again.
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config
>>>>     subnet=192.168.1.0/24
>>>>     -AT_CHECK([ovn-nbctl <http://192.168.1.0/24-AT_CHECK(%5Bovn-nbctl>
>>>>     get Logical-Switch-Port p41 dynamic_addresses], [0],
>>>>     -         ["f0:00:00:00:10:2b 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -# Add an excluded IP address that conflicts with p41. p41 should
>>>>     update.
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
>>>>     -exclude_ips="192.168.1.2"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         ["f0:00:00:00:10:2b 192.168.1.3"
>>>>     -])
>>>>     -
>>>>     -# Add static ip address
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
>>>>     -ovn-nbctl list Logical-Switch-Port p41
>>>>     -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
>>>>     -"dynamic 192.168.1.101"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41
>>>>     dynamic_addresses], [0],
>>>>     -         ["0a:00:00:a8:01:65 192.168.1.100"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p42
>>>>     dynamic_addresses], [0],
>>>>     -         ["0a:00:00:a8:01:66 192.168.1.101"
>>>>     -])
>>>>     -
>>>>     -# define a mac address prefix
>>>>     -ovn-nbctl ls-add sw6
>>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>>     options:mac_prefix="00:11:22:33:44:55"
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw6
>>>>     other_config:subnet=192.168.100.0/24
>>>>     -for <http://192.168.100.0/24-for> n in $(seq 1 3); do
>>>>     -    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses
>>>>     "p5$n" dynamic
>>>>     -done
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p51
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:a8:64:03 192.168.100.2"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p52
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:a8:64:04 192.168.100.3"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p53
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:a8:64:05 192.168.100.4"
>>>>  ��  -])
>>>>     -
>>>>     -# verify configuration order does not break IPAM/MACAM
>>>>     -ovn-nbctl ls-add sw7
>>>>     -for n in $(seq 1 3); do
>>>>     -    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses
>>>>     "p7$n" dynamic
>>>>     -done
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw7
>>>>     other_config:ipv6_prefix="bef0::"
>>>>     -p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 
>>>> dynamic_addresses)
>>>>     -p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 
>>>> dynamic_addresses)
>>>>     -p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 
>>>> dynamic_addresses)
>>>>     -AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
>>>>     -AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
>>>>     -AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
>>>>     -
>>>>     -# request to assign mac only
>>>>     -#
>>>>     -ovn-nbctl ls-add sw8
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw8 
>>>> other_config:mac_only=true
>>>>     -for n in $(seq 1 3); do
>>>>     -    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses
>>>>     "p8$n" dynamic
>>>>     -done
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p81
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:00:00:06"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p82
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:00:00:07"
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p83
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:00:00:08"
>>>>     -])
>>>>     -
>>>>     -# clear mac_prefix and check it is allocated in a random manner
>>>>     -ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
>>>>     -ovn-nbctl ls-add sw9
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw9 
>>>> other_config:mac_only=true
>>>>     -ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 
>>>> dynamic
>>>>     -
>>>>     -mac_prefix=$(ovn-nbctl --wait=sb get NB_Global .
>>>>     options:mac_prefix | tr -d \")
>>>>     -port_addr=$(ovn-nbctl get Logical-Switch-Port p91
>>>>     dynamic_addresses | tr -d \")
>>>>     -AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
>>>>     -
>>>>     -ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
>>>>     -ovn-nbctl ls-add sw10
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>>>     other_config:ipv6_prefix="ae01::"
>>>>     -ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101
>>>>     "dynamic ae01::1"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p101
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:00:00:0a ae01::1"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb set Logical-Switch sw10
>>>>     other_config:subnet=192.168.110.0/24
>>>>     -ovn-nbctl <http://192.168.110.0/24-ovn-nbctl> --wait=sb lsp-add
>>>>     sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 
>>>> ae01::2"
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p102
>>>>     dynamic_addresses], [0],
>>>>     -    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
>>>>     -])
>>>>     -
>>>>     -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 northd-backup
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ipam connectivity])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -# Test for a ping using dynamically allocated addresses.
>>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>>     -ovn-nbctl ls-add foo -- add Logical_Switch foo other_config
>>>>     subnet=192.168.1.0/24
>>>>     -ovn-nbctl <http://192.168.1.0/24-ovn-nbctl> ls-add alice -- add
>>>>     Logical_Switch alice other_config subnet=192.168.2.0/24
>>>>     <http://192.168.2.0/24>
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -          options:router-port=foo \
>>>>     -          -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect alice to R1
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice type=router \
>>>>     -          options:router-port=alice 
>>>> addresses=\"00:00:00:01:02:04\"
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl --wait=sb lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "dynamic"
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>>     foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl --wait=sb lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "dynamic"
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>>     alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
>>>>     -
>>>>     -# Create logical port foo2 in foo
>>>>     -ovn-nbctl --wait=sb lsp-add foo foo2 \
>>>>     --- lsp-set-addresses foo2 "dynamic"
>>>>     -AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port
>>>>     foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
>>>>     -
>>>>     -# Create a hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=foo2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>>     -    set interface hv1-vif3 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>>     -    ofport-request=3
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and foo2
>>>>     -src_mac="0a0000a80103"
>>>>     -dst_mac="0a0000a80104"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="0a0000a80103"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Packet to Expect at foo2
>>>>     -src_mac="0a0000a80103"
>>>>     -dst_mac="0a0000a80104"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>>> -expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > received1.packets
>>>>     -echo $expected > expout
>>>>     -AT_CHECK([cat received1.packets], [0], [expout])
>>>>     -
>>>>     -# Packet to Expect at alice1
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="0a0000a80203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif3-tx.pcap > received2.packets
>>>>     -echo $expected > expout
>>>>     -AT_CHECK([cat received2.packets], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ovs-vswitchd restart])
>>>>     -AT_KEYWORDS([vswitchd])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>>> 10.0.0.4"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -sleep 2
>>>>     -
>>>>     -as hv1 ovs-vsctl show
>>>>     -
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
>>>>     -
>>>>     -echo "Total flows before vswitchd restart = " $total_flows
>>>>     -
>>>>     -# Code taken from ovs-save utility
>>>>     -save_flows () {
>>>>     -    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
>>>>     -    as hv1 ovs-ofctl dump-flows "br-int" | sed -e 
>>>> '/NXST_FLOW/d' \
>>>>     -            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> 
>>>> restore_flows.sh
>>>>     -    echo "EOF" >> restore_flows.sh
>>>>     -}
>>>>     -
>>>>     -restart_vswitchd () {
>>>>     -    restore_flows=$1
>>>>     -
>>>>     -    if test $restore_flows = true; then
>>>>     -        save_flows
>>>>     -    fi
>>>>     -
>>>>     -    as hv1
>>>>     -    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>>     -
>>>>     -    if test $restore_flows = true; then
>>>>     -        as hv1
>>>>     -        ovs-vsctl --no-wait set open_vswitch .
>>>>     other_config:flow-restore-wait="true"
>>>>     -    fi
>>>>     -
>>>>     -    as hv1
>>>>     -    start_daemon ovs-vswitchd --enable-dummy=system -vvconn
>>>>     -vofproto_dpif -vunixctl
>>>>     -    ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -    if test $restore_flows = true; then
>>>>     -        sh ./restore_flows.sh
>>>>     -        echo "Flows after restore"
>>>>     -        as hv1
>>>>     -        ovs-ofctl dump-flows br-int
>>>>     -        ovs-vsctl --no-wait --if-exists remove open_vswitch .
>>>>     other_config \
>>>>     -            flow-restore-wait="true"
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -# Save the flows, restart vswitchd and restore the flows
>>>>     -restart_vswitchd true
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>>>     | wc -l`
>>>>     -    echo "Total flows after vswitchd restart = "
>>>>     $total_flows_after_restart
>>>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>>>     -])
>>>>     -
>>>>     -# Restart vswitchd without restoring
>>>>     -restart_vswitchd false
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int
>>>>     | wc -l`
>>>>     -    echo "Total flows after vswitchd restart = "
>>>>     $total_flows_after_restart
>>>>     -    test "${total_flows}" = "${total_flows_after_restart}"
>>>>     -])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send arp for nexthop])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Topology: Two LSs - ls1 and ls2 are connected via router r0
>>>>     -
>>>>     -# Create logical switches
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -
>>>>     -# Create  router
>>>>     -ovn-nbctl create Logical_Router name=lr0
>>>>     -
>>>>     -# Add router ls1p1 port to gateway router
>>>>     -ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
>>>>     -ovn-nbctl <http://192.168.0.1/24-ovn-nbctl> lsp-add ls1 ls1lp1 --
>>>>     set Logical_Switch_Port ls1lp1  \
>>>>     -    type=router options:router-port=lrp-ls1lp1 \
>>>>     -    addresses='"f0:00:00:00:00:01 192.168.0.1"'
>>>>     -
>>>>     -# Add router ls2p2 port to gateway router
>>>>     -ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
>>>>     -ovn-nbctl <http://192.168.1.1/24-ovn-nbctl> lsp-add ls2 ls2lp1 --
>>>>     set Logical_Switch_Port ls2lp1 \
>>>>     -    type=router options:router-port=lrp-ls2lp1 \
>>>>     -    addresses='"f0:00:00:00:00:02 192.168.1.1"'
>>>>     -
>>>>     -# Set default gateway (nexthop) to 192.168.1.254
>>>>     -ovn-nbctl lr-route-add lr0 "0.0.0.0/0 <http://0.0.0.0/0>"
>>>>     192.168.1.254 lrp-ls2lp1
>>>>     -
>>>>     -# Create logical port ls1lp2 in ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1lp2 \
>>>>     --- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
>>>>     -
>>>>     -# Create logical port ls2lp2 in ls2
>>>>     -ovn-nbctl lsp-add ls2 ls2lp2 \
>>>>     --- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
>>>>     -    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
>>>>     -    options:tx_pcap=hv1/ls1lp2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
>>>>     -    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
>>>>     -    options:tx_pcap=hv1/ls2lp2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list chassis
>>>>     -ovn-sbctl list encap
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "------Flows dump-----"
>>>>     -as hv1
>>>>     -ovs-ofctl dump-flows
>>>>     -echo "---------------------"
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -src_mac="f00000000003"
>>>>     -dst_mac="f00000000001"
>>>>     -src_ip=`ip_to_hex 192 168 0 2`
>>>>     -dst_ip=`ip_to_hex 8 8 8 8`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -# Send IP packet destined to 8.8.8.8 from lsp1lp2
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
>>>>     -
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -# ARP packet should be received with Target IP Address set to
>>>>     192.168.1.254 and
>>>>     -# not 8.8.8.8
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ls2lp2-tx.pcap | trim_zeros > packets
>>>> -expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe" 
>>>>
>>>>     -echo $expected > expout
>>>>     -AT_CHECK([cat packets], [0], [expout])
>>>>     -cat packets
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -# Create logical switch
>>>>     -ovn-nbctl ls-add ls0
>>>>     -# Create gateway router
>>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>>     -# Add router port to gateway router
>>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>>     <http://192.168.0.1/24>
>>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port 
>>>> lrp0-rp \
>>>>     -    type=router options:router-port=lrp0
>>>>     addresses='"f0:00:00:00:00:01"'
>>>>     -# Add nat-address option
>>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="f0:00:00:00:00:01 192.168.0.2"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0
>>>>     -
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>>> network_name=physnet1])
>>>>     -
>>>>     -# Wait until the patch ports are created in hv1 to connect br-int
>>>>     to br-eth0
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
>>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>>     -
>>>>     -# Wait for packet to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>>
>>>>     -echo $expected > expout
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>>
>>>>     -echo $expected >> expout
>>>>     -AT_CHECK([sort packets], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in
>>>>     localnet])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -# Create logical switch
>>>>     -ovn-nbctl ls-add ls0
>>>>     -# Create gateway router
>>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>>     -# Add router port to gateway router
>>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>>     <http://192.168.0.1/24>
>>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port 
>>>> lrp0-rp \
>>>>     -    type=router options:router-port=lrp0
>>>>     addresses='"f0:00:00:00:00:01"'
>>>>     -# Add nat-address option
>>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="router"
>>>>     -# Add NAT rules
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>>>     <http://10.0.0.0/24>])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
>>>>     -# Add load balancers
>>>>     -AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80
>>>>     <http://192.168.0.3:80> 10.0.0.2:80
>>>>     <http://10.0.0.2:80>,10.0.0.3:80 <http://10.0.0.3:80>])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
>>>>     -AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080
>>>>     <http://192.168.0.3:8080> 10.0.0.2:8080
>>>>     <http://10.0.0.2:8080>,10.0.0.3:8080 <http://10.0.0.3:8080>])
>>>>     -AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl \
>>>>     -    -- add-br br-phys \
>>>>     -    -- add-br br-eth0
>>>>     -
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>>     -AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface
>>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>>> network_name=physnet1])
>>>>     -
>>>>     -# Wait until the patch ports are created to connect br-int to 
>>>> br-eth0
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
>>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>>     -
>>>>     -ovn-sbctl list port_binding lrp0-rp
>>>>     -echo "*****"
>>>>     -ovn-nbctl list logical_switch_port lrp0-rp
>>>>     -ovn-nbctl list logical_router_port lrp0
>>>>     -ovn-nbctl show
>>>>     -# Wait for packet to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>>
>>>>     -echo $expected > expout
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>>
>>>>     -echo $expected >> expout
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003" 
>>>>
>>>>     -echo $expected >> expout
>>>>     -AT_CHECK([sort packets], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- delete mac bindings])
>>>>     -ovn_start
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl -- add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -# Create logical switch ls0
>>>>     -ovn-nbctl ls-add ls0
>>>>     -# Create ports lp0, lp1 in ls0
>>>>     -ovn-nbctl lsp-add ls0 lp0
>>>>     -ovn-nbctl lsp-add ls0 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
>>>>     -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
>>>>     -dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" |
>>>>     cut -f2 -d " "`
>>>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>>>     logical_port=lp0 mac="mac1"
>>>>     -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid
>>>>     logical_port=lp1 mac="mac2"
>>>>     -ovn-sbctl find MAC_Binding
>>>>     -# Delete port lp0 and check that its MAC_Binding is deleted.
>>>>     -ovn-nbctl lsp-del lp0
>>>>     -ovn-sbctl find MAC_Binding
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0
>>>>     | wc -l` = 0])
>>>>     -# Delete logical switch ls0 and check that its MAC_Binding is
>>>>     deleted.
>>>>     -ovn-nbctl ls-del ls0
>>>>     -ovn-sbctl find MAC_Binding
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- conntrack zone allocation])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# 2 logical switches "foo" (192.168.1.0/24
>>>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>>>     <http://172.16.1.0/24>)
>>>>     -# connected to a router R1.
>>>>     -# foo has foo1 to act as a client.
>>>>     -# bar has bar1, bar2, bar3 to act as servers.
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -for i in foo1 bar1 bar2 bar3; do
>>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>>     -        set interface $i external-ids:iface-id=$i \
>>>>     -        options:tx_pcap=hv1/$i-tx.pcap \
>>>>     -        options:rxq_pcap=hv1/$i-rx.pcap
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port bar1, bar2 and bar3 in bar
>>>>     -for i in `seq 1 3`; do
>>>>     -    ip=`expr $i + 1`
>>>>     -    ovn-nbctl lsp-add bar bar$i \
>>>>     -    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
>>>>     -done
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep
>>>>     REG13 | wc -l` -eq 4])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- tag allocation])
>>>>     -ovn_start
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add ls0])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
>>>>     -AT_CHECK([ovn-nbctl ls-add ls1])
>>>>     -
>>>>     -dnl When a tag is provided, no allocation is done
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>>>     -])
>>>>     -dnl The same 'tag' gets created in southbound database.
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c0"], [0], [3
>>>>     -])
>>>>     -
>>>>     -dnl Allocate tags and see it getting created in both NB and SB
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c1"], [0], [1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c2"], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c3"], [0], [4
>>>>     -])
>>>>     -
>>>>     -dnl A different parent.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c4"], [0], [1
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c5"], [0], [2
>>>>     -])
>>>>     -
>>>>     -dnl Delete a logical port and create a new one.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c6"], [0], [1
>>>>     -])
>>>>     -
>>>>     -dnl Restart northd to see that the same allocation remains.
>>>>     -as northd
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-northd])
>>>>     -start_daemon ovn-northd \
>>>>     -    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
>>>>     -    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
>>>>     -
>>>>     -dnl Create a switch to make sure that ovn-northd has run through
>>>>     the main loop.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>>     -])
>>>>     -
>>>>     -dnl Create a switch port with a tag that has already been 
>>>> allocated.
>>>>     -dnl It should go through fine with a duplicate tag.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="c7"], [0], [2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add ls2])
>>>>     -dnl When there is no parent_name provided (for say, 'localnet'),
>>>>     'tag_request'
>>>>     -dnl gets copied to 'tag'
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
>>>>     -])
>>>>     -dnl The same 'tag' gets created in southbound database.
>>>>     -AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find
>>>>     port_binding \
>>>>     -logical_port="local0"], [0], [25
>>>>     -])
>>>>     -dnl If 'tag_request' is 0 for localnet, nothing gets written 
>>>> to 'tag'
>>>>     -AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1])
>>>>     -dnl change the tag_request.
>>>>     -AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1
>>>>     tag_request=50])
>>>>     -AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on
>>>>     localnet])
>>>>     -ovn_start
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -    ovs-vsctl add-br br-eth0
>>>>     -    AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-eth0])
>>>>     -done
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>>> network_name=physnet1])
>>>>     -
>>>>     -
>>>>     -# Create 3 vifs.
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif1
>>>>     "f0:00:00:00:00:01 192.168.1.1"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif1
>>>>     "f0:00:00:00:00:01"])
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2
>>>>     "f0:00:00:00:00:02 192.168.1.2"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif2
>>>>     "f0:00:00:00:00:02"])
>>>>     -AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses localvif3
>>>>     "f0:00:00:00:00:03 192.168.1.3"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-port-security localvif3
>>>>     "f0:00:00:00:00:03"])
>>>>     -
>>>>     -# Bind the localvif1 to hv1.
>>>>     -as hv1
>>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface
>>>>     localvif1 external_ids:iface-id=localvif1])
>>>>     -
>>>>     -# On hv1, check that there are no flows outputting bcast to 
>>>> tunnel
>>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>>     -
>>>>     -# On hv2, check that no flow outputs bcast to tunnel to hv1.
>>>>     -as hv2
>>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>>     -
>>>>     -# Now bind vif2 on hv2.
>>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface
>>>>     localvif2 external_ids:iface-id=localvif2])
>>>>     -
>>>>     -# At this point, the broadcast flow on vif2 should be deleted.
>>>>     -# because, there is now a localnet vif bound (table=32
>>>>     programming logic)
>>>>     -OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 |
>>>>     ofctl_strip | grep output | wc -l` -eq 0])
>>>>     -
>>>>     -# Verify that the local net patch port exists on hv2.
>>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>>     -
>>>>     -# Now bind vif3 on hv2.
>>>>     -AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface
>>>>     localvif3 external_ids:iface-id=localvif3])
>>>>     -
>>>>     -# Verify that the local net patch port still exists on hv2
>>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>>     -
>>>>     -# Delete localvif2
>>>>     -AT_CHECK([ovn-nbctl lsp-del localvif2])
>>>>     -
>>>>     -# Verify that the local net patch port still exists on hv2,
>>>>     -# because, localvif3 is still bound.
>>>>     -OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port
>>>>     patch-br-int-to-ln_port" | wc -l` -eq 1])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -AT_SETUP([ovn -- ACL logging])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -for i in lp1 lp2; do
>>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>>     -        set interface $i external-ids:iface-id=$i \
>>>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>>>     -done
>>>>     -
>>>>     -lp1_mac="f0:00:00:00:00:01"
>>>>     -lp1_ip="192.168.1.2"
>>>>     -
>>>>     -lp2_mac="f0:00:00:00:00:02"
>>>>     -lp2_ip="192.168.1.3"
>>>>     -
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>>>     -ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0
>>>>     to-lport 1000 'tcp.dst==81' drop
>>>>     -
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
>>>>     -ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0
>>>>     to-lport 1000 'tcp.dst==83' allow
>>>>     -
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
>>>>     -ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85'
>>>>     allow-related
>>>>     -
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
>>>>     -ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow
>>>>     acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
>>>>     -
>>>>     -ovn-sbctl dump-flows
>>>>     -
>>>>     -
>>>>     -# Send packet that should be dropped without logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should be dropped with logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should be allowed without logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should be allowed with logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should allow related flows without logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should allow related flows with logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should be rejected without logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Send packet that should be rejected with logging.
>>>>     -packet="inport==\"lp1\" && eth.src==$lp1_mac && 
>>>> eth.dst==$lp2_mac &&
>>>>     -        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && 
>>>> ip4.dst==$lp2_ip &&
>>>>     -        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
>>>>     -as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log'
>>>>     hv/ovn-controller.log) ])
>>>>     -
>>>>     -AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed
>>>>     's/.*name=/name=/'], [0], [dnl
>>>>     -name="drop-flow", verdict=drop, severity=alert:
>>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn 
>>>>
>>>>     -name="allow-flow", verdict=allow, severity=info:
>>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn 
>>>>
>>>>     -name="<unnamed>", verdict=allow, severity=info:
>>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn 
>>>>
>>>>     -name="reject-flow", verdict=reject, severity=alert:
>>>> tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVN_CLEANUP([hv])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -AT_SETUP([ovn -- ACL rate-limited logging])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -for i in lp1 lp2; do
>>>>     -    ovs-vsctl -- add-port br-int $i -- \
>>>>     -        set interface $i external-ids:iface-id=$i \
>>>>     -        options:tx_pcap=hv/$i-tx.pcap \
>>>>     -        options:rxq_pcap=hv/$i-rx.pcap
>>>>     -done
>>>>     -
>>>>     -lp1_mac="f0:00:00:00:00:01"
>>>>     -lp1_ip="192.168.1.2"
>>>>     -
>>>>     -lp2_mac="f0:00:00:00:00:02"
>>>>     -lp2_ip="192.168.1.3"
>>>>     -
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp1 $lp1_mac
>>>>     -ovn-nbctl lsp-set-addresses lp2 $lp2_mac
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -
>>>>     -
>>>>     -# Add an ACL that rate-limits logs at 10 per second.
>>>>     -ovn-nbctl meter-add http-rl1 drop 10 pktps
>>>>     -ovn-nbctl --log --severity=alert --meter=http-rl1
>>>>     --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
>>>>     -
>>>>     -# Add an ACL that rate-limits logs at 5 per second.
>>>>     -ovn-nbctl meter-add http-rl2 drop 5 pktps
>>>>     -ovn-nbctl --log --severity=alert --meter=http-rl2
>>>>     --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
>>>>     -
>>>>     -# Add an ACL that doesn't rate-limit logs.
>>>>     -ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0
>>>>     to-lport 1000 'tcp.dst==82' drop
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -# For each ACL, send 100 packets.
>>>>     -for i in `seq 1 100`; do
>>>>     -    ovs-appctl netdev-dummy/receive lp1
>>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)' 
>>>>
>>>>     -
>>>>     -    ovs-appctl netdev-dummy/receive lp1
>>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)' 
>>>>
>>>>     -
>>>>     -    ovs-appctl netdev-dummy/receive lp1
>>>> 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)' 
>>>>
>>>>     -done
>>>>     -
>>>>     -# The rate at which packets are sent is highly system-dependent,
>>>>     so we
>>>>     -# can't count on precise drop counts.  To work around that, we 
>>>> just
>>>>     -# check that exactly 100 "http-acl3" actions were logged and that
>>>>     there
>>>>     -# were more "http-acl1" actions than "http-acl2" ones.
>>>>     -OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3'
>>>>     hv/ovn-controller.log) ])
>>>>     -
>>>>     -# On particularly slow or overloaded systems, the transmission
>>>>     rate may
>>>>     -# be lower than the configured meter rate.  To prevent false test
>>>>     -# failures, we check the duration count of the meter, and if it's
>>>>     -# greater than nine seconds, just skip the test.
>>>>     -d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep
>>>>     "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s 
>>>> .*/\1/')
>>>>     -
>>>>     -echo "Meter duration: $d_secs"
>>>>     -AT_SKIP_IF([test $d_secs -gt 9])
>>>>     -
>>>>     -# Print some information that may help debugging.
>>>>     -as hv ovs-appctl -t ovn-controller meter-table-list
>>>>     -as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
>>>>     -
>>>>     -n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
>>>>     -n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
>>>>     -n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
>>>>     -
>>>>     -AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
>>>>     -AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -
>>>>     -AT_SETUP([ovn -- DSCP marking and meter check])
>>>>     -AT_KEYWORDS([ovn])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp1
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp2
>>>>     -ovn-nbctl --wait=sb lsp-add lsw0 lp3
>>>>     -ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
>>>>     -ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
>>>>     -ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
>>>>     -ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
>>>>     -ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -net_add n1
>>>>     -sim_add hv
>>>>     -as hv
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap
>>>>     options:rxq_pcap=vif1-rx.pcap ofport-request=1
>>>>     -ovs-vsctl add-port br-int vif2 -- set Interface vif2
>>>>     external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap
>>>>     options:rxq_pcap=vif2-rx.pcap ofport-request=2
>>>>     -
>>>>     -AT_CAPTURE_FILE([trace])
>>>>     -ovn_trace () {
>>>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>>>     -}
>>>>     -
>>>>     -# Extracts nw_tos from the final flow from ofproto/trace output
>>>>     and prints
>>>>     -# it on stdout.  Prints "none" if no nw_tos was included.
>>>>     -get_final_nw_tos() {
>>>>     -    if flow=$(grep '^Final flow:' stdout); then :; else
>>>>     -       # The output didn't have a final flow.
>>>>     -       return 99
>>>>     -    fi
>>>>     -
>>>>     -    tos=$(echo "$flow" | sed -n
>>>>     's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
>>>>     -    case $tos in
>>>>     -        '') echo none ;;
>>>>     -        *) echo $tos ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -# check_tos TOS
>>>>     -#
>>>>     -# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set
>>>>     to TOS.
>>>>     -check_tos() {
>>>>     -    # First check with ovn-trace for logical flows.
>>>>     -    echo "checking for tos $1"
>>>>     -    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
>>>>     -     echo 'output("lp2");') > expout
>>>>     -    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src
>>>>     == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src ==
>>>>     1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
>>>>     -
>>>>     -    # Then re-check with ofproto/trace for a physical packet.
>>>>     -    AT_CHECK([ovs-appctl ofproto/trace br-int
>>>> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'], 
>>>>
>>>>     [0], [stdout-nolog])
>>>>     -    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
>>>>     -])
>>>>     -}
>>>>     -
>>>>     -# check at L2
>>>>     -AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src ==
>>>>     f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0],
>>>>     [output("lp2");
>>>>     -])
>>>>     -AT_CHECK([ovs-appctl ofproto/trace br-int
>>>> 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'],
>>>>     [0], [stdout-nolog])
>>>>     -AT_CHECK([get_final_nw_tos], [0], [none
>>>>     -])
>>>>     -
>>>>     -# check at L3 without dscp marking
>>>>     -check_tos 0
>>>>     -
>>>>     -# Mark DSCP with a valid value
>>>>     -qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS
>>>>     priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\
>>>>     is_chassis_resident(\"lp1\")" direction="from-lport" -- set
>>>>     Logical_Switch lsw0 qos_rules=@lp1-qos)
>>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>>>     -])
>>>>     -check_tos 48
>>>>     -
>>>>     -# check at hv without qos meter
>>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>>     meter | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# Update the meter rate
>>>>     -ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
>>>>     -
>>>>     -# check at hv with a qos meter table
>>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>>     rate=100 | wc -l], [0], [1
>>>>     -])
>>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>>     meter | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# Update the DSCP marking
>>>>     -ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
>>>>     -check_tos 63
>>>>     -
>>>>     -# Update the meter rate
>>>>     -ovn-nbctl --wait=hv set QoS $qos_id
>>>>     bandwidth=rate=4294967295,burst=4294967295
>>>>     -
>>>>     -# check at hv with a qos meter table
>>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>>     burst_size=4294967295 | wc -l], [0], [1
>>>>     -])
>>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>>     meter | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\""
>>>>     direction="to-lport"
>>>>     -check_tos 63
>>>>     -
>>>>     -# Disable DSCP marking
>>>>     -ovn-nbctl --wait=hv qos-del lsw0
>>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
>>>>     -])
>>>>     -check_tos 0
>>>>     -
>>>>     -# check at hv without qos meter
>>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>>     meter | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# check meter with chassis not resident
>>>>     -ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" &&
>>>>     is_chassis_resident("lp3")' rate=11123 burst=111230
>>>>     -AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# check no meter table
>>>>     -AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep
>>>>     meter | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep
>>>>     rate=11123 | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -OVN_CLEANUP([hv])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- read-only sb db:ptcp access])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -
>>>>     -: > .$1.db.~lock~
>>>>     -ovsdb-tool create ovn-sb.db 
>>>> "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>>     -
>>>>     -# Add read-only remote to sb ovsdb-server
>>>>     -AT_CHECK(
>>>>     -  [ovsdb-tool transact ovn-sb.db \
>>>>     -     ['["OVN_Southbound",
>>>>     -       {"op": "insert",
>>>>     -        "table": "SB_Global",
>>>>     -        "row": {
>>>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>>>     -       {"op": "insert",
>>>>     -        "table": "Connection",
>>>>     -        "uuid-name": "xyz",
>>>>     -        "row": {"target": "ptcp:0:127.0.0.1",
>>>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>>>     -
>>>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock
>>>>     --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
>>>>     -
>>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>>     -
>>>>     -# read-only accesses should succeed
>>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global],
>>>>     [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list
>>>>     Connection], [0], [stdout], [ignore])
>>>>     -
>>>>     -# write access should fail
>>>>     -AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch
>>>>     vxlan 1.2.4.8], [1], [ignore],
>>>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>>>     allowed when database server is in read only mode","error":"not
>>>>     allowed"}
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- read-only sb db:pssl access])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>>     -\\]"])
>>>>     -
>>>>     -: > .$1.db.~lock~
>>>>     -ovsdb-tool create ovn-sb.db 
>>>> "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>>     -
>>>>     -# Add read-only remote to sb ovsdb-server
>>>>     -AT_CHECK(
>>>>     -  [ovsdb-tool transact ovn-sb.db \
>>>>     -     ['["OVN_Southbound",
>>>>     -       {"op": "insert",
>>>>     -        "table": "SB_Global",
>>>>     -        "row": {
>>>>     -          "connections": ["set", [["named-uuid", "xyz"]]]}},
>>>>     -       {"op": "insert",
>>>>     -        "table": "Connection",
>>>>     -        "uuid-name": "xyz",
>>>>     -        "row": {"target": "pssl:0:127.0.0.1",
>>>>     -               "read_only": true}}]']], [0], [ignore], [ignore])
>>>>     -
>>>>     -start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
>>>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>>>     - --private-key="$PKIDIR/testpki-privkey2.pem" \
>>>>     - --certificate="$PKIDIR/testpki-cert2.pem" \
>>>>     - --ca-cert="$PKIDIR/testpki-cacert.pem" \
>>>>     -                          ovn-sb.db
>>>>     -
>>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>>     -
>>>>     -# read-only accesses should succeed
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -                    list SB_Global], [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -                    list Connection], [0], [stdout], [ignore])
>>>>     -
>>>>     -# write access should fail
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
>>>>     -[ovn-sbctl: transaction error: {"details":"insert operation not
>>>>     allowed when database server is in read only mode","error":"not
>>>>     allowed"}
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- nb connection/ssl commands])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>>     -\\]"])
>>>>     -
>>>>     -: > .$1.db.~lock~
>>>>     -ovsdb-tool create ovn-nb.db 
>>>> "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
>>>>     -
>>>>     -# Start nb db server using db connection/ssl entries (unpopulated
>>>>     initially)
>>>>     -start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
>>>>     - --remote=db:OVN_Northbound,NB_Global,connections \
>>>>     - --private-key=db:OVN_Northbound,SSL,private_key \
>>>>     - --certificate=db:OVN_Northbound,SSL,certificate \
>>>>     - --ca-cert=db:OVN_Northbound,SSL,ca_cert \
>>>>     -                          ovn-nb.db
>>>>     -
>>>>     -# Populate SSL configuration entries in nb db
>>>>     -AT_CHECK(
>>>>     -    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>>>     -                       $PKIDIR/testpki-cert.pem \
>>>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>>>     [stdout], [ignore])
>>>>     -
>>>>     -# Populate a passive SSL connection in nb db
>>>>     -AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0],
>>>>     [stdout], [ignore])
>>>>     -
>>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>>     -
>>>>     -# Verify SSL connetivity to nb db server
>>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          list NB_Global],
>>>>     -         [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          list Connection],
>>>>     -         [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          get-connection],
>>>>     -         [0], [stdout], [ignore])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- sb connection/ssl commands])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
>>>>     -PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
>>>>     -AT_SKIP_IF([expr "$PKIDIR" : ".*[      '\"
>>>>     -\\]"])
>>>>     -
>>>>     -: > .$1.db.~lock~
>>>>     -ovsdb-tool create ovn-sb.db 
>>>> "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
>>>>     -
>>>>     -# Start sb db server using db connection/ssl entries (unpopulated
>>>>     initially)
>>>>     -start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
>>>>     - --remote=db:OVN_Southbound,SB_Global,connections \
>>>>     - --private-key=db:OVN_Southbound,SSL,private_key \
>>>>     - --certificate=db:OVN_Southbound,SSL,certificate \
>>>>     - --ca-cert=db:OVN_Southbound,SSL,ca_cert \
>>>>     -                          ovn-sb.db
>>>>     -
>>>>     -# Populate SSL configuration entries in sb db
>>>>     -AT_CHECK(
>>>>     -    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
>>>>     -                       $PKIDIR/testpki-cert.pem \
>>>>     -                       $PKIDIR/testpki-cacert.pem], [0],
>>>>     [stdout], [ignore])
>>>>     -
>>>>     -# Populate a passive SSL connection in sb db
>>>>     -AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0],
>>>>     [stdout], [ignore])
>>>>     -
>>>>     -PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>>>>     -
>>>>     -# Verify SSL connetivity to sb db server
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          list SB_Global],
>>>>     -         [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          list Connection],
>>>> ��   -         [0], [stdout], [ignore])
>>>>     -AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
>>>>     - --private-key=$PKIDIR/testpki-privkey.pem \
>>>>     - --certificate=$PKIDIR/testpki-cert.pem \
>>>>     - --ca-cert=$PKIDIR/testpki-cacert.pem \
>>>>     -          get-connection],
>>>>     -         [0], [stdout], [ignore])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- nested containers])
>>>>     -ovn_start
>>>>     -
>>>>     -# Physical network:
>>>>     -# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
>>>>     -
>>>>     -# Logical network:
>>>>     -# 3 Logical switches - "mgmt" (172.16.1.0/24
>>>>     <http://172.16.1.0/24>), "foo" (192.168.1.0/24
>>>>     <http://192.168.1.0/24>)
>>>>     -# and "bar" (192.168.2.0/24 <http://192.168.2.0/24>). They are
>>>>     all connected to router R1.
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl ls-add mgmt
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -
>>>>     -# Connect mgmt to R1
>>>>     -ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt
>>>>     type=router \
>>>>     -          options:router-port=mgmt 
>>>> addresses=\"00:00:00:01:02:02\"
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>>>     type=router \
>>>>     -          options:router-port=bar addresses=\"00:00:00:01:02:04\"
>>>>     -
>>>>     -# "mgmt" has VM1 and VM2 connected
>>>>     -ovn-nbctl lsp-add mgmt vm1 \
>>>>     --- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
>>>>     -
>>>>     -ovn-nbctl lsp-add mgmt vm2 \
>>>>     --- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# "foo1" and "foo2" are containers belonging to switch "foo"
>>>>     -# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as
>>>>     parent_port.
>>>>     -ovn-nbctl lsp-add foo foo1 vm1 1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
>>>>     -
>>>>     -ovn-nbctl lsp-add foo foo2 vm2 2 \
>>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>>     -
>>>>     -# "bar1" and "bar2" are containers belonging to switch "bar"
>>>>     -# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as
>>>>     parent_port.
>>>>     -ovn-nbctl lsp-add bar bar1 vm1 2 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
>>>>     -
>>>>     -ovn-nbctl lsp-add bar bar2 vm2 1 \
>>>>     --- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
>>>>     -
>>>>     -# bar3 is a standalone VM belonging to switch "bar"
>>>>     -ovn-nbctl lsp-add bar bar3 \
>>>>     --- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int vm1 -- \
>>>>     -    set interface vm1 external-ids:iface-id=vm1 \
>>>>     -    options:tx_pcap=hv1/vm1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vm1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int bar3 -- \
>>>>     -    set interface bar3 external-ids:iface-id=bar3 \
>>>>     -    options:tx_pcap=hv1/bar3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/bar3-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int vm2 -- \
>>>>     -    set interface vm2 external-ids:iface-id=vm2 \
>>>>     -    options:tx_pcap=hv2/vm2-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vm2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and foo2 (same switch, different
>>>>     HVs and
>>>>     -# different VLAN tags).
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="f00000010206"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at foo2
>>>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet > expected
>>>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>>>     -
>>>>     -# Send ip packets between foo1 and bar2 (different switch,
>>>>     different HV)
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at bar2
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="f00000010208"
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet >> expected
>>>>     -OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
>>>>     -
>>>>     -# Send ip packets between foo1 and bar1
>>>>     -# (different switch, loopback to same vm but different tag)
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at bar1
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="f00000010207"
>>>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet > expected1
>>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>>     -
>>>>     -# Send ip packets between bar1 and bar3
>>>>     -# (same switch. But one is container and another is a 
>>>> standalone VM)
>>>>     -src_mac="f00000010207"
>>>>     -dst_mac="f00000010209"
>>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 3`
>>>> -packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at bar3
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet > expected
>>>>     -OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
>>>>     -
>>>>     -# Send ip packets between foo1 and vm1.
>>>>     -(different switch, container to the VM hosting it.)
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 2`
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at vm1
>>>>     -src_mac="000000010202"
>>>>     -dst_mac="f00000010203"
>>>> -packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet >> expected1
>>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>>     -
>>>>     -# Send packets from vm1 to bar1.
>>>>     -(different switch, A hosting VM to a container inside it)
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010202"
>>>>     -src_ip=`ip_to_hex 172 16 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at vm1
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="f00000010207"
>>>> -packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo  $packet >> expected1
>>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>>     -
>>>>     -# Send broadcast packet from foo1. foo1 should not receive the
>>>>     same packet.
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="ffffffffffff"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 255 255 255 255`
>>>> -packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
>>>>     -
>>>>     -# expected packet at VM1
>>>>     -OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based
>>>>     routes])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>>     LS "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and bar
>>>>     -# (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>>     -#
>>>>     -# R2 and R3 are gateway routers.
>>>>     -# R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) and R3 has
>>>>     bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     -# connected to it. Note how both alice and bob have the same
>>>>     subnet behind it.
>>>>     -# We are trying to simulate external network via those 2
>>>>     switches. In real
>>>>     -# world the switch ports of these switches will have addresses
>>>>     set as "unknown"
>>>>     -# to make them learning switches. Or those switches will be
>>>>     "localnet" ones.
>>>>     -
>>>>     -# Create three hypervisors and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=bar1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>>     -    set interface hv3-vif1 external-ids:iface-id=bob1 \
>>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
>>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add bob
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -    options:router-port=foo addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar
>>>>     type=router \
>>>>     -    options:router-port=bar addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect bob to R3
>>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>>     <http://172.16.1.2/24>
>>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>>     -    type=router options:router-port=bob
>>>>     addresses=\"00:00:03:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Connect R3 to join
>>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>>     <http://20.0.0.3/24>
>>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>>> r3-join \
>>>>     -    type=router options:router-port=R3_join
>>>>     addresses='"00:00:04:01:02:05"'
>>>>     -
>>>>     -# Install static routes with source ip address as the policy for
>>>>     routing.
>>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>>     go via R3.
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>>     <http://192.168.1.0/24> 20.0.0.2
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>>     <http://192.168.2.0/24> 20.0.0.3
>>>>     -
>>>>     -# Install static routes with destination ip address as the policy
>>>>     for routing.
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port bar1 in bar
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
>>>>     -
>>>>     -# Create logical port bob1 in bob
>>>>     -ovn-nbctl lsp-add bob bob1 \
>>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and bar1
>>>>     -# (East-west traffic should flow normally)
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
>>>>     -
>>>>     -# Send ip packets between bar1 and bob1
>>>>     -src_mac="f00000010204"
>>>>     -dst_mac="000001010204"
>>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>>>     -#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
>>>>     -
>>>>     -# Packet to expect at bar1
>>>>     -src_mac="000001010204"
>>>>     -dst_mac="f00000010204"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 192 168 2 2`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo $expected > expected
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -# Packet to Expect at alice1
>>>>     -src_mac="000002010203"
>>>>     -dst_mac="f00000010205"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo $expected > expected
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Packet to Expect at bob1
>>>>     -src_mac="000003010203"
>>>>     -dst_mac="f00000010206"
>>>>     -src_ip=`ip_to_hex 192 168 2 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 4`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo $expected > expected
>>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01
>>>>     10.0.0.4 aef0::4"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 
>>>> 20.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>>     10.0.0.6 20.0.0.4"
>>>>     -
>>>>     -DNS1=`ovn-nbctl create DNS records={}`
>>>>     -DNS2=`ovn-nbctl create DNS records={}`
>>>>     -
>>>>     -ovn-nbctl set DNS $DNS1 records:vm1.ovn.org
>>>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>>>     -ovn-nbctl set DNS $DNS1 records:vm2.ovn.org
>>>>     <http://vm2.ovn.org>="10.0.0.6 20.0.0.4"
>>>>     -ovn-nbctl set DNS $DNS2 records:vm3.ovn.org
>>>>     <http://vm3.ovn.org>="40.0.0.4"
>>>>     -
>>>>     -ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -sleep 2
>>>>     -as hv1 ovs-vsctl show
>>>>     -
>>>>     -echo "*************************"
>>>>     -ovn-sbctl list DNS
>>>>     -echo "*************************"
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -# set_dns_params host_name
>>>>     -# Sets the dns_req_data and dns_resp_data
>>>>     -set_dns_params() {
>>>>     -    local hname=$1
>>>>     -    local ttl=00000e10
>>>>     -    an_count=0001
>>>>     -    type=0001
>>>>     -    case $hname in
>>>>     -    vm1)
>>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>>     -        query_name=03766d31036f766e036f726700
>>>>     -        # IPv4 address - 10.0.0.4
>>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>>>     -        ;;
>>>>     -    vm2)
>>>>     -        # vm2.ovn.org <http://vm2.ovn.org>
>>>>     -        query_name=03766d32036f766e036f726700
>>>>     -        # IPv4 address - 10.0.0.6
>>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000006
>>>>     -        # IPv4 address - 20.0.0.4
>>>>     -
>>>> expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004 
>>>>
>>>>     -        an_count=0002
>>>>     -        ;;
>>>>     -    vm3)
>>>>     -        # vm3.ovn.org <http://vm3.ovn.org>
>>>>     -        query_name=03766d33036f766e036f726700
>>>>     -        # IPv4 address - 40.0.0.4
>>>>     - expected_dns_answer=${query_name}00010001${ttl}000428000004
>>>>     -        ;;
>>>>     -    vm1_ipv6_only)
>>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>>     -        query_name=03766d31036f766e036f726700
>>>>     -        # IPv6 address - aef0::4
>>>>     -        type=001c
>>>>     -
>>>> expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004 
>>>>
>>>>     -        ;;
>>>>     -    vm1_ipv4_v6)
>>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>>     -        query_name=03766d31036f766e036f726700
>>>>     -        type=00ff
>>>>     -        an_count=0002
>>>>     -        # IPv4 address - 10.0.0.4
>>>>     -        # IPv6 address - aef0::4
>>>>     - expected_dns_answer=${query_name}00010001${ttl}00040a000004
>>>>     -
>>>> expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010 
>>>>
>>>>     -
>>>> expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004 
>>>>
>>>>     -        ;;
>>>>     -    vm1_invalid_type)
>>>>     -        # vm1.ovn.org <http://vm1.ovn.org>
>>>>     -        query_name=03766d31036f766e036f726700
>>>>     -        # IPv6 address - aef0::4
>>>>     -        type=0002
>>>>     -        ;;
>>>>     -    vm1_incomplete)
>>>>     -        # set type to none
>>>>     -        type=''
>>>>     -    esac
>>>>     -    # TTL - 3600
>>>>     -    local dns_req_header=010201200001000000000000
>>>>     -    local dns_resp_header=010281200001${an_count}00000000
>>>>     - dns_req_data=${dns_req_header}${query_name}${type}0001
>>>>     -
>>>> dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} 
>>>>
>>>>     -}
>>>>     -
>>>>     -# This shell function sends a DNS request packet
>>>>     -# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
>>>>     -test_dns() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     dns_reply=$6
>>>>     -    local dns_query_data=$7
>>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>>     -    # Packet size => IPv4 header (20) + UDP header (8) +
>>>>     -    #                DNS data (header + query)
>>>>     -    ip_len=`expr 28 + ${#dns_query_data} / 2`
>>>>     -    udp_len=`expr $ip_len - 20`
>>>>     -    ip_len=$(printf "%x" $ip_len)
>>>>     -    udp_len=$(printf "%x" $udp_len)
>>>>     -    local
>>>> request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
>>>>     - request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
>>>>     -    # dns data
>>>>     -    request=${request}${dns_query_data}
>>>>     -
>>>>     -    if test $dns_reply != 0; then
>>>>     -        local dns_reply=$1
>>>>     -        ip_len=`expr 28 + ${#dns_reply} / 2`
>>>>     -        udp_len=`expr $ip_len - 20`
>>>>     -        ip_len=$(printf "%x" $ip_len)
>>>>     -        udp_len=$(printf "%x" $udp_len)
>>>>     -        local
>>>> reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
>>>>     - 
>>>> reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
>>>>     -        echo $reply >> $inport.expected
>>>>     -    else
>>>>     -        for outport; do
>>>>     -            echo $request >> $outport.expected
>>>>     -        done
>>>>     -    fi
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport 
>>>> $request
>>>>     -}
>>>>     -
>>>>     -test_dns6() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     dns_reply=$6
>>>>     -    local dns_query_data=$7
>>>>     -    shift; shift; shift; shift; shift; shift; shift;
>>>>     -    # Packet size => UDP header (8) +
>>>>     -    #                DNS data (header + query)
>>>>     -    ip_len=`expr 8 + ${#dns_query_data} / 2`
>>>>     -    udp_len=$ip_len
>>>>     -    ip_len=$(printf "%x" $ip_len)
>>>>     -    udp_len=$(printf "%x" $udp_len)
>>>>     -    local
>>>> request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip} 
>>>>
>>>>     -    request=${request}9234003500${udp_len}0000
>>>>     -    #dns data
>>>>     -    request=${request}${dns_query_data}
>>>>     -
>>>>     -    if test $dns_reply != 0; then
>>>>     -        local dns_reply=$1
>>>>     -        ip_len=`expr 8 + ${#dns_reply} / 2`
>>>>     -        udp_len=$ip_len
>>>>     -        ip_len=$(printf "%x" $ip_len)
>>>>     -        udp_len=$(printf "%x" $udp_len)
>>>>     -        local
>>>> reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip} 
>>>>
>>>>     - reply=${reply}0035923400${udp_len}0000${dns_reply}
>>>>     -        echo $reply >> $inport.expected
>>>>     -    else
>>>>     -        for outport; do
>>>>     -            echo $request >> $outport.expected
>>>>     -        done
>>>>     -    fi
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport 
>>>> $request
>>>>     -}
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>>     -
>>>>     -set_dns_params vm2
>>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=1
>>>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap > 1.packets
>>>>     -cat 1.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 1.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -set_dns_params vm1
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=1
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Clear the query name options for ls1-lp2
>>>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
>>>>     <http://vm2.ovn.org>
>>>>     -
>>>>     -set_dns_params vm2
>>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=0
>>>>     -test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 3.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap > 1.packets
>>>>     -AT_CHECK([cat 1.packets], [0], [])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Clear the query name for ls1-lp1
>>>>     -# Since ls1 has no query names configued,
>>>>     -# ovn-northd should not add the DNS flows.
>>>>     -ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
>>>>     <http://vm1.ovn.org>
>>>>     -
>>>>     -set_dns_params vm1
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=0
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 3 only.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Test IPv6 (AAAA records) using IPv4 packet.
>>>>     -# Add back the DNS options for ls1-lp1.
>>>>     -ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org
>>>>     <http://vm1.ovn.org>="10.0.0.4 aef0::4"
>>>>     -
>>>>     -set_dns_params vm1_ipv6_only
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=1
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 4.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
>>>>     -set_dns_params vm1_ipv4_v6
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=1
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 5.
>>>>     -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -cat 2.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 2.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Invalid type.
>>>>     -set_dns_params vm1_invalid_type
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=0
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 6.
>>>>     -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Incomplete DNS packet.
>>>>     -set_dns_params vm1_incomplete
>>>>     -src_ip=`ip_to_hex 10 0 0 6`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=0
>>>>     -test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 7.
>>>>     -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Add one more DNS record to the ls1.
>>>>     -ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 
>>>> $DNS2"
>>>>     -
>>>>     -set_dns_params vm3
>>>>     -src_ip=`ip_to_hex 10 0 0 4`
>>>>     -dst_ip=`ip_to_hex 10 0 0 1`
>>>>     -dns_reply=1
>>>>     -test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 8.
>>>>     -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap > 1.packets
>>>>     -cat 1.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat 1.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -# Try DNS query over IPv6
>>>>     -set_dns_params vm1
>>>>     -src_ip=aef00000000000000000000000000004
>>>>     -dst_ip=aef00000000000000000000000000001
>>>>     -dns_reply=1
>>>>     -test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply
>>>>     $dns_req_data $dns_resp_data
>>>>     -
>>>>     -# NXT_RESUMEs should be 9.
>>>>     -OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap > 1.packets
>>>>     -# Skipping the UDP checksum.
>>>>     -cat 1.expected | cut -c 1-120,125- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
>>>>     -
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -rm -f 1.expected
>>>>     -rm -f 2.expected
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA
>>>>     distributed router gateway port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add gw1
>>>>     -as gw1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -sim_add gw2
>>>>     -as gw2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>>     -
>>>>     -sim_add ext1
>>>>     -as ext1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl \
>>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>>     -                                     chassis_name=gw1 \
>>>>     -                                     priority=20 -- \
>>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>>     -                                     chassis_name=gw2 \
>>>>     -                                     priority=10 -- \
>>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port outside1 in outside
>>>>     -ovn-nbctl lsp-add outside outside1 \
>>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# Create localnet port in alice
>>>>     -ovn-nbctl lsp-add alice ln-alice
>>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>>>     -# mapping to the external network, is the one generating packets
>>>>     -as gw1 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -as gw2 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -as ext1 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 2
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -test_ip_packet()
>>>>     -{
>>>>     -    local active_gw=$1
>>>>     -    local backup_gw=$2
>>>>     -    local backup_vswitchd_dead=$3
>>>>     -
>>>>     -    # Send ip packet between foo1 and outside1
>>>>     -    src_mac="f00000010203" # foo1 mac
>>>>     -    dst_mac="000001010203" # rp-foo mac (internal router leg)
>>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -    # ARP request packet to expect at outside1
>>>>     -
>>>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>>>
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -    # Send ARP reply from outside1 back to the router
>>>>     -    # XXX: note, we could avoid this if we plug this port into a
>>>>     netns
>>>>     -    # and setup the IP address into the port, so the kernel would
>>>>     simply reply
>>>>     -    src_mac="000002010203"
>>>>     -    reply_mac="f00000010204"
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>>>     -
>>>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>>>
>>>>     -
>>>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>>>     -
>>>>     -    OVS_WAIT_UNTIL([
>>>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>>>     table=66 | \
>>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>>     -    ])
>>>>     -
>>>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>>>     -    src_mac="000002010203"
>>>>     -    dst_mac="f00000010204"
>>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -
>>>> expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    echo $expected > ext1-vif1.expected
>>>>     -
>>>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>>
>>>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>>>     -    as $active_gw reset_pcap_file br-phys_n1 
>>>> $active_gw/br-phys_n1
>>>>     -
>>>>     -    if test $backup_vswitchd_dead != 1; then
>>>>     -        # Reset the file only if vswitchd in backup gw is alive
>>>>     -        as $backup_gw reset_pcap_file br-phys_n1
>>>>     $backup_gw/br-phys_n1
>>>>     -    fi
>>>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>>>     -
>>>>     -    # Resend packet from foo1 to outside1
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -    sleep 1
>>>>     -
>>>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap > packets
>>>>     -    cat packets | grep $expected > exp
>>>>     -    # Its possible that $active_gw/br-phys_n1-tx.pcap may have
>>>>     received multiple
>>>>     -    # garp packets. So consider only the first packet.
>>>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>>>     -    AT_CHECK([cat exp], [0], [expout])
>>>>     -    rm -f expout
>>>>     -    if test $backup_vswitchd_dead != 1; then
>>>>     -        # Check for backup gw only if vswitchd is alive
>>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap > packets
>>>>     -        AT_CHECK([grep $expected packets | sort], [0], [])
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -test_ip_packet gw1 gw2 0
>>>>     -
>>>>     -ovn-nbctl --timeout=3 --wait=hv \
>>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>>     -                                     chassis_name=gw1 \
>>>>     -                                     priority=10 -- \
>>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>>     -                                     chassis_name=gw2 \
>>>>     -                                     priority=20 -- \
>>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -test_ip_packet gw2 gw1 0
>>>>     -
>>>>     -# Get the claim count of both gw1 and gw2.
>>>>     -gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log |
>>>>     wc -l`
>>>>     -gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log |
>>>>     wc -l`
>>>>     -
>>>>     -# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
>>>>     -as gw2
>>>>     -OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
>>>>     -
>>>>     -# gw1 should claim the cr-alice and the claim count of gw1 
>>>> should be
>>>>     -# incremented by 1.
>>>>     -gw1_claim_ct=$((gw1_claim_ct+1))
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat 
>>>> gw1/ovn-controller.log \
>>>>     -| grep -c "cr-alice: Claiming"`])
>>>>     -
>>>>     -AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
>>>>     -grep -c "cr-alice: Claiming"`])
>>>>     -
>>>>     -test_ip_packet gw1 gw2 1
>>>>     -
>>>>     -as gw2
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[gw1],[ext1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA
>>>>     distributed router gateway port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add gw1
>>>>     -as gw1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -sim_add gw2
>>>>     -as gw2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>>     -
>>>>     -sim_add ext1
>>>>     -as ext1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-int ext1-vif1 -- \
>>>>     -    set interface ext1-vif1 external-ids:iface-id=outside1 \
>>>>     -    options:tx_pcap=ext1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=ext1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R0
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add join
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -#Connect foo to R0
>>>>     -ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
>>>>     -    type=router options:router-port=R0-foo \
>>>>     -    -- lsp-set-addresses foo-R0 router
>>>>     -
>>>>     -#Connect R0 to join
>>>>     -ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
>>>>     <http://100.60.1.1/24>
>>>>     -ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port 
>>>> join-R0 \
>>>>     -    type=router options:router-port=R0-join \
>>>>     -    -- lsp-set-addresses join-R0 router
>>>>     -
>>>>     -#Connect join to R1
>>>>     -ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
>>>>     <http://100.60.1.2/24>
>>>>     -ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port 
>>>> join-R1 \
>>>>     -    type=router options:router-port=R1-join \
>>>>     -    -- lsp-set-addresses join-R1 router
>>>>     -
>>>>     -#add route rules
>>>>     -ovn-nbctl lr-route-add R0 0.0.0.0/0 <http://0.0.0.0/0> 100.60.1.2
>>>>     -ovn-nbctl lr-route-add R1 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     100.60.1.1
>>>>     -
>>>>     -# Connect alice to R1 as distributed router gateway port on gw1
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -
>>>>     -ovn-nbctl \
>>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>>     -                                     chassis_name=gw1 \
>>>>     -                                     priority=20 -- \
>>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>>     -                                     chassis_name=gw2 \
>>>>     -                                     priority=10 -- \
>>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port outside1 in outside
>>>>     -ovn-nbctl lsp-add outside outside1 \
>>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# Create localnet port in alice
>>>>     -ovn-nbctl lsp-add alice ln-alice
>>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
>>>>     -# mapping to the external network, is the one generating packets
>>>>     -as gw1 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -as gw2 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -as ext1 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
>>>>     -
>>>>     -# hv1 should be in 'ref_chassis' of the ha_chasssi_group as 
>>>> logical
>>>>     -# switch 'foo' can reach the router 'R1' (which has gw router 
>>>> port)
>>>>     -# via foo1 -> foo -> R0 -> join -> R1
>>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="hv1"`
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$hv1_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 2
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -test_ip_packet()
>>>>     -{
>>>>     -    local active_gw=$1
>>>>     -    local backup_gw=$2
>>>>     -
>>>>     -    # Send ip packet between foo1 and outside1
>>>>     -    src_mac="f00000010203" # foo1 mac
>>>>     -    dst_mac="000001010203" # foo-R0 mac (internal router leg)
>>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -    # ARP request packet to expect at outside1
>>>>     -
>>>> #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip} 
>>>>
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -    # Send ARP reply from outside1 back to the router
>>>>     -    # XXX: note, we could avoid this if we plug this port into a
>>>>     netns
>>>>     -    # and setup the IP address into the port, so the kernel would
>>>>     simply reply
>>>>     -    src_mac="000002010203"
>>>>     -    reply_mac="f00000010204"
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -    src_ip=`ip_to_hex 172 16 1 1`
>>>>     -
>>>> arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip} 
>>>>
>>>>     -
>>>>     -    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
>>>>     -
>>>>     -    OVS_WAIT_UNTIL([
>>>>     -        test `as $active_gw ovs-ofctl dump-flows br-int | grep
>>>>     table=66 | \
>>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>>     -    ])
>>>>     -
>>>>     -    # Packet to Expect at ext1 chassis, outside1 port
>>>>     -    src_mac="000002010203"
>>>>     -    dst_mac="f00000010204"
>>>>     -    src_ip=`ip_to_hex 192 168 1 2`
>>>>     -    dst_ip=`ip_to_hex 172 16 1 3`
>>>>     -
>>>> expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    echo $expected > ext1-vif1.expected
>>>>     -
>>>> exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>>
>>>>     -    echo $exp_gw_ip_garp >> ext1-vif1.expected
>>>>     -
>>>>     -    as $active_gw reset_pcap_file br-phys_n1 
>>>> $active_gw/br-phys_n1
>>>>     -    as $backup_gw reset_pcap_file br-phys_n1 
>>>> $backup_gw/br-phys_n1
>>>>     -    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
>>>>     -
>>>>     -    # Resend packet from foo1 to outside1
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
>>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $active_gw/br-phys_n1-tx.pcap > packets
>>>>     -    cat packets | grep $expected > exp
>>>>     -    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
>>>>     -    AT_CHECK([cat exp], [0], [expout])
>>>>     -
>>>>     -    $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $backup_gw/br-phys_n1-tx.pcap > packets
>>>>     -    AT_CHECK([grep $expected packets | sort], [0], [])
>>>>     -}
>>>>     -
>>>>     -test_ip_packet gw1 gw2
>>>>     -
>>>>     -ovn-nbctl --timeout=3 --wait=hv \
>>>>     -    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
>>>>     -                                     chassis_name=gw1 \
>>>>     -                                     priority=10 -- \
>>>>     -    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
>>>>     -                                     chassis_name=gw2 \
>>>>     -                                     priority=20 -- \
>>>>     -    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -test_ip_packet gw2 gw1
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 1 LR with distributed router gateway port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR R1 that has switches foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>) and
>>>>     -# alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>>     The logical port
>>>>     -# between R1 and alice has a "redirect-chassis" specified,
>>>>     -# i.e. it is the distributed router gateway port.
>>>>     -# Switch alice also has a localnet port defined.
>>>>     -# An additional switch outside has a localnet port and the
>>>>     -# same subnet as alice (172.16.1.0/24 <http://172.16.1.0/24>).
>>>>     -
>>>>     -# Physical network:
>>>>     -# Three hypervisors hv[123].
>>>>     -# hv1 hosts vif foo1.
>>>>     -# hv2 is the "redirect-chassis" that hosts the distributed
>>>>     -# router gateway port.
>>>>     -# hv3 hosts vif outside1.
>>>>     -# In order to show that connectivity works only through hv2,
>>>>     -# an initial round of tests is run without any bridge-mapping
>>>>     -# defined for the localnet on hv2.  These tests are expected
>>>>     -# to fail.
>>>>     -# Subsequent tests are run after defining the bridge-mapping
>>>>     -# for the localnet on hv2. These tests are expected to succeed.
>>>>     -
>>>>     -# Create three hypervisors and create OVS ports corresponding
>>>>     -# to logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect alice to R1 as distributed router gateway port on hv2
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24> \
>>>>     -    -- set Logical_Router_Port alice 
>>>> options:redirect-chassis="hv2"
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port outside1 in outside
>>>>     -ovn-nbctl lsp-add outside outside1 \
>>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# Create localnet port in alice
>>>>     -ovn-nbctl lsp-add alice ln-alice
>>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
>>>>     -as hv1 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -as hv3 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 2
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list chassis
>>>>     -ovn-sbctl list encap
>>>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>>>     -ovn-sbctl list Gateway_Chassis
>>>>     -echo "------ Port_Binding chassisredirect -------"
>>>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>>>     -echo "-------------------------------------------"
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv3 dump ----------"
>>>>     -as hv3 ovs-ofctl show br-int
>>>>     -as hv3 ovs-ofctl dump-flows br-int
>>>>     -echo "--------------------------"
>>>>     -
>>>>     -
>>>>     -# Check that redirect mapping is programmed only on hv2
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep
>>>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep
>>>>     =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
>>>>     -])
>>>>     -# Check that hv1 sends chassisredirect port traffic to hv2
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep
>>>>     =0x3,metadata=0x1 | grep output | wc -l], [0], [1
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep
>>>>     =0x3,metadata=0x1 | wc -l], [0], [0
>>>>     -])
>>>>     -# Check that arp reply on distributed gateway port is only
>>>>     programmed on hv2
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep
>>>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep
>>>>     load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -
>>>>     -: > hv2-vif1.expected
>>>>     -: > hv3-vif1.expected
>>>>     -
>>>>     -# test_arp INPORT SHA SPA TPA [REPLY_HA]
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT.  The packet is an ARP
>>>>     -# request with SHA, SPA, and TPA as specified.  If REPLY_HA is
>>>>     provided, then
>>>>     -# it should be the hardware address of the target to expect to
>>>>     receive in an
>>>>     -# ARP reply; otherwise no reply is expected.
>>>>     -#
>>>>     -# INPORT is an logical switch port number, e.g. 11 for vif11.
>>>>     -# SHA and REPLY_HA are each 12 hex digits.
>>>>     -# SPA and TPA are each 8 hex digits.
>>>>     -test_arp() {
>>>>     -    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
>>>>     -    local
>>>> request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa} 
>>>>
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>>     $request
>>>>     -
>>>>     -    if test X$reply_ha != X; then
>>>>     -        # Expect to receive the reply, if any.
>>>>     -        local
>>>> reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa} 
>>>>
>>>>     -        echo $reply >> hv${hv}-vif$inport.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -rtr_ip=$(ip_to_hex 172 16 1 1)
>>>>     -foo_ip=$(ip_to_hex 192 168 1 2)
>>>>     -outside_ip=$(ip_to_hex 172 16 1 3)
>>>>     -
>>>>     -echo $rtr_ip
>>>>     -echo $foo_ip
>>>>     -echo $outside_ip
>>>>     -
>>>>     -# ARP for router IP address from outside1, no response expected
>>>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>>     -
>>>>     -# Send ip packet between foo1 and outside1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>>     -
>>>>     -# Now add bridge-mappings on hv2, which should make everything 
>>>> work
>>>>     -as hv2 ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>>>     to br-phys
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>>>     -grep "Port patch-br-int-to-ln-alice" | wc -l`])
>>>>     -
>>>>     -# ARP for router IP address from outside1
>>>>     -test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
>>>>     -
>>>>     -# hv3-vif1.expected should also have the gw router port garp 
>>>> packet.
>>>> -exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101 
>>>>
>>>>     -echo $exp_gw_ip_garp >> hv3-vif1.expected
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>>     -
>>>>     -# Send ip packet between foo1 and outside1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 172 16 1 3`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -# Packet to Expect at outside1
>>>>     -src_mac="000002010203"
>>>>     -dst_mac="f00000010204"
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -echo "------ hv1 dump ----------"
>>>>     -as hv1 ovs-ofctl show br-int
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv2 dump ----------"
>>>>     -as hv2 ovs-ofctl show br-int
>>>>     -as hv2 ovs-ofctl dump-flows br-int
>>>>     -echo "------ hv3 dump ----------"
>>>>     -as hv3 ovs-ofctl show br-int
>>>>     -as hv3 ovs-ofctl dump-flows br-int
>>>>     -echo "----------------------------"
>>>>     -
>>>>     -echo $expected >> hv3-vif1.expected
>>>>     -OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
>>>>     -
>>>>     -#Check ovn-trace over "chassisredirect" port
>>>>     -AT_CAPTURE_FILE([trace])
>>>>     -ovn_trace () {
>>>>     -    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
>>>>     -}
>>>>     -
>>>>     -echo 'ip.ttl--;' > expout
>>>>     -echo 'eth.src = 00:00:02:01:02:03;' >> expout
>>>>     -echo 'eth.dst = f0:00:00:01:02:04;' >> expout
>>>>     -echo 'output("ln-alice");' >> expout
>>>>     -AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src ==
>>>>     f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src ==
>>>>     192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0],
>>>>     [expout])
>>>>     -
>>>>     -# Create logical port alice1 in alice on hv1
>>>>     -as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
>>>>     -
>>>>     -# Create logical port foo2 in foo on hv2
>>>>     -as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=foo2 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovn-nbctl lsp-add foo foo2 \
>>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -: > hv1-vif2.expected
>>>>     -
>>>>     -# Send ip packet between alice1 and foo2
>>>>     -src_mac="f00000010205"
>>>>     -dst_mac="000002010203"
>>>>     -src_ip=`ip_to_hex 172 16 1 4`
>>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
>>>>     -
>>>>     -# Packet to Expect at foo2
>>>>     -src_mac="000001010203"
>>>>     -dst_mac="f00000010206"
>>>>     -src_ip=`ip_to_hex 172 16 1 4`
>>>>     -dst_ip=`ip_to_hex 192 168 1 3`
>>>> -expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -echo $expected >> hv2-vif1.expected
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding
>>>>     logical_port=cr-alice | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice
>>>>     options redirect-chassis
>>>>     -
>>>>     -AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc
>>>>     -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed
>>>>     router])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -# Create logical switches
>>>>     -ovn-nbctl ls-add ls0
>>>>     -ovn-nbctl ls-add ls1
>>>>     -# Create distributed router
>>>>     -ovn-nbctl create Logical_Router name=lr0
>>>>     -# Add distributed gateway port to distributed router
>>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
>>>>     <http://192.168.0.1/24> \
>>>>     -    -- set Logical_Router_Port lrp0 
>>>> options:redirect-chassis="hv2"
>>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port 
>>>> lrp0-rp \
>>>>     -    type=router options:router-port=lrp0 addresses="router"
>>>>     -# Add router port to ls1
>>>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>>>     <http://10.0.0.1/24>
>>>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port 
>>>> lrp1-rp \
>>>>     -    type=router options:router-port=lrp1 addresses="router"
>>>>     -# Add logical ports for NAT rules
>>>>     -ovn-nbctl lsp-add ls1 foo1 \
>>>>     --- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
>>>>     -ovn-nbctl lsp-add ls1 foo2 \
>>>>     --- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
>>>>     -# Add nat-addresses option
>>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="router"
>>>>     -# Add NAT rules
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24
>>>>     <http://10.0.0.0/24>])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3
>>>>     10.0.0.3 foo1 f0:00:00:00:00:03])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4
>>>>     10.0.0.4 foo2 f0:00:00:00:00:04])
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -# Initially test with no bridge-mapping on hv2, expect to receive
>>>>     no packets
>>>>     -
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -# Initially test with no bridge-mapping on hv3
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port
>>>>     network_name=physnet1])
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 2
>>>>     -
>>>>     -# Expect no packets when hv2 bridge-mapping is not present
>>>>     -: > packets
>>>>     -OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
>>>>     -
>>>>     -# Add bridge-mapping on hv2
>>>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -
>>>>     -# Wait until the patch ports are created in hv2 to connect br-int
>>>>     to br-phys
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
>>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>>     -
>>>>     -# Wait for packets to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" 
>>>>
>>>>     -echo $expected > expout
>>>> -expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002" 
>>>>
>>>>     -echo $expected >> expout
>>>>     -AT_CHECK([sort packets], [0], [expout])
>>>>     -sort packets | cat
>>>>     -
>>>>     -# Temporarily remove nat-addresses option to avoid race 
>>>> conditions
>>>>     -# due to GARP backoff
>>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 
>>>> nat-addresses=""
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>>     -
>>>>     -# Add OVS ports for foo1 and foo2 on hv3
>>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>>     -    set interface hv3-vif1 external-ids:iface-id=foo1 \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv3-vif2 -- \
>>>>     -    set interface hv3-vif2 external-ids:iface-id=foo2 \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -# Add bridge-mapping on hv3
>>>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -
>>>>     -# Wait until the patch ports are created in hv3 to connect br-int
>>>>     to br-phys
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
>>>>     -grep "Port patch-br-int-to-ln_port" | wc -l`])
>>>>     -
>>>>     -# Re-add nat-addresses option
>>>>     -ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="router"
>>>>     -
>>>>     -# Wait for packets to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros > packets
>>>> -garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003" 
>>>>
>>>>     -echo $garp_1 > expout
>>>> -garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004" 
>>>>
>>>>     -echo $garp_2 >> expout
>>>>     -
>>>>     -cat packets | grep $garp_1 | head -1 > exp
>>>>     -cat packets | grep $garp_2 | head -1 >> exp
>>>>     -AT_CHECK([cat exp], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# VLAN traffic for external network redirected through
>>>>     distributed router
>>>>     -# gateway port should use vlans(i.e input network vlan tag)
>>>>     across hypervisors
>>>>     -# instead of tunneling.
>>>>     -AT_SETUP([ovn -- vlan traffic for external network with
>>>>     distributed router gateway port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# # One LR R1 that has switches foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>) and
>>>>     -# # alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>>     it.  The logical port
>>>>     -# # between R1 and alice has a "redirect-chassis" specified,
>>>>     -# # i.e. it is the distributed router gateway port(172.16.1.6).
>>>>     -# # Switch alice also has a localnet port defined.
>>>>     -# # An additional switch outside has the same subnet as alice
>>>>     -# # (172.16.1.0/24 <http://172.16.1.0/24>), a localnet port and
>>>>     nexthop port(172.16.1.1)
>>>>     -# # which will receive the packet destined for external network
>>>>     -# # (i.e 8.8.8.8 as destination ip).
>>>>     -
>>>>     -# Physical network:
>>>>     -# # Four hypervisors hv[1234].
>>>>     -# # hv1 hosts vif foo1.
>>>>     -# # hv2 is the "redirect-chassis" that hosts the distributed
>>>>     router gateway port.
>>>>     -# # Later to test GARPs for the router port - foo, hv2 and hv4
>>>>     are added to the ha_chassis_group
>>>>     -# # hv3 hosts nexthop port vif outside1.
>>>>     -# # All other tests connect hypervisors to network n1 through
>>>>     br-phys for tunneling.
>>>>     -# # But in this test, hv1 won't connect to n1(and no br-phys in
>>>>     hv1), and
>>>>     -# # in order to show vlans(instead of tunneling) used between hv1
>>>>     and hv2,
>>>>     -# # a new network n2 created and hv1 and hv2 connected to this
>>>>     network through br-ex.
>>>>     -# # hv2 and hv3 are still connected to n1 network through 
>>>> br-phys.
>>>>     -net_add n1
>>>>     -
>>>>     -# We are not calling ovn_attach for hv1, to avoid adding br-phys.
>>>>     -# Tunneling won't work in hv1 as ovn-encap-ip is not added to any
>>>>     bridge in hv1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -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,vxlan \
>>>>     -    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
>>>>     -    -- add-br br-int \
>>>>     -    -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true \
>>>>     -    -- set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=public:br-ex
>>>>     -
>>>>     -start_daemon ovn-controller
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl set Open_vSwitch .
>>>> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>>>     -
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-int hv3-vif1 -- \
>>>>     -    set interface hv3-vif1 external-ids:iface-id=outside1 \
>>>>     -    options:tx_pcap=hv3/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv3/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings="phys:br-phys"
>>>>     -
>>>>     -sim_add hv4
>>>>     -as hv4
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.4
>>>>     -ovs-vsctl set Open_vSwitch .
>>>> external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
>>>>     -
>>>>     -# Create network n2 for vlan connectivity between hv1 and hv2
>>>>     -net_add n2
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-ex
>>>>     -net_attach n2 br-ex
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-ex
>>>>     -net_attach n2 br-ex
>>>>     -
>>>>     -as hv4
>>>>     -ovs-vsctl add-br br-ex
>>>>     -net_attach n2 br-ex
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect alice to R1 as distributed router gateway port
>>>>     (172.16.1.6) on hv2
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24
>>>>     <http://172.16.1.6/24> \
>>>>     -    -- set Logical_Router_Port alice 
>>>> options:redirect-chassis="hv2"
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router \
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port outside1 in outside, which is a nexthop 
>>>> address
>>>>     -# for 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     -ovn-nbctl lsp-add outside outside1 \
>>>>     --- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
>>>>     -
>>>>     -# Set default gateway (nexthop) to 172.16.1.1
>>>>     -ovn-nbctl lr-route-add R1 "0.0.0.0/0 <http://0.0.0.0/0>"
>>>>     172.16.1.1 alice
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24
>>>>     <http://192.168.1.1/24>])
>>>>     -ovn-nbctl set Logical_Switch_Port rp-alice
>>>>     options:nat-addresses=router
>>>>     -
>>>>     -ovn-nbctl lsp-add foo ln-foo
>>>>     -ovn-nbctl lsp-set-addresses ln-foo unknown
>>>>     -ovn-nbctl lsp-set-options ln-foo network_name=public
>>>>     -ovn-nbctl lsp-set-type ln-foo localnet
>>>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
>>>>     -
>>>>     -# Create localnet port in alice
>>>>     -ovn-nbctl lsp-add alice ln-alice
>>>>     -ovn-nbctl lsp-set-addresses ln-alice unknown
>>>>     -ovn-nbctl lsp-set-type ln-alice localnet
>>>>     -ovn-nbctl lsp-set-options ln-alice network_name=phys
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -# Check that there is a logical flow in logical switch foo's 
>>>> pipeline
>>>>     -# to set the outport to rp-foo (which is expected).
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>>>     ls_in_l2_lkup | \
>>>>     -grep rp-foo | grep -v is_chassis_resident | wc -l`])
>>>>     -
>>>>     -# Set the option 'reside-on-redirect-chassis' for foo
>>>>     -ovn-nbctl set logical_router_port foo
>>>>     options:reside-on-redirect-chassis=true
>>>>     -# Check that there is a logical flow in logical switch foo's 
>>>> pipeline
>>>>     -# to set the outport to rp-foo with the condition
>>>>     is_chassis_redirect.
>>>>     -ovn-sbctl dump-flows foo
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep
>>>>     ls_in_l2_lkup | \
>>>>     -grep rp-foo | grep is_chassis_resident | wc -l`])
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list nat
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list chassis
>>>>     -echo "---------------------"
>>>>     -
>>>>     -for chassis in hv1 hv2 hv3; do
>>>>     -    as $chassis
>>>>     -    echo "------ $chassis dump ----------"
>>>>     -    ovs-vsctl show br-int
>>>>     -    ovs-ofctl show br-int
>>>>     -    ovs-ofctl dump-flows br-int
>>>>     -    echo "--------------------------"
>>>>     -done
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -foo1_ip=$(ip_to_hex 192 168 1 2)
>>>>     -gw_ip=$(ip_to_hex 172 16 1 6)
>>>>     -dst_ip=$(ip_to_hex 8 8 8 8)
>>>>     -nexthop_ip=$(ip_to_hex 172 16 1 1)
>>>>     -
>>>>     -foo1_mac="f00000010203"
>>>>     -foo_mac="000001010203"
>>>>     -gw_mac="000002010203"
>>>>     -nexthop_mac="f00000010204"
>>>>     -
>>>>     -# Send ip packet from foo1 to 8.8.8.8
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000001010203"
>>>> -packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -# Wait for GARPs announcing gw IP to arrive
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
>>>>     -grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
>>>>     -    ])
>>>>     -
>>>>     -# VLAN tagged packet with router port(192.168.1.1) MAC as
>>>>     destination MAC
>>>>     -# is expected on bridge connecting hv1 and hv2
>>>> -expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo $expected > hv1-br-ex_n2.expected
>>>>     -
>>>>     -# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
>>>>     -# As connection tracking not enabled for this test, snat can't be
>>>>     done on the packet.
>>>>     -# We still see foo1 as the source ip address. But source
>>>>     mac(gateway MAC) and
>>>>     -# dest mac(nexthop mac) are properly configured.
>>>> -expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -echo $expected > hv3-vif1.expected
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
>>>>     -as hv3 reset_pcap_file hv3-vif1 hv3/vif1
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -sleep 2
>>>>     -
>>>>     -# On hv1, table 32 check that no packet goes via the tunnel port
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
>>>>     -| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -ip_packet() {
>>>>     -    grep "1010203f00000010203"
>>>>     -}
>>>>     -
>>>>     -# Check vlan tagged packet on the bridge connecting hv1 and hv2
>>>>     with the
>>>>     -# foo1's mac.
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
>>>>     -cat hv1-br-ex_n2.expected > expout
>>>>     -AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
>>>>     -
>>>>     -# Check expected packet on nexthop interface
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
>>>>     -cat hv3-vif1.expected > expout
>>>>     -AT_CHECK([sort hv3-vif1], [0], [expout])
>>>>     -
>>>>     -# Test the GARP for the router port ip - 192.168.1.1
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>>     -
>>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>>>     -
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
>>>>     -
>>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=hagrp1`
>>>>     -ovn-nbctl remove logical_router_port alice options 
>>>> redirect-chassis
>>>>     -ovn-nbctl --wait=sb set logical_router_port alice
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -# When hv2 claims the gw router port cr-alice, it should send out
>>>>     -# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
>>>>     -
>>>>     -# foo1 (on hv1) should receive GARP without VLAN tag
>>>> -exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101" 
>>>>
>>>>     -echo $exp_garp_on_foo1 > foo1.expout
>>>>     -
>>>>     -# ovn-controller on hv2 should send garp with VLAN tag
>>>> -sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101" 
>>>>
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>>>     -# Wait until we receive atleast 1 packet
>>>>     -OVS_WAIT_UNTIL([test 1=`$PYTHON
>>>>     "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-ex_n2-tx.pcap | wc -l`])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-ex_n2-tx.pcap | head -1 > packets
>>>>     -echo $sent_garp > expout
>>>>     -AT_CHECK([cat packets], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv4/br-ex_n2-tx.pcap > empty
>>>>     -AT_CHECK([cat empty], [0], [])
>>>>     -
>>>>     -# Make hv4 master
>>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
>>>>     -
>>>>     -# Wait till cr-alice is claimed by hv4
>>>>     -hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>>> name=hv4)
>>>>     -# check that the chassis redirect port has been claimed by the
>>>>     gw1 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -# Reset the pcap file for hv2/br-ex_n2. From now on
>>>>     ovn-controller in hv2
>>>>     -# should not send GARPs for the router ports.
>>>>     -as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
>>>>     -
>>>>     -echo $sent_garp > br-ex_n2.expout
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
>>>>     -OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
>>>>     -
>>>>     -sleep 2
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-ex_n2-tx.pcap > empty
>>>>     -AT_CHECK([cat empty], [0], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
>>>>     -AT_KEYWORDS([ovn-nd_ra])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# In this test case we create 1 lswitch with 3 VIF ports 
>>>> attached,
>>>>     -# and a lrouter connected to the lswitch.
>>>>     -# We generate the Router solicitation packet and verify the
>>>>     Router Advertisement
>>>>     -# reply packet from the ovn-controller.
>>>>     -
>>>>     -# Create hypervisor and logical switch lsw0, logical router lr0,
>>>>     attach lsw0
>>>>     -# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode
>>>>     column to
>>>>     -# 'slaac' to allow lrp0 send RA for SLAAC mode.
>>>>     -ovn-nbctl ls-add lsw0
>>>>     -ovn-nbctl lr-add lr0
>>>>     -ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
>>>>     -ovn-nbctl set Logical_Router_Port lrp0
>>>>     ipv6_ra_configs:address_mode="slaac"
>>>>     -ovn-nbctl \
>>>>     -    -- lsp-add lsw0 lsp0 \
>>>>     -    -- set Logical_Switch_Port lsp0 type=router \
>>>>     -                     options:router-port=lrp0 \
>>>>     -                     addresses='"fa:16:3e:00:00:01
>>>>     fdad:1234:5678::1"'
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12
>>>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>>>     -ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12
>>>>     fdad:1234:5678:0:f816:3eff:fe:2"
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp2
>>>>     -ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13
>>>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>>>     -ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13
>>>>     fdad:1234:5678:0:f816:3eff:fe:3"
>>>>     -
>>>>     -ovn-nbctl lsp-add lsw0 lp3
>>>>     -ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14
>>>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>>>     -ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14
>>>>     fdad:1234:5678:0:f816:3eff:fe:4"
>>>>     -
>>>>     -# Add ACL rule for ICMPv6 on lsw0
>>>>     -ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  
>>>> allow-related
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 &&
>>>>     icmp6'  allow-related
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 &&
>>>>     icmp6'  allow-related
>>>>     -ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 &&
>>>>     icmp6'  allow-related
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>>     -    set interface hv1-vif3 external-ids:iface-id=lp3 \
>>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>>     -    ofport-request=3
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -# Make sure that ovn-controller has installed the corresponding
>>>>     OF Flow.
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>>     -
>>>>     -# This shell function sends a Router Solicitation packet.
>>>>     -# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
>>>>     -test_ipv6_ra() {
>>>>     -    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5
>>>>     prefix_opt=$6
>>>>     -    local
>>>> request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac} 
>>>>
>>>>     -
>>>>     -    local len=24
>>>>     -    local mtu_opt=""
>>>>     -    if test $mtu != 0; then
>>>>     -        len=`expr $len + 8`
>>>>     -        mtu_opt=05010000${mtu}
>>>>     -    fi
>>>>     -
>>>>     -    if test ${#prefix_opt} != 0; then
>>>>     - prefix_opt=${prefix_opt}fdad1234567800000000000000000000
>>>>     -        len=`expr $len + ${#prefix_opt} / 2`
>>>>     -    fi
>>>>     -
>>>>     -    len=$(printf "%x" $len)
>>>>     -    local lrp_mac=fa163e000001
>>>>     -    local lrp_lla=fe80000000000000f8163efffe000001
>>>>     -    local
>>>> reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt} 
>>>>
>>>>     -    echo $reply >> $inport.expected
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} 
>>>> $request
>>>>     -}
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0.log])
>>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
>>>>     -
>>>>     -# MTU is not set and the address mode is set to slaac
>>>>     -addr_mode=00
>>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>>     -src_mac=fa163e000002
>>>>     -src_lla=fe80000000000000f8163efffe000002
>>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0
>>>>     $default_prefix_option_config
>>>>     -
>>>>     -# NXT_RESUME should be 1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap  > 1.packets
>>>>     -
>>>>     -cat 1.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum.
>>>>     -cat 1.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -rm -f *.expected
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>>     -
>>>>     -# Set the MTU to 1500
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>>     ipv6_ra_configs:mtu=1500
>>>>     -
>>>>     -# Make sure that ovn-controller has installed the corresponding
>>>>     OF Flow.
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>>     -
>>>>     -addr_mode=00
>>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>>     -src_mac=fa163e000003
>>>>     -src_lla=fe80000000000000f8163efffe000003
>>>>     -mtu=000005dc
>>>>     -
>>>>     -test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu
>>>>     $default_prefix_option_config
>>>>     -
>>>>     -# NXT_RESUME should be 2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap  > 2.packets
>>>>     -
>>>>     -cat 2.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum.
>>>>     -cat 2.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -rm -f *.expected
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>>     -
>>>>     -# Set the address mode to dhcpv6_stateful
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>>>     -# Make sure that ovn-controller has installed the corresponding
>>>>     OF Flow.
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>>     -
>>>>     -addr_mode=80
>>>> -default_prefix_option_config=03044080ffffffffffffffff00000000
>>>>     -src_mac=fa163e000004
>>>>     -src_lla=fe80000000000000f8163efffe000004
>>>>     -mtu=000005dc
>>>>     -
>>>>     -test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu
>>>>     $default_prefix_option_config
>>>>     -
>>>>     -# NXT_RESUME should be 3.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif3-tx.pcap  > 3.packets
>>>>     -
>>>>     -cat 3.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum.
>>>>     -cat 3.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -rm -f *.expected
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>>     -
>>>>     -# Set the address mode to dhcpv6_stateless
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>>>     -# Make sure that ovn-controller has installed the corresponding
>>>>     OF Flow.
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int |
>>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>>     -
>>>>     -addr_mode=40
>>>> -default_prefix_option_config=030440c0ffffffffffffffff00000000
>>>>     -src_mac=fa163e000002
>>>>     -src_lla=fe80000000000000f8163efffe000002
>>>>     -mtu=000005dc
>>>>     -
>>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>>>     $default_prefix_option_config
>>>>     -
>>>>     -# NXT_RESUME should be 4.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap  > 1.packets
>>>>     -
>>>>     -cat 1.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum.
>>>>     -cat 1.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -rm -f *.expected
>>>>     -reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -reset_pcap_file hv1-vif3 hv1/vif3
>>>>     -
>>>>     -# Set the address mode to invalid.
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port lrp0
>>>>     ipv6_ra_configs:address_mode=invalid
>>>>     -# Make sure that ovn-controller has not installed any OF Flow for
>>>>     IPv6 ND RA.
>>>>     -OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int |
>>>>     grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
>>>>     -
>>>>     -addr_mode=40
>>>>     -default_prefix_option_config=""
>>>>     -src_mac=fa163e000002
>>>>     -src_lla=fe80000000000000f8163efffe000002
>>>>     -mtu=000005dc
>>>>     -
>>>>     -test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu
>>>>     $default_prefix_option_config
>>>>     -
>>>>     -# NXT_RESUME should be 4 only.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif1-tx.pcap  > 1.packets
>>>>     -AT_CHECK([cat 1.packets], [0], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- /32 router IP address])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# 2 LS 'foo' and 'alice' connected via router R1.
>>>>     -# R1 connects to 'alice' with a /32 IP address. We use static
>>>>     routes and
>>>>     -# nexthop to push traffic to a logical port in switch 'alice'
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo
>>>>     type=router \
>>>>     -          options:router-port=foo addresses=\"00:00:00:01:02:03\"
>>>>     -
>>>>     -# Connect alice to R1.
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
>>>>     <http://172.16.1.1/32>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -          type=router options:router-port=alice
>>>>     addresses=\"00:00:00:01:02:04\"
>>>>     -
>>>>     -# Create logical port foo1 in foo
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical port alice1 in alice
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
>>>>     -
>>>>     -#install default route in R1 to use alice1's IP address as 
>>>> nexthop
>>>>     -ovn-nbctl lr-route-add R1 0.0.0.0/0 <http://0.0.0.0/0> 
>>>> 10.0.0.2 alice
>>>>     -
>>>>     -# Create two hypervisor and create OVS ports corresponding to
>>>>     logical ports.
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=foo1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=alice1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -
>>>>     -# 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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -# Send ip packets between foo1 and alice1
>>>>     -src_mac="f00000010203"
>>>>     -dst_mac="000000010203"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>>> -packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -
>>>>     -# Send the first packet to trigger a ARP response and 
>>>> population of
>>>>     -# mac_bindings table.
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" |
>>>>     wc -l` -gt 0])
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -# Packet to Expect at 'alice1'
>>>>     -src_mac="000000010204"
>>>>     -dst_mac="f00000010204"
>>>>     -src_ip=`ip_to_hex 192 168 1 2`
>>>>     -dst_ip=`ip_to_hex 10 0 0 2`
>>>>     -echo
>>>> "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" 
>>>>
>>>>     > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -# Add localport to the switch
>>>>     -ovn-nbctl lsp-add ls1 lp01
>>>>     -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
>>>>     -ovn-nbctl lsp-set-type lp01 localport
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -    ovs-vsctl add-port br-int vif01 -- \
>>>>     -        set Interface vif01 external-ids:iface-id=lp01 \
>>>>     - options:tx_pcap=hv${i}/vif01-tx.pcap \
>>>>     - options:rxq_pcap=hv${i}/vif01-rx.pcap \
>>>>     -                              ofport-request=${i}0
>>>>     -
>>>>     -    ovs-vsctl add-port br-int vif${i}1 -- \
>>>>     -        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
>>>>     - options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
>>>>     - options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
>>>>     -                              ofport-request=${i}1
>>>>     -
>>>>     -    ovn-nbctl lsp-add ls1 lp${i}1
>>>>     -    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
>>>>     -    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
>>>>     -
>>>>     -        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = 
>>>> xup])
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -ovn-sbctl dump-flows
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    echo hv${1%?}
>>>>     -}
>>>>     -#
>>>>     -# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). INPORT is
>>>>     specified as
>>>>     -# logical switch port numbers, e.g. 11 for vif11.
>>>>     -#
>>>>     -# EOUT is the end-to-end output port, that is, where the packet
>>>>     will end up
>>>>     -# after possibly bouncing through one or more localnet ports.
>>>>     LOUT is the
>>>>     -# logical output port, which might be a localnet port, as seen by
>>>>     ovn-trace
>>>>     -# (which doesn't know what localnet ports are connected to and
>>>>     therefore can't
>>>>     -# figure out the end-to-end answer).
>>>>     -#
>>>>     -# DEFHV is the default hypervisor from where the packet is going
>>>>     to be sent
>>>>     -# if the source port is a localport.
>>>>     -for i in 1 2; do
>>>>     -    for j in 0 1; do
>>>>     -        : > $i$j.expected
>>>>     -    done
>>>>     -done
>>>>     -test_packet() {
>>>>     -    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
>>>>     -    echo "$@"
>>>>     -
>>>>     -    # First try tracing the packet.
>>>>     -    uflow="inport==\"lp$inport\" && eth.dst==$dst &&
>>>>     eth.src==$src && eth.type==0x$eth"
>>>>     -    if test $lout != drop; then
>>>>     -        echo "output(\"$lout\");"
>>>>     -    fi > expout
>>>>     -    AT_CAPTURE_FILE([trace])
>>>>     -    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed
>>>>     '1,/Minimal trace/d'], [0], [expout])
>>>>     -
>>>>     -    # Then actually send a packet, for an end-to-end test.
>>>>     -    local packet=$(echo $dst$src | sed 's/://g')${eth}
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    # If hypervisor 0 (localport) use the defhv parameter
>>>>     -    if test $hv = hv0; then
>>>>     -        hv=$defhv
>>>>     -    fi
>>>>     -    vif=vif$inport
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $vif $packet
>>>>     -    if test $eout != drop; then
>>>>     -        echo $packet >> ${eout#lp}.expected
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -
>>>>     -# lp11 and lp21 are on different hypervisors
>>>>     -test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
>>>>     -test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
>>>>     -
>>>>     -# Both VIFs should be able to reach the localport on their own HV
>>>>     -test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
>>>>     -test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
>>>>     -
>>>>     -# Packet sent from localport on same hv should reach the vif
>>>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 
>>>> lp11 hv1
>>>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 
>>>> lp21 hv2
>>>>     -
>>>>     -# Packet sent from localport on different hv should be dropped
>>>>     -test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop 
>>>> lp21 hv1
>>>>     -test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop 
>>>> lp11 hv2
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2; do
>>>>     -    for j in 0 1; do
>>>>     -        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], 
>>>> [$i$j.expected])
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -# create gateways with external network connectivity
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    sim_add gw$i
>>>>     -    as gw$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -    ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl ls-add inside
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -# create hypervisors with a vif port each to an internal network
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.1$i
>>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>>     -        ofport-request=1
>>>>     -
>>>>     -        ovn-nbctl lsp-add inside inside$i \
>>>>     -            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i
>>>>     192.168.1.10$i"
>>>>     -
>>>>     -done
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -# Connect inside to R1
>>>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>>>     rp-inside \
>>>>     -    type=router options:router-port=inside \
>>>>     -    -- lsp-set-addresses rp-inside router
>>>>     -
>>>>     -# Connect outside to R1 as distributed router gateway port on 
>>>> gw1+gw2
>>>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>>>     <http://192.168.0.101/24>
>>>>     -
>>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>>>     -- \
>>>>     -          --id=@gc1 create Gateway_Chassis \
>>>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>>>     -- \
>>>>     -          set Logical_Router_Port outside
>>>>     'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>>>     rp-outside \
>>>>     -    type=router options:router-port=outside \
>>>>     -    -- lsp-set-addresses rp-outside router
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -echo "---------NB dump-----"
>>>>     -ovn-nbctl show
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router
>>>>     -echo "---------------------"
>>>>     -ovn-nbctl list logical_router_port
>>>>     -echo "---------------------"
>>>>     -
>>>>     -echo "---------SB dump-----"
>>>>     -ovn-sbctl list datapath_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list port_binding
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl dump-flows
>>>>     -echo "---------------------"
>>>>     -ovn-sbctl list chassis
>>>>     -ovn-sbctl list encap
>>>>     -echo "---------------------"
>>>>     -echo "------ Gateway_Chassis dump (SBDB) -------"
>>>>     -ovn-sbctl list Gateway_Chassis
>>>>     -echo "------ Port_Binding chassisredirect -------"
>>>>     -ovn-sbctl find Port_Binding type=chassisredirect
>>>>     -echo "-------------------------------------------"
>>>>     -
>>>>     -# There should be one ha_chassis_group with the name "outside"
>>>>     -ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
>>>>     -ha_chassis_group name="outside"`
>>>>     -
>>>>     -AT_CHECK([test $ha_chassi_grp_name = outside])
>>>>     -
>>>>     -# There should be 2 ha_chassis rows in SB DB.
>>>>     -AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
>>>>     -grep -v chassis-name | awk '{print $3}' \
>>>>     -| grep '-' | wc -l ], [0], [2
>>>>     -])
>>>>     -
>>>>     -ha_ch=`ovn-sbctl --bare --columns ha_chassis  find 
>>>> ha_chassis_group`
>>>>     -# Trim the spaces.
>>>>     -ha_ch=`echo $ha_ch | sed 's/ //g'`
>>>>     -
>>>>     -ha_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | 
>>>> sort`
>>>>     -do
>>>>     -    ha_ch_list="$ha_ch_list $i"
>>>>     -done
>>>>     -
>>>>     -# Trim the spaces.
>>>>     -ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
>>>>     -
>>>>     -AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
>>>>     -
>>>>     -for chassis in gw1 gw2 hv1 hv2; do
>>>>     -    as $chassis
>>>>     -    echo "------ $chassis dump ----------"
>>>>     -    ovs-ofctl show br-int
>>>>     -    ovs-ofctl dump-flows br-int
>>>>     -    echo "--------------------------"
>>>>     -done
>>>>     -bfd_dump() {
>>>>     -    for chassis in gw1 gw2 hv1 hv2; do
>>>>     -        as $chassis
>>>>     -        echo "------ $chassis dump (BFD)----"
>>>>     -        echo "BFD (from $chassis):"
>>>>     -        # dump BFD config and status to the other chassis
>>>>     -        for chassis2 in gw1 gw2 hv1 hv2; do
>>>>     -            if [[ "$chassis" != "$chassis2" ]]; then
>>>>     -                echo " -> $chassis2:"
>>>>     -                echo "   $(ovs-vsctl --bare --columns
>>>>     bfd,bfd_status find Interface name=ovn-$chassis2-0)"
>>>>     -            fi
>>>>     -        done
>>>>     -        echo "--------------------------"
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -bfd_dump
>>>>     -
>>>>     -hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>>>     Interface name=ovn-gw1-0)
>>>>     -hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find
>>>>     Interface name=ovn-gw2-0)
>>>>     -hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>>>     Interface name=ovn-gw1-0)
>>>>     -hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find
>>>>     Interface name=ovn-gw2-0)
>>>>     -
>>>>     -echo $hv1_gw1_ofport
>>>>     -echo $hv1_gw2_ofport
>>>>     -echo $hv2_gw1_ofport
>>>>     -echo $hv2_gw2_ofport
>>>>     -
>>>>     -echo "--- hv1 ---"
>>>>     -as hv1 ovs-ofctl dump-flows br-int table=32
>>>>     -
>>>>     -echo "--- hv2 ---"
>>>>     -as hv2 ovs-ofctl dump-flows br-int table=32
>>>>     -
>>>>     -gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>>> name=gw1)
>>>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>>> name=gw2)
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw1
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# make sure ARP responder flows for outside router port reside on
>>>>     gw1 too
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# check that the chassis redirect port has been claimed by the
>>>>     gw1 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="hv1"`
>>>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="hv2"`
>>>>     -
>>>>     -exp_ref_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>>     -do
>>>>     -    if test $i = $hv1_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    elif test $i = $hv2_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    fi
>>>>     -done
>>>>     -
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -
>>>>     -# at this point, we invert the priority of the gw chassis between
>>>>     gw1 and gw2
>>>>     -
>>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>>     -                    name=outside_gw1 chassis_name=gw1 priority=10
>>>>     -- \
>>>>     -          --id=@gc1 create Gateway_Chassis \
>>>>     -                    name=outside_gw2 chassis_name=gw2 priority=20
>>>>     -- \
>>>>     -          set Logical_Router_Port outside
>>>>     'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -
>>>>     -# XXX: Let the change propagate down to the ovn-controllers
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -# we make sure that the hypervisors noticed, and inverted the
>>>>     slave ports
>>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# check that the chassis redirect port has been reclaimed by the
>>>>     gw2 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from gw1 #########
>>>>     -as gw1
>>>>     -for chassis in gw2 hv1 hv2; do
>>>>     -    echo "checking gw1 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>>>     -as gw2
>>>>     -for chassis in gw1 hv1 hv2; do
>>>>     -    echo "checking gw2 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>>>     -as hv1
>>>>     -for chassis in gw1 gw2; do
>>>>     -    echo "checking hv1 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -# make sure BFD is not enabled to hv2, we don't need it
>>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-hv2-0],[0],
>>>>     -         [[
>>>>     -]])
>>>>     -
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>>>     -as hv2
>>>>     -for chassis in gw1 gw2; do
>>>>     -    echo "checking hv2 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -# make sure BFD is not enabled to hv1, we don't need it
>>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-hv1-0],[0],
>>>>     -         [[
>>>>     -]])
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw2 now
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# disconnect GW2 from the network, GW1 should take over
>>>>     -as gw2
>>>>     -port=${sandbox}_br-phys
>>>>     -as main ovs-vsctl del-port n1 $port
>>>>     -
>>>>     -bfd_dump
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw2 now
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# check that the chassis redirect port has been reclaimed by the
>>>>     gw1 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
>>>>     -as gw2
>>>>     -for chassis in gw1 hv1 hv2; do
>>>>     -    echo "checking gw2 -> $chassis"
>>>>     -    OVS_WAIT_UNTIL([
>>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0)
>>>>     -    test "$bfd_cfg" = "enable=true min_rx=2000"
>>>>     -])
>>>>     -done
>>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
>>>>     -for chassis in gw1 hv1 hv2; do
>>>>     -    echo "checking gw2 -> $chassis"
>>>>     -    OVS_WAIT_UNTIL([
>>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0)
>>>>     -    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
>>>>     -])
>>>>     -done
>>>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>>>     -ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
>>>>     -for chassis in gw1 hv1 hv2; do
>>>>     -    echo "checking gw2 -> $chassis"
>>>>     -    OVS_WAIT_UNTIL([
>>>>     -    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0)
>>>>     -    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
>>>>     -])
>>>>     -done
>>>>     -
>>>>     -# Delete the inside1 vif. The ref_chassis in ha_chassis_group
>>>>     shouldn't have
>>>>     -# reference to hv1.
>>>>     -as hv1 ovs-vsctl del-port hv1-vif1
>>>>     -
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$hv2_ch_uuid" = "$ref_ch_list"])
>>>>     -
>>>>     -# Delete the inside2 vif.
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -echo "Deleting hv2-vif1"
>>>>     -as hv2 ovs-vsctl del-port hv2-vif1
>>>>     -
>>>>     -# ref_chassis of ha_chassis_group should be empty
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     exp_ref_ch_list=""
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# Delete the Gateway_Chassis for lrp - outside
>>>>     -ovn-nbctl clear Logical_Router_Port outside gateway_chassis
>>>>     -
>>>>     -# There shoud be no ha_chassis_group rows in SB DB.
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc 
>>>> -l`])
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>>     -
>>>>     -ovn-nbctl remove NB_Global . options "bfd-min-rx"
>>>>     -ovn-nbctl remove NB_Global . options "bfd-min-tx"
>>>>     -ovn-nbctl remove NB_Global . options "bfd-mult"
>>>>     -
>>>>     -# Now test with HA chassis group instead of Gateway chassis in 
>>>> NB DB
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
>>>>     -
>>>>     -ovn-nbctl list ha_chassis_group
>>>>     -ovn-nbctl --bare --columns _uuid find ha_chassis_group 
>>>> name=hagrp1
>>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>>     ha_chassis_group name=hagrp1`
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
>>>>     -
>>>>     -# ovn-northd should not create HA chassis group and HA chassis 
>>>> rows
>>>>     -# unless the HA chassis group in OVN NB DB is associated to
>>>>     -# a logical router port.
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
>>>>     -
>>>>     -# Associate hagrp1 to outside logical router port
>>>>     -ovn-nbctl set Logical_Router_Port outside
>>>>     ha_chassis_group=$hagrp1_uuid
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
>>>>     -find ha_chassis_group | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep
>>>>     chassis | \
>>>>     -grep -v chassis-name | wc -l`])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw1
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# make sure ARP responder flows for outside router port reside on
>>>>     gw1 too
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
>>>>     -grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep
>>>>     arp_tpa=192.168.0.101 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# check that the chassis redirect port has been claimed by the
>>>>     gw1 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -# Re add the ovs ports.
>>>>     -for i in 1 2; do
>>>>     -    as hv$i
>>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>>     -        set interface hv$i-vif1 external-ids:iface-id=inside$i \
>>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>>     -        ofport-request=1
>>>>     -done
>>>>     -
>>>>     -hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="hv1"`
>>>>     -hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis
>>>>     name="hv2"`
>>>>     -
>>>>     -exp_ref_ch_list=''
>>>>     -for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
>>>>     -do
>>>>     -    if test $i = $hv1_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    elif test $i = $hv2_ch_uuid; then
>>>>     -        exp_ref_ch_list="${exp_ref_ch_list}$i"
>>>>     -    fi
>>>>     -done
>>>>     -
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find
>>>>     ha_chassis_group | sort`
>>>>     -     # Trim the spaces.
>>>>     -     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
>>>>     -     test "$exp_ref_ch_list" = "$ref_ch_list"])
>>>>     -
>>>>     -# Increase the priority of gw2
>>>>     -ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
>>>>     -grep active_backup | grep 
>>>> slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
>>>>     -| wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# check that the chassis redirect port has been reclaimed by the
>>>>     gw2 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from gw1 #########
>>>>     -as gw1
>>>>     -for chassis in gw2 hv1 hv2; do
>>>>     -    echo "checking gw1 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from gw2 ##########
>>>>     -as gw2
>>>>     -for chassis in gw1 hv1 hv2; do
>>>>     -    echo "checking gw2 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from hv1 ###########
>>>>     -as hv1
>>>>     -for chassis in gw1 gw2; do
>>>>     -    echo "checking hv1 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -# make sure BFD is not enabled to hv2, we don't need it
>>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-hv2-0],[0],
>>>>     -         [[
>>>>     -]])
>>>>     -
>>>>     -# check BFD enablement on tunnel ports from hv2 ##########
>>>>     -as hv2
>>>>     -for chassis in gw1 gw2; do
>>>>     -    echo "checking hv2 -> $chassis"
>>>>     -    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-$chassis-0],[0],
>>>>     -             [[enable=true
>>>>     -]])
>>>>     -done
>>>>     -# make sure BFD is not enabled to hv1, we don't need it
>>>>     -AT_CHECK([ovs-vsctl --bare --columns bfd find Interface
>>>>     name=ovn-hv1-0],[0],
>>>>     -         [[
>>>>     -]])
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw2 now
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# disconnect GW2 from the network, GW1 should take over
>>>>     -as gw2
>>>>     -port=${sandbox}_br-phys
>>>>     -as main ovs-vsctl del-port n1 $port
>>>>     -
>>>>     -bfd_dump
>>>>     -
>>>>     -# make sure that flows for handling the outside router port
>>>>     reside on gw2 now
>>>>     -OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[1
>>>>     -]])
>>>>     -OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
>>>>     -grep 00:00:02:01:02:04 | wc -l], [0], [[0
>>>>     -]])
>>>>     -
>>>>     -# check that the chassis redirect port has been reclaimed by the
>>>>     gw1 chassis
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find
>>>>     Port_Binding \
>>>>     -logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
>>>>     -]])
>>>>     -
>>>>     -OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA
>>>>     distributed router])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -ovn-nbctl ls-add ls0
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl create Logical_Router name=lr0
>>>>     -ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
>>>>     <http://192.168.0.100/24>
>>>>     -
>>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>>     -                    name=outside_gw1 chassis_name=hv2 priority=10
>>>>     -- \
>>>>     -          --id=@gc1 create Gateway_Chassis \
>>>>     -                    name=outside_gw2 chassis_name=hv3 
>>>> priority=1 -- \
>>>>     -          set Logical_Router_Port lrp0 
>>>> 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port 
>>>> lrp0-rp \
>>>>     -    type=router options:router-port=lrp0 addresses="router"
>>>>     -ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
>>>>     <http://10.0.0.1/24>
>>>>     -ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port 
>>>> lrp1-rp \
>>>>     -    type=router options:router-port=lrp1 addresses="router"
>>>>     -
>>>>     -# Add NAT rules
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24
>>>>     <http://10.0.0.0/24>])
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -AT_CHECK([ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface
>>>>     snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap
>>>>     options:rxq_pcap=hv1/snoopvif-rx.pcap])
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -
>>>>     -sim_add hv3
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch .
>>>>     external-ids:ovn-bridge-mappings=physnet1:br-phys])
>>>>     -
>>>>     -# Create a localnet port.
>>>>     -AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-options ln_port 
>>>> network_name=physnet1])
>>>>     -
>>>>     -# wait for earlier changes to take effect
>>>>     -AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>>     -# add nat-addresses option
>>>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="router"
>>>>     -
>>>>     -# Wait for packets to be received through hv2.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -only_broadcast_from_lrp1() {
>>>>     -    grep "fffffffffffff00000000001"
>>>>     -}
>>>>     -
>>>> -garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>>>
>>>>     -echo $garp > expout
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv1_snoop_tx
>>>>     -echo "packets on hv1-snoopvif:"
>>>>     -cat hv1_snoop_tx
>>>>     -AT_CHECK([sort hv1_snoop_tx], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv2_br_phys_tx
>>>>     -echo "packets on hv2 br-phys tx"
>>>>     -cat hv2_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv3_br_phys_tx
>>>>     -echo "packets on hv3 br-phys tx"
>>>>     -cat hv3_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
>>>>     -
>>>>     -
>>>>     -# at this point, we invert the priority of the gw chassis between
>>>>     hv2 and hv3
>>>>     -
>>>>     -ovn-nbctl --wait=hv \
>>>>     -          --id=@gc0 create Gateway_Chassis \
>>>>     -                    name=outside_gw1 chassis_name=hv2 
>>>> priority=1 -- \
>>>>     -          --id=@gc1 create Gateway_Chassis \
>>>>     -                    name=outside_gw2 chassis_name=hv3 priority=10
>>>>     -- \
>>>>     -          set Logical_Router_Port lrp0 
>>>> 'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -
>>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>>     -
>>>>     -# Wait for packets to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq >  hv1_snoopvif_tx
>>>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv3_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv2_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>>>     -
>>>>     -# change localnet port tag.
>>>>     -AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
>>>>     -
>>>>     -# wait for earlier changes to take effect
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int
>>>>     table=65 | \
>>>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>>>     -])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int
>>>>     table=65 | \
>>>>     -grep "actions=mod_vlan_vid:2014" | wc -l`
>>>>     -])
>>>>     -
>>>>     -# update nat-addresses option
>>>>     -ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
>>>>     -
>>>>     -#Wait until the Port_Binding.nat_addresses is cleared.
>>>>     -OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns
>>>>     nat_addresses find port_binding \
>>>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>>>     -
>>>>     -as hv1 reset_pcap_file snoopvif hv1/snoopvif
>>>>     -as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>>     -
>>>>     -ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0
>>>>     nat-addresses="router"
>>>>     -
>>>>     -#Wait until the Port_Binding.nat_addresses is set.
>>>>     -OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns
>>>>     nat_addresses find port_binding \
>>>>     -logical_port=lrp0-rp | grep is_chassis | wc -l`])
>>>>     -
>>>>     -# Wait for packets to be received.
>>>>     -OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>> -garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064" 
>>>>
>>>>     -echo $garp > expout
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq >  hv1_snoopvif_tx
>>>>     -AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv3_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 |
>>>>     uniq > hv2_br_phys_tx
>>>>     -AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't
>>>>     bounce the master])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -# create two gateways with external network connectivity
>>>>     -for i in 1 2; do
>>>>     -    sim_add gw$i
>>>>     -    as gw$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -    ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl ls-add inside
>>>>     -ovn-nbctl ls-add outside
>>>>     -
>>>>     -# create one hypervisors with a vif port the internal network
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=inside1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovn-nbctl lsp-add inside inside1 \
>>>>     -        -- lsp-set-addresses inside1 "f0:00:00:01:22:01
>>>>     192.168.1.101"
>>>>     -
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -
>>>>     -# Connect inside to R1
>>>>     -ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port
>>>>     rp-inside \
>>>>     -    type=router options:router-port=inside \
>>>>     -    -- lsp-set-addresses rp-inside router
>>>>     -
>>>>     -# Connect outside to R1 as distributed router gateway port on 
>>>> gw1+gw2
>>>>     -ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
>>>>     <http://192.168.0.101/24>
>>>>     -
>>>>     -ovn-nbctl --id=@gc0 create Gateway_Chassis \
>>>>     -                    name=outside_gw1 chassis_name=gw1 priority=20
>>>>     -- \
>>>>     -          --id=@gc1 create Gateway_Chassis \
>>>>     -                    name=outside_gw2 chassis_name=gw2 priority=10
>>>>     -- \
>>>>     -          set Logical_Router_Port outside
>>>>     'gateway_chassis=[@gc0,@gc1]'
>>>>     -
>>>>     -ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port
>>>>     rp-outside \
>>>>     -    type=router options:router-port=outside \
>>>>     -    -- lsp-set-addresses rp-outside router
>>>>     -
>>>>     -# Create localnet port in outside
>>>>     -ovn-nbctl lsp-add outside ln-outside
>>>>     -ovn-nbctl lsp-set-addresses ln-outside unknown
>>>>     -ovn-nbctl lsp-set-type ln-outside localnet
>>>>     -ovn-nbctl lsp-set-options ln-outside network_name=phys
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -# currently when ovn-controller is restarted, the old entry is
>>>>     deleted
>>>>     -# and a new one is created, which leaves the Gateway_Chassis with
>>>>     -# an empty chassis for a while. NOTE: restarting ovn-controller
>>>>     in tests
>>>>     -# doesn't have the same effect because "name" is conserved, 
>>>> and the
>>>>     -# Chassis entry is not replaced.
>>>>     -
>>>>     -> gw1/ovn-controller.log
>>>>     -
>>>>     -gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis 
>>>> name=gw2)
>>>>     -ovn-sbctl destroy Chassis $gw2_chassis
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport"
>>>>     gw1/ovn-controller.log`])
>>>>     -
>>>>     -OVN_CLEANUP([gw1],[gw2],[hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
>>>>     -AT_KEYWORDS([ovn-nd_ns for unknown mac])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add sw0_ip6
>>>>     -ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
>>>>     -ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
>>>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
>>>>     -"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
>>>>     -
>>>>     -ovn-nbctl lr-add lr0_ip6
>>>>     -ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01
>>>>     aef0:0:0:0:0:0:0:0/64
>>>>     -ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
>>>>     -ovn-nbctl lsp-set-type lrp0_ip6-attachment router
>>>>     -ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
>>>>     -ovn-nbctl lsp-set-options lrp0_ip6-attachment 
>>>> router-port=lrp0_ip6
>>>>     -ovn-nbctl set logical_router_port lrp0_ip6
>>>>     ipv6_ra_configs:address_mode=slaac
>>>>     -
>>>>     -ovn-nbctl ls-add public
>>>>     -ovn-nbctl lsp-add public ln-public
>>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>>>     -
>>>>     -ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
>>>>     -2001:db8:1:0:200:02ff:fe01:0204/64 \
>>>>     --- set Logical_Router_port ip6_public 
>>>> options:redirect-chassis="hv1"
>>>>     -
>>>>     -#install static route
>>>>     -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
>>>>     -ip_prefix="\:\:/0" 
>>>> nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
>>>>     --- add Logical_Router lr0_ip6 static_routes @lrt
>>>>     -
>>>>     -ovn-nbctl lsp-add public rp-ip6_public -- set 
>>>> Logical_Switch_Port \
>>>>     -rp-ip6_public  type=router options:router-port=ip6_public \
>>>>     --- lsp-set-addresses rp-ip6_public router
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = 
>>>> xup])
>>>>     -
>>>>     -# There should be 2 Neighbor Advertisement flows for the 
>>>> router port
>>>>     -# aef0:: ip address in logical switch pipeline with action
>>>>     nd_na_router.
>>>>     -AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
>>>>     -grep "nd_na_router" | wc -l], [0], [2
>>>>     -])
>>>>     -
>>>>     -# There should be 4 Neighbor Advertisement flows with action
>>>>     nd_na_router
>>>>     -# in the router pipeline for the router lr0_ip6.
>>>>     -AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
>>>>     -wc -l], [0], [4
>>>>     -])
>>>>     -
>>>>     -cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public |
>>>>     grep _uuid | cut -f2 -d ":"`
>>>>     -
>>>>     -# There is only one chassis.
>>>>     -chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d 
>>>> ":"`
>>>>     -OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding
>>>>     $cr_uuid chassis`])
>>>>     -
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for
>>>>     unknown MAC
>>>>     -# addresses. ovn-controller should generate an IPv6 NS request
>>>>     for IPv6
>>>>     -# packets whose MAC is unknown (in the ARP_REQUEST router
>>>>     pipeline stage.
>>>>     -# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -# This function sends ipv6 packet
>>>>     -test_ipv6() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
>>>>     -
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
>>>>     -    packet=${packet}8000000000000000
>>>>     -
>>>>     -    src_mac=000002010204
>>>>     -
>>>> expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip} 
>>>>
>>>>     - 
>>>> expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
>>>>     - expected_packet=${expected_packet}${nd_target}0101${src_mac}
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} 
>>>> $packet
>>>>     -    rm -f ipv6_ns.expected
>>>>     -    echo $expected_packet >> ipv6_ns.expected
>>>>     -}
>>>>     -
>>>>     -src_mac=506400000002
>>>>     -dst_mac=00000000af01
>>>>     -src_ip=aef0000000000000526400fffe000002
>>>>     -dst_ip=20010db800010000020002fffe010205
>>>>     -dst_mcast_mac=3333ff010205
>>>>     -mcast_node_ip=ff0200000000000000000001ff010205
>>>>     -nd_target=20010db800010000020002fffe010205
>>>>     -# Send an IPv6 packet. Generated IPv6 Neighbor solicitation 
>>>> packet
>>>>     -# should be received by the ports attached to br-phys.
>>>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>>>     -$mcast_node_ip $nd_target
>>>>     -
>>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>>>     " " -f1)])
>>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>>>     " -f1)])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-phys_n1-tx.pcap | \
>>>>     -trim_zeros > 1.packets
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-phys-tx.pcap | \
>>>>     -trim_zeros > 2.packets
>>>>     -
>>>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum
>>>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -# Now send a packet with destination ip other than
>>>>     -# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
>>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>>     -reset_pcap_file br-phys hv1/br-phys
>>>>     -
>>>>     -src_mac=506400000002
>>>>     -dst_mac=00000000af01
>>>>     -src_ip=aef0000000000000526400fffe000002
>>>>     -dst_ip=20020ab8000100000200020000020306
>>>>     -# multicast mac of the nexthop IP - 
>>>> 2001:db8:1:0:200:02ff:fe01:1305
>>>>     -dst_mcast_mac=3333ff011305
>>>>     -mcast_node_ip=ff0200000000000000000001ff011305
>>>>     -nd_target=20010db800010000020002fffe011305
>>>>     -test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
>>>>     -$mcast_node_ip $nd_target
>>>>     -
>>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d
>>>>     " " -f1)])
>>>>     -OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d "
>>>>     " -f1)])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-phys_n1-tx.pcap | \
>>>>     -trim_zeros > 1.packets
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-phys-tx.pcap | \
>>>>     -trim_zeros > 2.packets
>>>>     -
>>>>     -cat ipv6_ns.expected | cut -c -112 > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
>>>>     -AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -# Skipping the ICMPv6 checksum
>>>>     -cat ipv6_ns.expected | cut -c 117- > expout
>>>>     -AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
>>>>     -AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- options:requested-chassis for logical port])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -ovn-nbctl ls-add ls0
>>>>     -ovn-nbctl lsp-add ls0 lsp0
>>>>     -
>>>>     -# create two hypervisors, each with one vif port
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- \
>>>>     -set Interface hv1-vif0 ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.12
>>>>     -ovs-vsctl -- add-port br-int hv2-vif0 -- \
>>>>     -set Interface hv2-vif0 ofport-request=1
>>>>     -
>>>>     -# Allow only chassis hv1 to bind logical port lsp0.
>>>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -# Retrieve hv1 and hv2 chassis UUIDs from southbound database
>>>>     -ovn-sbctl wait-until chassis hv1
>>>>     -ovn-sbctl wait-until chassis hv2
>>>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis 
>>>> name=hv1)
>>>>     -hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis 
>>>> name=hv2)
>>>>     -
>>>>     -# (1) Chassis hv2 should not bind lsp0 when requested-chassis 
>>>> is hv1.
>>>>     -echo "verifying that hv2 does not bind lsp0 when hv2
>>>>     physical/logical mapping is added"
>>>>     -as hv2
>>>>     -ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0"
>>>>     hv2/ovn-controller.log)])
>>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding logical_port=lsp0) = x], [0], [])
>>>>     -
>>>>     -# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and
>>>>     OFTABLE_LOG_TO_PHY tables.
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [1], [])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     output], [1], [])
>>>>     -
>>>>     -# (3) Chassis hv1 should bind lsp0 when physical to logical
>>>>     mapping exists on hv1.
>>>>     -echo "verifying that hv1 binds lsp0 when hv1 physical/logical
>>>>     mapping is added"
>>>>     -as hv1
>>>>     -ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>>>     hv1/ovn-controller.log)])
>>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>>>     -
>>>>     -# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and
>>>>     OFTABLE_LOG_TO_PHY tables.
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [0], [ignore])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     actions=output:1], [0], [ignore])
>>>>     -
>>>>     -# (5) Chassis hv1 should release lsp0 binding and chassis hv2
>>>>     should bind lsp0 when
>>>>     -# the requested chassis for lsp0 is changed from hv1 to hv2.
>>>>     -echo "verifying that lsp0 binding moves when requested-chassis is
>>>>     changed"
>>>>     -
>>>>     -ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
>>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>>>     this chassis" hv1/ovn-controller.log)])
>>>>     -OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding logical_port=lsp0) = x"$hv2_uuid"])
>>>>     -
>>>>     -# (6) Chassis hv2 should add flows and hv1 should not.
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [0], [ignore])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     actions=output:1], [0], [ignore])
>>>>     -
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [1], [])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     output], [1], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- options:requested-chassis with hostname])
>>>>     -
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls0
>>>>     -ovn-nbctl lsp-add ls0 lsp0
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.11
>>>>     -ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0
>>>>     ofport-request=1
>>>>     -
>>>>     -ovn-sbctl wait-until chassis hv1
>>>>     -hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis
>>>>     name=hv1)
>>>>     -echo "hv1_hostname=${hv1_hostname}"
>>>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>>>     requested-chassis=${hv1_hostname}
>>>>     -as hv1 ovs-vsctl set interface hv1-vif0 
>>>> external-ids:iface-id=lsp0
>>>>     -
>>>>     -hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis 
>>>> name=hv1)
>>>>     -echo "hv1_uuid=${hv1_uuid}"
>>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0"
>>>>     hv1/ovn-controller.log)])
>>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [0], [ignore])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     actions=output:1], [0], [ignore])
>>>>     -
>>>>     -ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0
>>>>     requested-chassis=non-existant-chassis
>>>>     -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from
>>>>     this chassis" hv1/ovn-controller.log)])
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find
>>>>     port_binding logical_port=lsp0) = x], [0], [])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep
>>>>     in_port=1], [1], [])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep
>>>>     output], [1], [])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IPv6 periodic RA])
>>>>     -ovn_start
>>>>     -
>>>>     -# This test sets up two hypervisors.
>>>>     -# hv1 and hv2 run ovn-controllers, and
>>>>     -# each has a VIF connected to the same
>>>>     -# logical switch in OVN. The logical
>>>>     -# switch is connected to a logical
>>>>     -# router port that is configured to send
>>>>     -# periodic router advertisements.
>>>>     -#
>>>>     -# The reason for having two ovn-controller
>>>>     -# hypervisors is to ensure that the
>>>>     -# periodic RAs being sent by each ovn-controller
>>>>     -# are kept to their local hypervisors. If the
>>>>     -# packets are not kept local, then each port
>>>>     -# will receive too many RAs.
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -sim_add hv2
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -
>>>>     -ovn-nbctl lr-add ro
>>>>     -ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 
>>>> aef0:0:0:0:0:0:0:1/64
>>>>     -
>>>>     -ovn-nbctl ls-add sw
>>>>     -ovn-nbctl lsp-add sw sw-ro
>>>>     -ovn-nbctl lsp-set-type sw-ro router
>>>>     -ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
>>>>     -ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
>>>>     -ovn-nbctl lsp-add sw sw-p1
>>>>     -ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02
>>>>     aef0::200:ff:fe00:2"
>>>>     -ovn-nbctl lsp-add sw sw-p2
>>>>     -ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03
>>>>     aef0::200:ff:fe00:3"
>>>>     -
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:send_periodic=true
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:address_mode=slaac
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:max_interval=4
>>>>     -ovn-nbctl set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:min_interval=3
>>>>     -
>>>>     -for i in 1 2 ; do
>>>>     -    as hv$i
>>>>     -    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
>>>>     -        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
>>>>     -        options:tx_pcap=hv$i/vif1-tx.pcap \
>>>>     -        options:rxq_pcap=hv$i/vif1-rx.pcap \
>>>>     -        ofport-request=1
>>>>     -done
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -
>>>>     -}
>>>>     -
>>>>     -construct_expected_ra() {
>>>>     -    local src_mac=000000000001
>>>>     -    local dst_mac=333300000001
>>>>     -    local src_addr=fe80000000000000020000fffe000001
>>>>     -    local dst_addr=ff020000000000000000000000000001
>>>>     -
>>>>     -    local mtu=$1
>>>>     -    local ra_mo=$2
>>>>     -    local ra_prefix_la=$3
>>>>     -
>>>>     -    local slla=0101${src_mac}
>>>>     -    local mtu_opt=""
>>>>     -    if test $mtu != 0; then
>>>>     -        mtu_opt=05010000${mtu}
>>>>     -    fi
>>>>     -    shift 3
>>>>     -
>>>>     -    local prefix=""
>>>>     -    while [[ $# -gt 0 ]] ; do
>>>>     -        local size=$1
>>>>     -        local net=$2
>>>>     -
>>>> prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net} 
>>>>
>>>>     -        shift 2
>>>>     -    done
>>>>     -
>>>>     -    local 
>>>> ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
>>>>     -    local icmp=8600XXXX${ra}
>>>>     -
>>>>     -    local ip_len=$(expr ${#icmp} / 2)
>>>>     -    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
>>>>     -
>>>>     -    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
>>>>     -    local eth=${dst_mac}${src_mac}86dd${ip}
>>>>     -    local packet=${eth}
>>>>     -    echo $packet >> expected
>>>>     -}
>>>>     -
>>>>     -ra_test() {
>>>>     -    construct_expected_ra $@
>>>>     -
>>>>     -    for i in hv1 hv2 ; do
>>>>     -        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut
>>>>     -d " " -f1)])
>>>>     -
>>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" $i/vif1-tx.pcap > packets
>>>>     -
>>>>     -        cat expected | cut -c -112 > expout
>>>>     -        AT_CHECK([cat packets | cut -c -112], [0], [expout])
>>>>     -
>>>>     -        # Skip ICMPv6 checksum.
>>>>     -        cat expected | cut -c 117- > expout
>>>>     -        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
>>>>     -
>>>>     -        rm -f packets
>>>>     -        as $i reset_pcap_file $i-vif1 $i/vif1
>>>>     -    done
>>>>     -
>>>>     -    rm -f expected
>>>>     -}
>>>>     -
>>>>     -# Baseline test with no MTU
>>>>     -ra_test 0 00 c0 40 aef00000000000000000000000000000
>>>>     -
>>>>     -# Now make sure an MTU option makes it
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:mtu=1500
>>>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
>>>>     -
>>>>     -# Now test for multiple network prefixes
>>>>     -ovn-nbctl --wait=hv set Logical_Router_port ro-sw
>>>>     networks='aef0\:\:1/64 fd0f\:\:1/48'
>>>>     -ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30
>>>>     fd0f0000000000000000000000000000
>>>>     -
>>>>     -# Test a different address mode now
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:address_mode=dhcpv6_stateful
>>>>     -ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30
>>>>     fd0f0000000000000000000000000000
>>>>     -
>>>>     -# And the other address mode
>>>>     -ovn-nbctl --wait=hv set Logical_Router_Port ro-sw
>>>>     ipv6_ra_configs:address_mode=dhcpv6_stateless
>>>>     -ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30
>>>>     fd0f0000000000000000000000000000
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ACL reject rule test])
>>>>     -AT_KEYWORDS([acl-reject])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>>     IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv4 packet with
>>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
>>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>>     of the icmp destination
>>>>     -# unreachable frame generated from ACL rule hit
>>>>     -#
>>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>>     -# HV is a hypervisor number
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>>> digits
>>>>     -test_ip_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ipv4_dst=$6 ip_chksum=$7
>>>>     -    local exp_ip_chksum=$8 exp_icmp_chksum=$9
>>>>     -    shift 9
>>>>     -
>>>>     -    local ip_ttl=ff
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>>>
>>>>     -
>>>>     -    local reply_icmp_ttl=ff
>>>>     -    local icmp_type_code_response=0301
>>>>     -    local icmp_data=00000000
>>>>     -    local
>>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>>>
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>>     EXP_ICMP_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv6 packet with
>>>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
>>>>     -# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination
>>>>     unreachable frame generated from ACL rule hit
>>>>     -test_ipv6_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>>     ipv6_dst=$6 exp_icmp_chksum=$7
>>>>     -    shift 7
>>>>     -
>>>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>>>     -    local 
>>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
>>>>     -
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>>     IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>>>     EXP_TCP_RST_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an TCP syn segment with
>>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT,
>>>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>>>     checksums of the tcp reset segment generated from ACL rule hit
>>>>     -#
>>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>>     -# HV is an hypervisor number
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC and IPV4_DST are each 8 hex digits.
>>>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>>>     each 4 hex digits
>>>>     -test_tcp_syn_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ipv4_dst=$6 ip_chksum=$7
>>>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>>>     -    shift 12
>>>>     -
>>>>     -    local ip_ttl=ff
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>>
>>>>     -
>>>>     -    local tcp_rst_ttl=ff
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# Create hypervisors hv[123].
>>>>     -# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
>>>>     -# Add all of the vifs to a single logical switch sw0.
>>>>     -
>>>>     -net_add n1
>>>>     -ovn-nbctl ls-add sw0
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2 3; do
>>>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>>>     192.168.1.$i$j"
>>>>     -
>>>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>>>     -                set interface vif$i$j \
>>>>     -                external-ids:iface-id=sw0-p$i$j \
>>>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>>     -                ofport-request=$i$j
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -sleep 1
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    : > vif${i}1.expected
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl --log acl-add sw0 to-lport 1000 "outport ==
>>>>     \"sw0-p12\"" reject
>>>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>>>     \"sw0-p11\"" reject
>>>>     -ovn-nbctl --log acl-add sw0 from-lport 1000 "inport ==
>>>>     \"sw0-p21\"" reject
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>>>     -
>>>>     -test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168
>>>>     1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
>>>>     -test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168
>>>>     1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
>>>>     -test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168
>>>>     1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
>>>>     -
>>>>     -test_ipv6_packet 11 1 000000000011 000000000021
>>>>     fe80000000000000020001fffe000001 
>>>> fe80000000000000020001fffe000002 6183
>>>>     -
>>>>     -test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex
>>>>     192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 
>>>> 7d8d 4486
>>>>     -test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex
>>>>     192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 
>>>> 7d8d 4486
>>>>     -test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex
>>>>     192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 
>>>> 7d82 4486
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], 
>>>> [vif${i}1.expected])
>>>>     -done
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- Port Groups])
>>>>     -AT_KEYWORDS([ovnpg])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -#
>>>>     -# Three logical switches ls1, ls2, ls3.
>>>>     -# One logical router lr0 connected to ls[123],
>>>>     -# with nine subnets, three per logical switch:
>>>>     -#
>>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>>> <http://192.168.11.0/24>
>>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>>> <http://192.168.12.0/24>
>>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>>> <http://192.168.13.0/24>
>>>>     -#    ...
>>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>>> <http://192.168.33.0/24>
>>>>     -#
>>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>>     first two
>>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>>     -#
>>>>     -# This test will create two port groups and uses them in ACL.
>>>>     -
>>>>     -get_lsp_uuid () {
>>>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>>>     -}
>>>>     -
>>>>     -pg1_ports=
>>>>     -pg2_ports=
>>>>     -for i in 1 2 3; do
>>>>     -    ovn-nbctl ls-add ls$i
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            ovn-nbctl \
>>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>>>     -            if test $i != 3 && test $k == 1; then
>>>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>>>     -            fi
>>>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>>>     -            if test $i != 1 && test $k == 2; then
>>>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>>>     -            fi
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>>     192.168.$i$j.254/24
>>>>     -        ovn-nbctl \
>>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>>     type=router \
>>>>     -  options:router-port=lrp$i$j \
>>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>>>     -
>>>>     -# create ACLs on all lswitches to drop traffic from pg2 to pg1
>>>>     -ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src
>>>>     == $pg2_ip4' drop
>>>>     -ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src
>>>>     == $pg2_ip4' drop
>>>>     -ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src
>>>>     == $pg2_ip4' drop
>>>>     -
>>>>     -# Physical network:
>>>>     -#
>>>>     -# Three hypervisors hv[123].
>>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>>     lp?13 on hv3.
>>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>>     on hv3.
>>>>     -# lp?3[123] all on hv3.
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    case $1 in dnl (
>>>>     -        ?11) echo 1 ;; dnl (
>>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its
>>>>     logical router
>>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>>     -vif_to_lrp() {
>>>>     -    echo ${1%?}
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its 
>>>> logical
>>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>>     -vif_to_ls() {
>>>>     -    echo ${1%??}
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -done
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            hv=`vif_to_hv $i$j$k`
>>>>     -                as hv$hv ovs-vsctl \
>>>>     -                -- add-port br-int vif$i$j$k \
>>>>     -                -- set Interface vif$i$j$k \
>>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>>     -                    ofport-request=$i$j$k
>>>>     -        done
>>>>     -    done
>>>>     -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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a packet to be received on INPORT.
>>>>     The packet's
>>>>     -# content has Ethernet destination DST and source SRC (each
>>>>     exactly 12 hex
>>>>     -# digits) and Ethernet type ETHTYPE (4 hex digits). The OUTPORTs
>>>>     (zero or
>>>>     -# more) list the VIFs on which the packet should be received.
>>>>     INPORT and the
>>>>     -# OUTPORTs are specified as logical switch port numbers, e.g. 123
>>>>     for vif123.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            : > $i$j$k.expected
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    in_ls=`vif_to_ls $inport`
>>>>     -    in_lrp=`vif_to_lrp $inport`
>>>>     -    for outport; do
>>>>     -        out_ls=`vif_to_ls $outport`
>>>>     -        if test $in_ls = $out_ls; then
>>>>     -            # Ports on the same logical switch receive exactly
>>>>     the same packet.
>>>>     -            echo $packet
>>>>     -        else
>>>>     -            # Routing decrements TTL and updates source and 
>>>> dest MAC
>>>>     -            # (and checksum).
>>>>     -            out_lrp=`vif_to_lrp $outport`
>>>>     -            echo
>>>> f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -        fi >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>>     -as hv1 ovn-sbctl list port_binding
>>>>     -as hv1 ovn-sbctl list datapath_binding
>>>>     -as hv1 ovn-sbctl list port_group
>>>>     -as hv1 ovn-sbctl list address_set
>>>>     -as hv1 ovn-sbctl dump-flows
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Send IP packets between all pairs of source and destination 
>>>> ports,
>>>>     -# packets matches ACL (pg2 to pg1) should be dropped
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -for is in 1 2 3; do
>>>>     -  for js in 1 2 3; do
>>>>     -    for ks in 1 2 3; do
>>>>     -      bcast=
>>>>     -      s=$is$js$ks
>>>>     -      smac=f00000000$s
>>>>     -      sip=`ip_to_hex 192 168 $is$js $ks`
>>>>     -      for id in 1 2 3; do
>>>>     -          for jd in 1 2 3; do
>>>>     -              for kd in 1 2 3; do
>>>>     -                d=$id$jd$kd
>>>>     -                dip=`ip_to_hex 192 168 $id$jd $kd`
>>>>     -                if test $is = $id; then dmac=f00000000$d; else
>>>>     dmac=00000000ff$is$js; fi
>>>>     -                if test $d != $s; then unicast=$d; else 
>>>> unicast=; fi
>>>>     -
>>>>     -                # packets matches ACL should be dropped
>>>>     -                if test $id != 3 && test $kd == 1; then
>>>>     -                    if test $is != 1 && test $ks == 2; then
>>>>     -                        unicast=
>>>>     -                    fi
>>>>     -                fi
>>>>     -                test_ip $s $smac $dmac $sip $dip $unicast #1
>>>>     -              done
>>>>     -          done
>>>>     -        done
>>>>     -      done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -# Allow some time for packet forwarding.
>>>>     -# XXX This can be improved.
>>>>     -sleep 1
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>>     -                              [$i$j$k.expected])
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ACLs on Port Groups])
>>>>     -AT_KEYWORDS([ovnpg_acl])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -#
>>>>     -# Three logical switches ls1, ls2, ls3.
>>>>     -# One logical router lr0 connected to ls[123],
>>>>     -# with nine subnets, three per logical switch:
>>>>     -#
>>>>     -#    lrp11 on ls1 for subnet 192.168.11.0/24 
>>>> <http://192.168.11.0/24>
>>>>     -#    lrp12 on ls1 for subnet 192.168.12.0/24 
>>>> <http://192.168.12.0/24>
>>>>     -#    lrp13 on ls1 for subnet 192.168.13.0/24 
>>>> <http://192.168.13.0/24>
>>>>     -#    ...
>>>>     -#    lrp33 on ls3 for subnet 192.168.33.0/24 
>>>> <http://192.168.33.0/24>
>>>>     -#
>>>>     -# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the
>>>>     first two
>>>>     -# digits are the subnet and the last digit distinguishes the VIF.
>>>>     -#
>>>>     -# This test will create two port groups and ACLs will be applied
>>>>     on them.
>>>>     -
>>>>     -get_lsp_uuid () {
>>>>     -    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
>>>>     -}
>>>>     -
>>>>     -pg1_ports=
>>>>     -pg2_ports=
>>>>     -for i in 1 2 3; do
>>>>     -    ovn-nbctl ls-add ls$i
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            ovn-nbctl \
>>>>     -                -- lsp-add ls$i lp$i$j$k \
>>>>     -                -- lsp-set-addresses lp$i$j$k \
>>>>     -                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
>>>>     -            # logical ports lp[12]?1 belongs to port group pg1
>>>>     -            if test $i != 3 && test $k == 1; then
>>>>     -                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
>>>>     -            fi
>>>>     -            # logical ports lp[23]?2 belongs to port group pg2
>>>>     -            if test $i != 1 && test $k == 2; then
>>>>     -                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
>>>>     -            fi
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j
>>>>     192.168.$i$j.254/24
>>>>     -        ovn-nbctl \
>>>>     -            -- lsp-add ls$i lrp$i$j-attachment \
>>>>     -            -- set Logical_Switch_Port lrp$i$j-attachment
>>>>     type=router \
>>>>     -  options:router-port=lrp$i$j \
>>>>     -  addresses='"00:00:00:00:ff:'$i$j'"'
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
>>>>     -ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
>>>>     -
>>>>     -# create ACLs on pg1 to drop traffic from pg2 to pg1
>>>>     -ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
>>>>     -ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
>>>>     -        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
>>>>     -
>>>>     -# Physical network:
>>>>     -#
>>>>     -# Three hypervisors hv[123].
>>>>     -# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2,
>>>>     lp?13 on hv3.
>>>>     -# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23
>>>>     on hv3.
>>>>     -# lp?3[123] all on hv3.
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of the 
>>>> hypervisor
>>>>     -# on which it is located.
>>>>     -vif_to_hv() {
>>>>     -    case $1 in dnl (
>>>>     -        ?11) echo 1 ;; dnl (
>>>>     -        ?12 | ?21 | ?22) echo 2 ;; dnl (
>>>>     -        ?13 | ?23 | ?3?) echo 3 ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its
>>>>     logical router
>>>>     -# port, e.g. "vif_to_lrp 123" yields 12.
>>>>     -vif_to_lrp() {
>>>>     -    echo ${1%?}
>>>>     -}
>>>>     -
>>>>     -# Given the name of a logical port, prints the name of its 
>>>> logical
>>>>     -# switch, e.g. "vif_to_ls 123" yields 1.
>>>>     -vif_to_ls() {
>>>>     -    echo ${1%??}
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2 3; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -done
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            hv=`vif_to_hv $i$j$k`
>>>>     -                as hv$hv ovs-vsctl \
>>>>     -                -- add-port br-int vif$i$j$k \
>>>>     -                -- set Interface vif$i$j$k \
>>>>     -                    external-ids:iface-id=lp$i$j$k \
>>>>     - options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
>>>>     - options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
>>>>     -                    ofport-request=$i$j$k
>>>>     -        done
>>>>     -    done
>>>>     -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
>>>>     -
>>>>     -# Allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -# XXX This should be more systematic.
>>>>     -sleep 1
>>>>     -
>>>>     -lsp_to_mac() {
>>>>     -    echo f0:00:00:00:0${1:0:1}:${1:1:2}
>>>>     -}
>>>>     -
>>>>     -lrp_to_mac() {
>>>>     -    echo 00:00:00:00:ff:$1
>>>>     -}
>>>>     -
>>>>     -# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE 
>>>> OUTPORT...
>>>>     -#
>>>>     -# This shell function causes a ICMP packet to be received on 
>>>> INPORT.
>>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>>     should
>>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>>     switch
>>>>     -# port numbers, e.g. 123 for vif123.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            : > $i$j$k.expected
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -test_icmp() {
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     icmp_type=$6
>>>>     -    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
>>>>     -                  eth.dst==$dst_mac && ip.ttl==64 && 
>>>> ip4.src==$src_ip
>>>>     -                  && ip4.dst==$dst_ip && 
>>>> icmp4.type==$icmp_type &&
>>>>     -                  icmp4.code==0"
>>>>     -    shift; shift; shift; shift; shift; shift
>>>>     -    hv=hv`vif_to_hv $inport`
>>>>     -    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -    in_ls=`vif_to_ls $inport`
>>>>     -    in_lrp=`vif_to_lrp $inport`
>>>>     -    for outport; do
>>>>     -        out_ls=`vif_to_ls $outport`
>>>>     -        if test $in_ls = $out_ls; then
>>>>     -            # Ports on the same logical switch receive exactly
>>>>     the same packet.
>>>>     -            echo $packet | ovstest test-ovn expr-to-packets
>>>>     -        else
>>>>     -            # Routing decrements TTL and updates source and 
>>>> dest MAC
>>>>     -            # (and checksum).
>>>>     -            out_lrp=`vif_to_lrp $outport`
>>>>     -            exp_smac=`lrp_to_mac $out_lrp`
>>>>     -            exp_dmac=`lsp_to_mac $outport`
>>>>     -            exp_packet="eth.src==$exp_smac && 
>>>> eth.dst==$exp_dmac &&
>>>>     -                ip.ttl==63 && ip4.src==$src_ip && 
>>>> ip4.dst==$dst_ip &&
>>>>     -                icmp4.type==$icmp_type && icmp4.code==0"
>>>>     -            echo $exp_packet | ovstest test-ovn expr-to-packets
>>>>     -
>>>>     -        fi >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -as hv1 ovs-vsctl --columns=name,ofport list interface
>>>>     -as hv1 ovn-sbctl list port_binding
>>>>     -as hv1 ovn-sbctl list datapath_binding
>>>>     -as hv1 ovn-sbctl list port_group
>>>>     -as hv1 ovn-sbctl list address_set
>>>>     -as hv1 ovn-sbctl dump-flows
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Send IP packets between all pairs of source and destination 
>>>> ports,
>>>>     -# packets matches ACL1 but not ACL2 should be dropped
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -for is in 1 2 3; do
>>>>     -  for js in 1 2 3; do
>>>>     -    for ks in 1 2 3; do
>>>>     -      bcast=
>>>>     -      s=$is$js$ks
>>>>     -      slsp_mac=`lsp_to_mac $s`
>>>>     -      slrp_mac=`lrp_to_mac $is$js`
>>>>     -      sip=192.168.$is$js.$ks
>>>>     -      for id in 1 2 3; do
>>>>     -          for jd in 1 2 3; do
>>>>     -              for kd in 1 2 3; do
>>>>     -                d=$id$jd$kd
>>>>     -                dlsp_mac=`lsp_to_mac $d`
>>>>     -                dlrp_mac=`lrp_to_mac $id$jd`
>>>>     -                dip=192.168.$id$jd.$kd
>>>>     -                if test $is = $id; then dmac=$dlsp_mac; else
>>>>     dmac=$slrp_mac; fi
>>>>     -                if test $d != $s; then unicast=$d; else 
>>>> unicast=; fi
>>>>     -
>>>>     -                # packets matches ACL1 but not ACL2 should be 
>>>> dropped
>>>>     -                if test $id != 3 && test $kd == 1; then
>>>>     -                    if test $is == 1 || test $ks != 2; then
>>>>     -                        unicast=
>>>>     -                    fi
>>>>     -                fi
>>>>     -                # icmp request (type = 8)
>>>>     -                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
>>>>     -
>>>>     -                # if packets are not dropped, test the return
>>>>     traffic (icmp echo)
>>>>     -                # to make sure stateful works, too.
>>>>     -                if test x$unicast != x; then
>>>>     -                    if test $is = $id; then dmac=$slsp_mac; else
>>>>     dmac=$dlrp_mac; fi
>>>>     -                    # icmp echo (type = 0)
>>>>     -                    test_icmp $unicast $dlsp_mac $dmac $dip 
>>>> $sip 0 $s
>>>>     -                fi
>>>>     -              done
>>>>     -          done
>>>>     -        done
>>>>     -      done
>>>>     -  done
>>>>     -done
>>>>     -
>>>>     -# Allow some time for packet forwarding.
>>>>     -# XXX This can be improved.
>>>>     -sleep 1
>>>>     -
>>>>     -# Now check the packets actually received against the ones 
>>>> expected.
>>>>     -for i in 1 2 3; do
>>>>     -    for j in 1 2 3; do
>>>>     -        for k in 1 2 3; do
>>>>     -            OVN_CHECK_PACKETS([hv`vif_to_hv
>>>>     $i$j$k`/vif$i$j$k-tx.pcap],
>>>>     -                              [$i$j$k.expected])
>>>>     -        done
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (static
>>>>     addressing)])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 lp1
>>>>     -ovn-nbctl lsp-add ls1 lp2
>>>>     -ovn-nbctl lsp-add ls1 lp3
>>>>     -
>>>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1
>>>>     2001:db8::1"
>>>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2
>>>>     2001:db8::2"
>>>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3
>>>>     2001:db8::3"
>>>>     -
>>>>     -ovn-nbctl create Port_Group name=pg1
>>>>     -ovn-nbctl create Port_Group name=pg2
>>>>     -
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>>>     pg1 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>>     pg1 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>>     pg2 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>>>     pg2 ports @p
>>>>     -
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -
>>>>     -dnl Check if port group address sets were populated with ports'
>>>>     addresses
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>>     -         [0], [[["10.0.0.1", "10.0.0.2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>>>     -         [0], [[["10.0.0.2", "10.0.0.3"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>>     -         [0], [[["2001:db8::1", "2001:db8::2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>>>     -         [0], [[["2001:db8::2", "2001:db8::3"]]
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses lp1 \
>>>>     -    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
>>>>     -
>>>>     -dnl Check if updated address got propagated to the port group
>>>>     address sets
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>>     -         [0], [[["10.0.0.11", "10.0.0.2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>>     -         [0], [[["2001:db8::11", "2001:db8::2"]]
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic
>>>>     addressing)])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl ls-add ls2
>>>>     -ovn-nbctl ls-add ls3
>>>>     -
>>>>     -ovn-nbctl set Logical_Switch ls1 \
>>>>     -    other_config:subnet=10.1.0.0/24 <http://10.1.0.0/24>
>>>>     other_config:ipv6_prefix="2001:db8:1::"
>>>>     -ovn-nbctl set Logical_Switch ls2 \
>>>>     -    other_config:subnet=10.2.0.0/24 <http://10.2.0.0/24>
>>>>     other_config:ipv6_prefix="2001:db8:2::"
>>>>     -ovn-nbctl set Logical_Switch ls3 \
>>>>     -    other_config:subnet=10.3.0.0/24 <http://10.3.0.0/24>
>>>>     other_config:ipv6_prefix="2001:db8:3::"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 lp1
>>>>     -ovn-nbctl lsp-add ls2 lp2
>>>>     -ovn-nbctl lsp-add ls3 lp3
>>>>     -
>>>>     -ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
>>>>     -ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
>>>>     -ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
>>>>     -
>>>>     -ovn-nbctl create Port_Group name=pg1
>>>>     -ovn-nbctl create Port_Group name=pg2
>>>>     -
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group
>>>>     pg1 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>>     pg1 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group
>>>>     pg2 ports @p
>>>>     -ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group
>>>>     pg2 ports @p
>>>>     -
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -
>>>>     -dnl Check if port group address sets were populated with ports'
>>>>     addresses
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>>     -         [0], [[["10.1.0.2", "10.2.0.2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
>>>>     -         [0], [[["10.2.0.2", "10.3.0.2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>>     -         [0], [[["2001:db8:1::ff:fe00:1", 
>>>> "2001:db8:2::ff:fe00:2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
>>>>     -         [0], [[["2001:db8:2::ff:fe00:2", 
>>>> "2001:db8:3::ff:fe00:3"]]
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb set Logical_Switch ls1 \
>>>>     -    other_config:subnet=10.11.0.0/24 <http://10.11.0.0/24>
>>>>     other_config:ipv6_prefix="2001:db8:11::"
>>>>     -
>>>>     -dnl Check if updated address got propagated to the port group
>>>>     address sets
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
>>>>     -         [0], [[["10.11.0.2", "10.2.0.2"]]
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
>>>>     -         [0], [[["2001:db8:11::ff:fe00:1", 
>>>> "2001:db8:2::ff:fe00:2"]]
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ACL conjunction])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 
>>>> 10.0.0.4"
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp2 \
>>>>     --- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
>>>>     -
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 
>>>> 10.0.0.6"
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -
>>>>     -ovn-nbctl create Address_Set name=set1 \
>>>>     -addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
>>>>     -ovn-nbctl create Address_Set name=set2 \
>>>>     -addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
>>>>     -ovn-nbctl acl-add ls1 to-lport 1002 \
>>>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
>>>>     -ovn-nbctl acl-add ls1 to-lport 1001 \
>>>>     -'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
>>>>     -
>>>>     -# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>>>>     -#
>>>>     -# This shell function causes an ip packet to be received on 
>>>> INPORT.
>>>>     -# The packet's content has Ethernet destination DST and source 
>>>> SRC
>>>>     -# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex
>>>>     digits).
>>>>     -# The OUTPORTs (zero or more) list the VIFs on which the packet
>>>>     should
>>>>     -# be received.  INPORT and the OUTPORTs are specified as logical
>>>>     switch
>>>>     -# port numbers, e.g. 11 for vif11.
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
>>>>     -${dst_ip}0035111100080000
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -    for outport; do
>>>>     -        echo $packet >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -
>>>>     -sip=`ip_to_hex 10 0 0 4`
>>>>     -dip=`ip_to_hex 10 0 0 6`
>>>>     -
>>>>     -test_ip 1 f00000000001 f00000000002 $sip $dip 2
>>>>     -
>>>>     -cat 2.expected > expout
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [expout])
>>>>     -
>>>>     -# There should be total of 12 flows present with conjunction
>>>>     action and 2 flows
>>>>     -# with conj match. Eg.
>>>>     -# table=44, priority=2002,conj_id=2,metadata=0x1
>>>>     actions=resubmit(,45)
>>>>     -# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
>>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6
>>>>     actions=conjunction(2,2/2)
>>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4
>>>>     actions=conjunction(2,2/2)
>>>>     -# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5
>>>>     actions=conjunction(2,2/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7
>>>>     actions=conjunction(3,2/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9
>>>>     actions=conjunction(3,2/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8
>>>>     actions=conjunction(3,2/2)
>>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6
>>>>     actions=conjunction(2,1/2)
>>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4
>>>>     actions=conjunction(2,1/2)
>>>>     -# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5
>>>>     actions=conjunction(2,1/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6
>>>>     actions=conjunction(3,1/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4
>>>>     actions=conjunction(3,1/2)
>>>>     -# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5
>>>>     actions=conjunction(3,1/2)
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
>>>>     -grep conjunction | wc -l`])
>>>>     -OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
>>>>     -grep conj_id | wc -l`])
>>>>     -
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -# Set the ip address for ls1-lp2 from set2 so that the drop ACL
>>>>     flow is hit.
>>>>     -ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7
>>>>     20.0.0.4"
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02
>>>>     10.0.0.7 20.0.0.4"
>>>>     -
>>>>     -reset_pcap_file hv1-vif2 hv1/vif2
>>>>     -
>>>>     -rm -f 2.packets
>>>>     -
>>>>     -sip=`ip_to_hex 10 0 0 4`
>>>>     -dip=`ip_to_hex 10 0 0 7`
>>>>     -
>>>>     -test_ip 1 f00000000001 f00000000002 $sip $dip
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/vif2-tx.pcap > 2.packets
>>>>     -AT_CHECK([cat 2.packets], [0], [])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- TTL exceeded])
>>>>     -AT_KEYWORDS([ttl-exceeded])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>>>>     IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv4 packet with
>>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified
>>>>     and TTL set to 1.
>>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>>     of the icmp time exceeded frame
>>>>     -# generated by OVN logical router
>>>>     -#
>>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>>     -# HV is a hypervisor number
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
>>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>>> digits
>>>>     -test_ip_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ipv4_dst=$6 ip_router=$7 ip_chksum=$8
>>>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
>>>>     -    shift 10
>>>>     -
>>>>     -    local ip_ttl=01
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst} 
>>>>
>>>>     -
>>>>     -    local reply_icmp_ttl=fe
>>>>     -    local icmp_type_code_response=0b00
>>>>     -    local icmp_data=00000000
>>>>     -    local
>>>> reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data} 
>>>>
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>>>     IPV6_ROUTER EXP_ICMP_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv6
>>>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as 
>>>> specified.
>>>>     -# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum
>>>>     of the icmpv6 ttl exceeded
>>>>     -# packet sent by OVN logical router
>>>>     -test_ip6_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>>>     -    shift 8
>>>>     -
>>>>     -    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a 
>>>>
>>>>     -
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    net_add n$i
>>>>     -    ovn-nbctl ls-add sw$i
>>>>     -
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>>>     -
>>>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>>>     192.168.$i.1 2001:db8:$i::11"
>>>>     -
>>>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>>>     -        set interface vif$i \
>>>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>>>     -            ofport-request=$i
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2; do
>>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>>>     192.168.$i.254/24 2001:db8:$i::1/64
>>>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>>>     type=router \
>>>>     -                options:router-port=lrp$i
>>>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 
>>>> 2001:db8:'$i'::1"'
>>>>     -done
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>>     1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae
>>>>     f4ff
>>>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>>>     20010db8000100000000000000000011 20010db8000200000000000000000011
>>>>     20010db8000100000000000000000001 d461
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- router port unreachable])
>>>>     -AT_KEYWORDS([router-port-unreachable])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER
>>>>     L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv4 packet with
>>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM
>>>>     as specified.
>>>>     -# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums
>>>>     of the icmp frame generated by OVN logical router
>>>>     -# EXP_ICMP_CODE are code and type of the icmp frame generated by
>>>>     OVN logical router
>>>>     -#
>>>>     -# INPORT is a lport number, e.g. 11 for vif11.
>>>>     -# HV is a hypervisor number
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>>>     -# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex 
>>>> digits
>>>>     -test_ip_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ip_router=$6 l4_proto=$7 ip_chksum=$8
>>>>     -    local exp_ip_chksum=$9 exp_icmp_chksum=${10} 
>>>> exp_icmp_code=${11}
>>>>     -    shift 11
>>>>     -
>>>>     -    local ip_ttl=ff
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router} 
>>>>
>>>>     -
>>>>     -    local reply_icmp_ttl=fe
>>>>     -    local icmp_data=00000000
>>>>     -    local
>>>> reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC
>>>>     IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM
>>>>     EXP_TCP_RST_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an TCP syn segment with
>>>>     -# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT,
>>>>     TCP_DPORT, TCP_CHKSUM  as specified.
>>>>     -# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp
>>>>     checksums of the tcp reset segment generated by OVN logical router
>>>>     -#
>>>>     -# INPORT is an lport number, e.g. 11 for vif11.
>>>>     -# HV is an hypervisor number
>>>>     -# ETH_SRC and ETH_DST are each 12 hex digits.
>>>>     -# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
>>>>     -# TCP_SPORT and TCP_DPORT are 4 hex digits.
>>>>     -# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are
>>>>     each 4 hex digits
>>>>     -test_tcp_syn_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ip_router=$6 ip_chksum=$7
>>>>     -    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
>>>>     -    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
>>>>     -    shift 12
>>>>     -
>>>>     -    local ip_ttl=ff
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>>
>>>>     -
>>>>     -    local tcp_rst_ttl=fe
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>>>>     TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is a TCP syn segment with
>>>>     -# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT
>>>>     and TCP_CHKSUM as specified.
>>>>     -# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset
>>>>     segment generated by OVN logical router
>>>>     -test_tcp6_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>>     ipv6_router=$6
>>>>     -    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
>>>>     -    local exp_tcp_rst_chksum=${10}
>>>>     -    shift 10
>>>>     -
>>>>     -    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000 
>>>>
>>>>     -
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>>>>     IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
>>>>     -#
>>>>     -# Causes a packet to be received on INPORT of the hypervisor HV.
>>>>     The packet is an IPv6
>>>>     -# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO,
>>>>     IPV6_LEN and DATA as specified.
>>>>     -# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of
>>>>     the icmp6 packet sent by OVN logical router
>>>>     -test_ip6_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>>     ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
>>>>     -    local exp_icmp_code=${10} exp_icmp_chksum=${11}
>>>>     -    shift 11
>>>>     -
>>>>     -    local
>>>> ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
>>>>     -    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
>>>>     -
>>>>     -    local
>>>> reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr} 
>>>>
>>>>     -    echo $reply >> vif$inport.expected
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    net_add n$i
>>>>     -    ovn-nbctl ls-add sw$i
>>>>     -
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n$i br-phys 192.168.$i.1
>>>>     -
>>>>     -    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
>>>>     -        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i
>>>>     192.168.$i.1 2001:db8:$i::11"
>>>>     -
>>>>     -    ovs-vsctl -- add-port br-int vif$i -- \
>>>>     -        set interface vif$i \
>>>>     -        external-ids:iface-id=sw$i-p${i}0 \
>>>>     -            options:tx_pcap=hv$i/vif$i-tx.pcap \
>>>>     -            options:rxq_pcap=hv$i/vif$i-rx.pcap \
>>>>     -            ofport-request=$i
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -for i in 1 2; do
>>>>     -    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i
>>>>     192.168.$i.254/24 2001:db8:$i::1/64
>>>>     -    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
>>>>     -              -- set Logical_Switch_Port lrp$i-attachment
>>>>     type=router \
>>>>     -                options:router-port=lrp$i
>>>>     addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 
>>>> 2001:db8:'$i'::1"'
>>>>     -done
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -# allow some time for ovn-northd and ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>>     1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
>>>>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168
>>>>     1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
>>>>     -test_ip6_packet 1 1 000000000001 00000000ff01
>>>>     20010db8000100000000000000000011 20010db8000100000000000000000001
>>>>     11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
>>>>     -
>>>>     -test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>>>>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
>>>>     -test_ip6_packet 2 2 000000000002 00000000ff02
>>>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>>>     84 0004 01020304 0103 627e
>>>>     -test_tcp6_packet 2 2 000000000002 00000000ff02
>>>>     20010db8000200000000000000000011 20010db8000200000000000000000001
>>>>     8b40 3039 0000 4486
>>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ovn-controller exit])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -# Logical network:
>>>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>>     -# sw1 has a single port bound on hv1
>>>>     -# sw2 has a single port bound on hv2
>>>>     -
>>>>     -ovn-nbctl lr-add ro
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl ls-add sw2
>>>>     -
>>>>     -sw1_ro_mac=00:00:10:00:00:01
>>>>     -sw1_ro_ip=10.0.0.1
>>>>     -sw2_ro_mac=00:00:20:00:00:01
>>>>     -sw2_ro_ip=20.0.0.1
>>>>     -sw1_p1_mac=00:00:10:00:00:02
>>>>     -sw1_p1_ip=10.0.0.2
>>>>     -sw2_p1_mac=00:00:20:00:00:02
>>>>     -sw2_p1_ip=20.0.0.2
>>>>     -
>>>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>>>     type=router \
>>>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>>>     type=router \
>>>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>>>     -
>>>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>>>     -
>>>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -sleep 1
>>>>     -
>>>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>>>     eth.dst==$sw1_ro_mac &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>>>     ip4.dst==$sw2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -
>>>>     -# Start by Sending the packet and make sure it makes it there as
>>>>     expected
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>>>     ip4.dst==$sw2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Stop ovn-controller on hv2
>>>>     -as hv2 ovs-appctl -t ovn-controller exit
>>>>     -
>>>>     -# Now send the packet again. This time, it should not arrive.
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>>>     -as hv2 start_daemon ovn-controller
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- external logical port])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -sim_add hv2
>>>>     -sim_add hv3
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp1 \
>>>>     --- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
>>>>     -
>>>>     -# Add a couple of external logical port
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
>>>>     --- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 
>>>> ae70::6"
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
>>>>     -"f0:00:00:00:00:03 10.0.0.6 ae70::6"
>>>>     -ovn-nbctl lsp-set-type ls1-lp_ext1 external
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
>>>>     --- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 
>>>> ae70::7"
>>>>     -ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
>>>>     -"f0:00:00:00:00:04 10.0.0.7 ae70::8"
>>>>     -ovn-nbctl lsp-set-type ls1-lp_ext2 external
>>>>     -
>>>>     -d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24
>>>>     <http://10.0.0.0/24> \
>>>>     -options="\"server_id\"=\"10.0.0.1\"
>>>>     \"server_mac\"=\"ff:10:00:00:00:01\" \
>>>>     -\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
>>>>     -
>>>>     -d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
>>>>     -options="\"server_id\"=\"00:00:00:10:00:01\"")"
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
>>>>     -ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
>>>>     -
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
>>>>     -ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
>>>>     -
>>>>     -# Create a logical router and connect it to ls1
>>>>     -ovn-nbctl lr-add lr0
>>>>     -ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
>>>>     <http://10.0.0.1/24>
>>>>     -ovn-nbctl lsp-add ls1 ls1-lr0
>>>>     -ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
>>>>     -    options:router-port=lr0-ls1 addresses=router
>>>>     -
>>>>     -# Create HA chassis group
>>>>     -ovn-nbctl ha-chassis-group-add hagrp1
>>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>>>     -
>>>>     -hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find
>>>>     ha_chassis_group name="hagrp1"`
>>>>     -
>>>>     -# There should be 1 HA_Chassis rows with chassis sets
>>>>     -OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk
>>>>     '{print $3}' \
>>>>     -| grep '-' | wc -l ], [0], [1
>>>>     -])
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-phys hv1-ext1 -- \
>>>>     -    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/ext1-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-phys hv2-ext2 -- \
>>>>     -    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/ext2-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -as hv3
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.3
>>>>     -ovs-vsctl -- add-port br-phys hv3-ext3 -- \
>>>>     -    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
>>>>     -    options:rxq_pcap=hv3/ext3-rx.pcap \
>>>>     -    ofport-request=2
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>>>     10.0.0.6 in hv1 and
>>>>     -# hv2 as ha-chassis-group is not set and no localnet port added
>>>>     to ls1.
>>>>     -AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" 
>>>> | \
>>>>     -wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -
>>>>     -hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk 
>>>> '{print $3}')
>>>>     -hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk 
>>>> '{print $3}')
>>>>     -hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk 
>>>> '{print $3}')
>>>>     -
>>>>     -# The port_binding row for ls1-lp_ext1 should have empty chassis
>>>>     -chassis=`ovn-sbctl --bare --columns chassis find port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -
>>>>     -AT_CHECK([test x$chassis == x], [0], [])
>>>>     -
>>>>     -# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
>>>>     -ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
>>>>     -ha-chassis-group=$hagrp1_uuid
>>>>     -
>>>>     -# Get the hagrp1 uuid in SB DB.
>>>>     -sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find
>>>>     ha_chassis_group \
>>>>     -name="hagrp1"`
>>>>     -
>>>>     -# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group 
>>>> find \
>>>>     -port_binding logical_port=ls1-lp_ext1`
>>>>     -     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
>>>>     -
>>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 -
>>>>     10.0.0.6 in hv1 and hv2
>>>>     -# as no localnet port added to ls1 yet.
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -
>>>>     -# Add the localnet port to the logical switch ls1
>>>>     -ovn-nbctl lsp-add ls1 ln-public
>>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>>     -ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
>>>>     -
>>>>     -ln_public_key=$(ovn-sbctl list port_binding ln-public | grep
>>>>     tunnel_key | \
>>>>     -awk '{print $3}')
>>>>     -
>>>>     -# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part 
>>>> of the
>>>>     -# ha chassis group.
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = "$hv1_uuid"])
>>>>     -
>>>>     -# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port 
>>>> in hv1
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | grep
>>>>     reg14=0x$ln_public_key | \
>>>>     -wc -l], [0], [3
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -
>>>>     -# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 -
>>>>     10.0.0.7 in hv1 and
>>>>     -# hv2 as requested-chassis option is not set.
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.07" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], 
>>>> [0], [0
>>>>     -])
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl show
>>>>     -
>>>>     -# This shell function sends a DHCP request packet
>>>>     -# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
>>>>     -test_dhcp() {
>>>>     -    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
>>>>     -    shift; shift; shift; shift; shift;
>>>>     -    if test $use_ip != 0; then
>>>>     -        src_ip=$1
>>>>     -        dst_ip=$2
>>>>     -        shift; shift;
>>>>     -    else
>>>>     -        src_ip=`ip_to_hex 0 0 0 0`
>>>>     -        dst_ip=`ip_to_hex 255 255 255 255`
>>>>     -    fi
>>>>     -    local
>>>> request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip} 
>>>>
>>>>     -    # udp header and dhcp header
>>>>     -    request=${request}0044004300fc0000
>>>>     -
>>>> request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac} 
>>>>
>>>>     -    # client hardware padding
>>>>     -    request=${request}00000000000000000000
>>>>     -    # server hostname
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # boot file name
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> request=${request}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # dhcp magic cookie
>>>>     -    request=${request}63825363
>>>>     -    # dhcp message type
>>>>     -    request=${request}3501${dhcp_type}ff
>>>>     -
>>>>     -    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
>>>>     -    # total IP length will be the IP length of the request packet
>>>>     -    # (which is 272 in our case) + 8 (padding bytes) +
>>>>     (expected_dhcp_opts / 2)
>>>>     -    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
>>>>     -    udp_len=`expr $ip_len - 20`
>>>>     -    ip_len=$(printf "%x" $ip_len)
>>>>     -    udp_len=$(printf "%x" $udp_len)
>>>>     -    # $ip_len var will be in 3 digits i.e 134. So adding a '0'
>>>>     before $ip_len
>>>>     -    local
>>>> reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip} 
>>>>
>>>>     -    # udp header and dhcp header.
>>>>     -    # $udp_len var will be in 3 digits. So adding a '0' before
>>>>     $udp_len
>>>>     -
>>>> reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
>>>>     -    # your ip address
>>>>     -    reply=${reply}${offer_ip}
>>>>     -    # next server ip address, relay agent ip address, client mac
>>>>     address
>>>>     -    reply=${reply}0000000000000000${src_mac}
>>>>     -    # client hardware padding
>>>>     -    reply=${reply}00000000000000000000
>>>>     -    # server hostname
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # boot file name
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -
>>>> reply=${reply}0000000000000000000000000000000000000000000000000000000000000000 
>>>>
>>>>     -    # dhcp magic cookie
>>>>     -    reply=${reply}63825363
>>>>     -    # dhcp message type
>>>>     -    local dhcp_reply_type=02
>>>>     -    if test $dhcp_type = 03; then
>>>>     -        dhcp_reply_type=05
>>>>     -    fi
>>>>     -
>>>> reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000 
>>>>
>>>>     -    echo $reply >> ext1_v4.expected
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>>>     hv${inport}-ext${inport} $request
>>>>     -}
>>>>     -
>>>>     -
>>>>     -trim_zeros() {
>>>>     -    sed 's/\(00\)\{1,\}$//'
>>>>     -}
>>>>     -
>>>>     -# This shell function sends a DHCPv6 request packet
>>>>     -# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP
>>>>     OUTPORT...
>>>>     -# The OUTPORTs (zero or more) list the VIFs on which the original
>>>>     DHCPv6
>>>>     -# packet should be received twice (one from ovn-controller and
>>>>     the other
>>>>     -# from the "ovs-ofctl monitor br-int resume"
>>>>     -test_dhcpv6() {
>>>>     -    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
>>>>     -    local req_pkt_in_expected=$6
>>>>     -    local
>>>> request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
>>>>     -    # dst ip ff02::1:2
>>>>     -    request=${request}ff020000000000000000000000010002
>>>>     -    # udp header and dhcpv6 header
>>>>     -    request=${request}02220223002affff${msg_code}010203
>>>>     -    # Client identifier
>>>>     -    request=${request}0001000a00030001${src_mac}
>>>>     -    # IA-NA (Identity Association for Non Temporary Address)
>>>>     -    request=${request}0003000c0102030400000e1000001518
>>>>     -    shift; shift; shift; shift; shift;
>>>>     -
>>>>     -    local server_mac=000000100001
>>>>     -    local server_lla=fe80000000000000020000fffe100001
>>>>     -    local reply_code=07
>>>>     -    if test $msg_code = 01; then
>>>>     -        reply_code=02
>>>>     -    fi
>>>>     -    local msg_len=54
>>>>     -    if test $offer_ip = 1; then
>>>>     -        msg_len=28
>>>>     -    fi
>>>>     -    local 
>>>> reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
>>>>     -    reply=${reply}${server_lla}${src_lla}
>>>>     -
>>>>     -    # udp header and dhcpv6 header
>>>>     - reply=${reply}0223022200${msg_len}ffff${reply_code}010203
>>>>     -    # Client identifier
>>>>     -    reply=${reply}0001000a00030001${src_mac}
>>>>     -    # IA-NA
>>>>     -    if test $offer_ip != 1; then
>>>>     - 
>>>> reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
>>>>     -        reply=${reply}ffffffffffffffff
>>>>     -    fi
>>>>     -    # Server identifier
>>>>     -    reply=${reply}0002000a00030001${server_mac}
>>>>     -
>>>>     -    echo $reply | trim_zeros >> ext${inport}_v6.expected
>>>>     -    # The inport also receives the request packet since it is
>>>>     connected
>>>>     -    # to the br-phys.
>>>>     -    #echo $request >> ext${inport}_v6.expected
>>>>     -
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive
>>>>     hv${inport}-ext${inport} $request
>>>>     -}
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
>>>>     -as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
>>>>     -as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
>>>>     -
>>>>     -AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
>>>>     -as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
>>>>     ---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
>>>>     -
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -# Send DHCPDISCOVER.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -server_mac=ff1000000001
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>>     -$expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 1 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 0 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>>     to receive
>>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>>     easier to test.
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -rm -f ext1_v4.expected
>>>>     -rm -f ext1_v4.packets
>>>>     -
>>>>     -# Send DHCPv6 request
>>>>     -src_mac=f00000000003
>>>>     -src_lla=fe80000000000000f20000fffe000003
>>>>     -offer_ip=ae700000000000000000000000000006
>>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 0 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap | \
>>>>     -sort > ext1_v6.packets
>>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>>     -# Skipping the UDP checksum
>>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>>     -
>>>>     -rm -f ext1_v6.expected
>>>>     -rm -f ext1_v6.packets
>>>>     -
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -# Delete the ha-chassis hv1.
>>>>     -ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = ""])
>>>>     -
>>>>     -# Add hv2 to the ha chassis group
>>>>     -ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
>>>>     -
>>>>     -ovn-sbctl list ha_chassis_group
>>>>     -ovn-sbctl list ha_chassis
>>>>     -
>>>>     -ovn-sbctl find port_binding logical_port=ls1-lp_ext1
>>>>     -
>>>>     -# The ls1-lp_ext1 should be bound to hv2
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = "$hv2_uuid"])
>>>>     -
>>>>     -# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port
>>>>     in hv2
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | grep
>>>>     reg14=0x$ln_public_key | \
>>>>     -wc -l], [0], [3
>>>>     -])
>>>>     -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [1
>>>>     -])
>>>>     -
>>>>     -# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep "0a.00.00.06" | wc -l], [0], [0
>>>>     -])
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
>>>>     -grep controller | grep tp_src=546 | grep \
>>>>     -"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
>>>>     -grep reg14=0x$ln_public_key | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should
>>>>     come from
>>>>     -# hv2 ovn-controller.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -server_mac=ff1000000001
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>>     -$expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 1 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>>     to receive
>>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>>     easier to test.
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -rm -f ext1_v4.expected
>>>>     -
>>>>     -# Send DHCPv6 request again
>>>>     -src_mac=f00000000003
>>>>     -src_lla=fe80000000000000f20000fffe000003
>>>>     -offer_ip=ae700000000000000000000000000006
>>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap | \
>>>>     -sort > ext1_v6.packets
>>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>>     -# Skipping the UDP checksum
>>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>>     -
>>>>     -rm -f ext1_v6.expected
>>>>     -rm -f ext1_v6.packets
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>>     -reset_pcap_file br-phys hv1/br-phys
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -reset_pcap_file br-phys hv2/br-phys
>>>>     -
>>>>     -# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
>>>>     -# response should come from the router pipeline of hv2.
>>>>     -ext1_mac=f00000000003
>>>>     -router_mac=a01000000001
>>>>     -ext1_ip=`ip_to_hex 10 0 0 6`
>>>>     -router_ip=`ip_to_hex 10 0 0 1`
>>>> -arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip} 
>>>>
>>>>     -
>>>>     -as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
>>>> -expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip} 
>>>>
>>>>     -echo $expected_response > expout
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap > ext1_arp_resp
>>>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>>>     -
>>>>     -# Verify that the response came from hv2
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv2/br-phys_n1-tx.pcap > ext1_arp_resp
>>>>     -AT_CHECK([cat ext1_arp_resp], [0], [expout])
>>>>     -
>>>>     -# Now add 3 ha chassis to the ha chassis group
>>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
>>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
>>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
>>>>     -
>>>>     -# hv1 should be master and claim ls1-lp_ext1
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = "$hv1_uuid"])
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>>     -reset_pcap_file br-phys hv1/br-phys
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -reset_pcap_file br-phys hv2/br-phys
>>>>     -
>>>>     -as hv3
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>>     -reset_pcap_file br-phys hv3/br-phys
>>>>     -
>>>>     -# Send DHCPDISCOVER.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -server_mac=ff1000000001
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>>     -$expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 3 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>>     to receive
>>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>>     easier to test.
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -rm -f ext1_v4.expected
>>>>     -rm -f ext1_v4.packets
>>>>     -
>>>>     -# Send DHCPv6 request
>>>>     -src_mac=f00000000003
>>>>     -src_lla=fe80000000000000f20000fffe000003
>>>>     -offer_ip=ae700000000000000000000000000006
>>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>>     -
>>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap | \
>>>>     -sort > ext1_v6.packets
>>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>>     -# Skipping the UDP checksum
>>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>>     -
>>>>     -rm -f ext1_v6.expected
>>>>     -rm -f ext1_v6.packets
>>>>     -as hv1 reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -# Now increase the priority of hv3 so it becomes master.
>>>>     -ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
>>>>     -
>>>>     -# hv3 should be master and claim ls1-lp_ext1
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = "$hv3_uuid"])
>>>>     -
>>>>     -as hv1
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>>     -reset_pcap_file br-phys hv1/br-phys
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv2-ext2 hv2/ext2
>>>>     -reset_pcap_file br-phys_n1 hv2/br-phys_n1
>>>>     -reset_pcap_file br-phys hv2/br-phys
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl show
>>>>     -reset_pcap_file hv3-ext3 hv3/ext3
>>>>     -reset_pcap_file br-phys_n1 hv3/br-phys_n1
>>>>     -reset_pcap_file br-phys hv3/br-phys
>>>>     -
>>>>     -# Send DHCPDISCOVER.
>>>>     -offer_ip=`ip_to_hex 10 0 0 6`
>>>>     -server_ip=`ip_to_hex 10 0 0 1`
>>>>     -server_mac=ff1000000001
>>>> -expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
>>>>     -test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
>>>>     -$expected_dhcp_opts
>>>>     -
>>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 1 in hv3.
>>>>     -OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap > ext1_v4.packets
>>>>     -cat ext1_v4.expected | cut -c -48 > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
>>>>     -# Skipping the IPv4 checksum.
>>>>     -cat ext1_v4.expected | cut -c 53- > expout
>>>>     -AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
>>>>     -
>>>>     -# ovs-ofctl also resumes the packets and this causes other ports
>>>>     to receive
>>>>     -# the DHCP request packet. So reset the pcap files so that its
>>>>     easier to test.
>>>>     -as hv1
>>>>     -reset_pcap_file hv1-ext1 hv1/ext1
>>>>     -
>>>>     -rm -f ext1_v4.expected
>>>>     -rm -f ext1_v4.packets
>>>>     -
>>>>     -# Send DHCPv6 request
>>>>     -src_mac=f00000000003
>>>>     -src_lla=fe80000000000000f20000fffe000003
>>>>     -offer_ip=ae700000000000000000000000000006
>>>>     -test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
>>>>     -
>>>>     -# NXT_RESUMEs should be 4 in hv1.
>>>>     -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv2.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -# NXT_RESUMEs should be 2 in hv3.
>>>>     -OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c
>>>>     NXT_RESUME`])
>>>>     -
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/ext1-tx.pcap | \
>>>>     -sort > ext1_v6.packets
>>>>     -cat ext1_v6.expected | cut -c -120 > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
>>>>     -# Skipping the UDP checksum
>>>>     -cat ext1_v6.expected | cut -c 125- > expout
>>>>     -AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
>>>>     -
>>>>     -# disconnect hv3 from the network, hv1 should take over
>>>>     -as hv3
>>>>     -port=${sandbox}_br-phys
>>>>     -as main ovs-vsctl del-port n1 $port
>>>>     -
>>>>     -# hv1 should be master and claim ls1-lp_ext1
>>>>     -OVS_WAIT_UNTIL(
>>>>     -    [chassis=`ovn-sbctl --bare --columns chassis find 
>>>> port_binding \
>>>>     -logical_port=ls1-lp_ext1`
>>>>     -    test "$chassis" = "$hv1_uuid"])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2],[hv3])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- Address Set Incremental Processing])
>>>>     -AT_KEYWORDS([ovn_as_inc])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.10
>>>>     -
>>>>     -ovn-nbctl ls-add ls1
>>>>     -for i in 1 2; do
>>>>     -    ovn-nbctl lsp-add ls1 lp$i \
>>>>     -        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 
>>>> 192.168.1.$i"
>>>>     -    as hv1 ovs-vsctl \
>>>>     -        -- add-port br-int vif$i \
>>>>     -        -- set Interface vif$i \
>>>>     -            external-ids:iface-id=lp$i
>>>>     -done
>>>>     -
>>>>     -for i in 1 2 3; do
>>>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>>>     -    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
>>>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>>>     -            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}'
>>>>     allow-related
>>>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>>>     [0], [ignore])
>>>>     -
>>>>     -    # Update address set as1
>>>>     -    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 
>>>> 10.1.2.11"
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"],
>>>>     [0], [ignore])
>>>>     -
>>>>     -    # Update address set as2
>>>>     -    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 
>>>> 10.1.2.13"
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>>     [0], [ignore])
>>>>     -
>>>>     -    # Add another ACL referencing as1
>>>>     -    n_flows_before=`ovs-ofctl dump-flows br-int | grep
>>>>     "10.1.2.10" | wc -l`
>>>>     -    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
>>>>     -            'outport=="lp2" && ip4 && ip4.src == $as1' 
>>>> allow-related
>>>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>>>     | wc -l`
>>>>     -    AT_CHECK([test $(expr $n_flows_before \* 2) =
>>>>     $n_flows_after], [0], [ignore])
>>>>     -
>>>>     -    # Remove an ACL
>>>>     -    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
>>>>     -            'outport=="lp2" && ip4 && ip4.src == $as1'
>>>>     -    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10"
>>>>     | wc -l`
>>>>     -    AT_CHECK([test $n_flows_before = $n_flows_after], [0], 
>>>> [ignore])
>>>>     -
>>>>     -    # Remove as1 while it is still used by an ACL, the lflows
>>>>     should be reparsed and
>>>>     -    # parsing should fail.
>>>>     -    echo "before del as1"
>>>>     -    ovn-nbctl list addr | grep as1
>>>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid
>>>>     -    echo "after del as1"
>>>>     -    ovn-nbctl list addr | grep as1
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"],
>>>>     [1], [ignore])
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>>     [1], [ignore])
>>>>     -
>>>>     -    # Recreate as1
>>>>     -    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>>     [0], [ignore])
>>>>     -
>>>>     -    # Remove ACLs and address sets
>>>>     -    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr
>>>>     $as2_uuid
>>>>     -    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"],
>>>>     [1], [ignore])
>>>>     -
>>>>     -    ovn-nbctl --wait=hv acl-del ls1
>>>>     -done
>>>>     -
>>>>     -# Gracefully terminate daemons
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ovn-controller restart])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One Logical Router: ro, with two logical switches sw1 and sw2.
>>>>     -# sw1 is for subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>>     -# sw2 is for subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>>     -# sw1 has a single port bound on hv1
>>>>     -# sw2 has a single port bound on hv2
>>>>     -
>>>>     -ovn-nbctl lr-add ro
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl ls-add sw2
>>>>     -
>>>>     -sw1_ro_mac=00:00:10:00:00:01
>>>>     -sw1_ro_ip=10.0.0.1
>>>>     -sw2_ro_mac=00:00:20:00:00:01
>>>>     -sw2_ro_ip=20.0.0.1
>>>>     -sw1_p1_mac=00:00:10:00:00:02
>>>>     -sw1_p1_ip=10.0.0.2
>>>>     -sw2_p1_mac=00:00:20:00:00:02
>>>>     -sw2_p1_ip=20.0.0.2
>>>>     -
>>>>     -ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
>>>>     -ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
>>>>     -ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro
>>>>     type=router \
>>>>     -  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
>>>>     -ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro
>>>>     type=router \
>>>>     -  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
>>>>     -
>>>>     -ovn-nbctl lsp-add sw1 sw1-p1 \
>>>>     --- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
>>>>     -
>>>>     -ovn-nbctl lsp-add sw2 sw2-p1 \
>>>>     --- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -sleep 1
>>>>     -
>>>>     -packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac &&
>>>>     eth.dst==$sw1_ro_mac &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip &&
>>>>     ip4.dst==$sw2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -
>>>>     -# Start by Sending the packet and make sure it makes it there as
>>>>     expected
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -# Expected packet has TTL decreased by 1
>>>>     -expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
>>>>     -       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip &&
>>>>     ip4.dst==$sw2_p1_ip &&
>>>>     -       udp && udp.src==53 && udp.dst==4369"
>>>>     -echo $expected | ovstest test-ovn expr-to-packets > expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -# Stop ovn-controller on hv2 with --restart flag
>>>>     -as hv2 ovs-appctl -t ovn-controller exit --restart
>>>>     -
>>>>     -# Now send the packet again. This time, it should still arrive
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -cat expected expected > expected2
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
>>>>     -
>>>>     -# Start ovn-controller again just so OVN_CLEANUP doesn't complain
>>>>     -as hv2 start_daemon ovn-controller
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
>>>>     -ovn_start
>>>>     -
>>>>     -# Set up a switch with some switch ports of varying address types
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl set logical_switch sw1
>>>>     other_config:subnet=192.168.0.0/24 <http://192.168.0.0/24>
>>>>     -
>>>>     -ovn-nbctl lsp-add sw1 sw1-p1
>>>>     -ovn-nbctl lsp-add sw1 sw1-p2
>>>>     -ovn-nbctl lsp-add sw1 sw1-p3
>>>>     -ovn-nbctl lsp-add sw1 sw1-p4
>>>>     -
>>>>     -ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1
>>>>     aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
>>>>     -ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
>>>>     -ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
>>>>     -ovn-nbctl lsp-set-addresses sw1-p4 "router"
>>>>     -ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
>>>>     -
>>>>     -ovn-nbctl list logical_switch_port
>>>>     -
>>>>     -# Now try to add duplicate addresses on a new port. These should
>>>>     all fail
>>>>     -ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     10.0.0.1"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     10.0.0.2"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     aef0::1"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     aef0::2"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     192.168.0.2"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 
>>>> 192.168.0.2
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04
>>>>     192.168.0.3"], [1], [],
>>>>     -[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 
>>>> 192.168.0.3
>>>>     -])
>>>>     -
>>>>     -# Now try re-setting sw1-p1. This should succeed
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01
>>>>     10.0.0.1 aef0::1"])
>>>>     -
>>>>     -# Now create a new switch and try setting IP addresses the same
>>>>     as the
>>>>     -# first switch. This should succeed.
>>>>     -ovn-nbctl ls-add sw2
>>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>>     10.0.0.1"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>>     192.168.0.2"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>>     192.168.0.3"])
>>>>     -AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04
>>>>     aef0::1"])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- router - check packet length - icmp defrag])
>>>>     -AT_KEYWORDS([check packet length])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl lsp-add sw0 sw0-port1
>>>>     -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 
>>>> 10.0.0.3"
>>>>     -
>>>>     -ovn-nbctl lr-add lr0
>>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
>>>>     <http://10.0.0.1/24>
>>>>     -ovn-nbctl lsp-add sw0 sw0-lr0
>>>>     -ovn-nbctl lsp-set-type sw0-lr0 router
>>>>     -ovn-nbctl lsp-set-addresses sw0-lr0 router
>>>>     -ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
>>>>     -
>>>>     -ovn-nbctl ls-add public
>>>>     -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 
>>>> 172.168.0.100/24
>>>>     -ovn-nbctl <http://172.168.0.100/24-ovn-nbctl> lsp-add public
>>>>     public-lr0
>>>>     -ovn-nbctl lsp-set-type public-lr0 router
>>>>     -ovn-nbctl lsp-set-addresses public-lr0 router
>>>>     -ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
>>>>     -
>>>>     -# localnet port
>>>>     -ovn-nbctl lsp-add public ln-public
>>>>     -ovn-nbctl lsp-set-type ln-public localnet
>>>>     -ovn-nbctl lsp-set-addresses ln-public unknown
>>>>     -ovn-nbctl lsp-set-options ln-public network_name=phys
>>>>     -
>>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
>>>>     -ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
>>>>     <http://10.0.0.0/24>
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -     local iface=$1
>>>>     -     local pcap_file=$2
>>>>     -     ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=dummy-tx.pcap \
>>>>     - options:rxq_pcap=dummy-rx.pcap
>>>>     -     rm -f ${pcap_file}*.pcap
>>>>     -     ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     - options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -     printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -test_ip_packet_larger() {
>>>>     -    local icmp_pmtu_reply_expected=$1
>>>>     -
>>>>     -    # Send ip packet from sw0-port1 to outside
>>>>     -    src_mac="505400000001" # sw-port1 mac
>>>>     -    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
>>>>     -    src_ip=`ip_to_hex 10 0 0 3`
>>>>     -    dst_ip=`ip_to_hex 172 168 0 3`
>>>>     -    # Set the packet length to 100.
>>>>     -    pkt_len=0064
>>>>     - packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
>>>>     -    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
>>>>     - 
>>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>>     - 
>>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>>     - 
>>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>>     - 
>>>> orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
>>>>     -    packet=${packet}${orig_packet_l3}
>>>>     -
>>>>     -
>>>> gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064 
>>>>
>>>>     -
>>>>     -    # If icmp_pmtu_reply_expected is 0, it means the packet is
>>>>     lesser than
>>>>     -    # the gateway mtu and should be delivered to the provider
>>>>     bridge via the
>>>>     -    # localnet port.
>>>>     -    # If icmp_pmtu_reply_expected is 1, it means the packet is
>>>>     larger than
>>>>     -    # the gateway mtu and ovn-controller should drop the packet
>>>>     and instead
>>>>     -    # generate ICMPv4  Destination Unreachable message with pmtu
>>>>     set to 42.
>>>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>>>     -        # Packet to expect at br-phys.
>>>>     -        src_mac="000020201213"
>>>>     -        dst_mac="00000012af11"
>>>>     -        src_ip=`ip_to_hex 10 0 0 3`
>>>>     -        dst_ip=`ip_to_hex 172 168 0 3`
>>>>     - expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
>>>>     - expected=${expected}${src_ip}${dst_ip}0304000000000000
>>>>     - expected=${expected}000000000000000000000000000000000000
>>>>     - expected=${expected}000000000000000000000000000000000000
>>>>     - expected=${expected}000000000000000000000000000000000000
>>>>     - expected=${expected}000000000000000000000000000000000000
>>>>     -        echo $expected > br_phys_n1.expected
>>>>     -        echo $gw_ip_garp >> br_phys_n1.expected
>>>>     -    else
>>>>     -        # MTU would be 100 - 18 = 82 (hex 0052)
>>>>     -        mtu=0052
>>>>     -        src_ip=`ip_to_hex 10 0 0 1`
>>>>     -        dst_ip=`ip_to_hex 10 0 0 3`
>>>>     -        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip
>>>>     + payload))
>>>>     -        reply_pkt_len=0080
>>>>     -        ip_csum=bd91
>>>>     -
>>>> icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879 
>>>>
>>>>     - 
>>>> icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
>>>>     - icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
>>>>     -        icmp_reply=${icmp_reply}${orig_packet_l3}
>>>>     -        echo $icmp_reply > hv1-vif1.expected
>>>>     -    fi
>>>>     -
>>>>     -    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
>>>>     -    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -
>>>>     -    # Send packet from sw0-port1 to outside
>>>>     -    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>>     -
>>>>     -    if test $icmp_pmtu_reply_expected = 0; then
>>>>     -        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap],
>>>>     [br_phys_n1.expected])
>>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" hv1/vif1-tx.pcap > pkts
>>>>     -        # hv1/vif1-tx.pcap can receive the GARP packet generated
>>>>     by ovn-controller
>>>>     -        # for the gateway router port. So ignore this packet.
>>>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>>>     -        AT_CHECK([cat packets], [0], [])
>>>>     -    else
>>>>     -        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], 
>>>> [hv1-vif1.expected])
>>>>     -        $PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" hv1/br-phys_n1-tx.pcap  > \
>>>>     -        pkts
>>>>     -        # hv1/br-phys_n1-tx.pcap can receive the GARP packet
>>>>     generated by ovn-controller
>>>>     -        # for the gateway router port. So ignore this packet.
>>>>     -        cat pkts | grep -v $gw_ip_garp > packets
>>>>     -        AT_CHECK([cat packets], [0], [])
>>>>     -    fi
>>>>     -}
>>>>     -
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
>>>>     -| grep "check_pkt_larger" | wc -l], [0], [[0
>>>>     -]])
>>>>     -dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep
>>>>     _uuid | \
>>>>     -awk '{print $3}')
>>>>     -ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
>>>>     -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
>>>>     -
>>>>     -# Set the gateway mtu to 100. If the packet length is > 100,
>>>>     ovn-controller
>>>>     -# should send icmp host not reachable with pmtu set to 100.
>>>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>>>     options:gateway_mtu=100
>>>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>>>     "check_pkt_larger(100)" | \
>>>>     -    wc -l` -eq 1
>>>>     -])
>>>>     -
>>>>     -icmp_reply_expected=1
>>>>     -test_ip_packet_larger $icmp_reply_expected
>>>>     -
>>>>     -# Set the gateway mtu to 500.
>>>>     -ovn-nbctl --wait=hv set logical_router_port lr0-public
>>>>     options:gateway_mtu=500
>>>>     -as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    test `as hv1 ovs-ofctl dump-flows br-int | grep
>>>>     "check_pkt_larger(500)" | \
>>>>     -    wc -l` -eq 1
>>>>     -])
>>>>     -
>>>>     -# Now the packet should be sent via the localnet port to br-phys.
>>>>     -icmp_reply_expected=0
>>>>     -test_ip_packet_larger $icmp_reply_expected
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IP packet buffering])
>>>>     -AT_KEYWORDS([ip-buffering])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR lr0 that has switches sw0 (192.168.1.0/24
>>>>     <http://192.168.1.0/24>) and
>>>>     -# sw1 (172.16.1.0/24 <http://172.16.1.0/24>) connected to it.
>>>>     -#
>>>>     -# Physical network:
>>>>     -# Tw0 hypervisors hv[12].
>>>>     -# hv1 hosts vif sw0-p0.
>>>>     -# hv1 hosts vif sw1-p0.
>>>>     -
>>>>     -send_icmp_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>>>>     ipv4_dst=$6 ip_chksum=$7 data=$8
>>>>     -    shift 8
>>>>     -
>>>>     -    local ip_ttl=ff
>>>>     -    local ip_len=001c
>>>>     -    local
>>>> packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data} 
>>>>
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>>>> $packet
>>>>     -}
>>>>     -
>>>>     -send_icmp6_packet() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>>>>     ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
>>>>     -    shift 8
>>>>     -
>>>>     -    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
>>>>     -    local 
>>>> packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport 
>>>> $packet
>>>>     -}
>>>>     -
>>>>     -get_arp_req() {
>>>>     -    local eth_src=$1 spa=$2 tpa=$3
>>>>     -    local
>>>> request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa} 
>>>>
>>>>     -    echo $request
>>>>     -}
>>>>     -
>>>>     -send_arp_reply() {
>>>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
>>>>     -    local
>>>> request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa} 
>>>>
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>>     $request
>>>>     -}
>>>>     -
>>>>     -send_na() {
>>>>     -    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 
>>>> dst_ip=$6
>>>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>>>     -    local
>>>> request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src} 
>>>>
>>>>     -
>>>>     -    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport
>>>>     $request
>>>>     -}
>>>>     -
>>>>     -get_nd() {
>>>>     -    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
>>>>     -    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
>>>>     -
>>>> request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src} 
>>>>
>>>>     -
>>>>     -    echo $request
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl ls-add sw1
>>>>     -
>>>>     -ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24> 2001:0:0:0:0:0:0:1/64
>>>>     -ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
>>>>     -    type=router options:router-port=sw0 \
>>>>     -    -- lsp-set-addresses rp-sw0 router
>>>>     -
>>>>     -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64
>>>>     -ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
>>>>     -    type=router options:router-port=sw1 \
>>>>     -    -- lsp-set-addresses rp-sw1 router
>>>>     -
>>>>     -ovn-nbctl lsp-add sw0 sw0-p0 \
>>>>     -    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2
>>>>     2001::2"
>>>>     -
>>>>     -ovn-nbctl lsp-add sw1 sw1-p0 \
>>>>     -    -- lsp-set-addresses sw1-p0 unknown
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -    printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -src_mac=f00000010203
>>>>     -src_ip=$(ip_to_hex 192 168 1 2)
>>>>     -src_ip6=20010000000000000000000000000002
>>>>     -
>>>>     -router_mac0=000001010203
>>>>     -router_mac1=000002010203
>>>>     -router_ip=$(ip_to_hex 172 16 1 1)
>>>>     -router_ip6=20020000000000000000000000000001
>>>>     -
>>>>     -dst_mac=001122334455
>>>>     -dst_ip=$(ip_to_hex 172 16 1 10)
>>>>     -dst_ip6=20020000000000000000000000000010
>>>>     -
>>>>     -data=0800bee4391a0001
>>>>     -
>>>>     -send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 
>>>> 0000 $data
>>>>     -send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
>>>>     -echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
>>>>     -echo
>>>> "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}" 
>>>>
>>>>     >> expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -nd_ip=ff0200000000000000000001ff000010
>>>>     -ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
>>>>     -
>>>>     -send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
>>>>     -echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
>>>>     -echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >>
>>>>     expected
>>>>     -send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- neighbor update on same HV])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# A public switch (pub) with a localnet port connected to two LRs
>>>>     (lr0 and lr1)
>>>>     -# each with a distributed gateway port.
>>>>     -# Two VMs: lp0 on sw0 connected to lr0
>>>>     -#          lp1 on sw1 connected to lr1
>>>>     -#
>>>>     -# This test adds a floating IP to each VM so when they are bound
>>>>     to the same
>>>>     -# hypervisor, it checks that the GARP sent by ovn-controller
>>>>     causes the
>>>>     -# MAC_Binding entries to be updated properly on each logical 
>>>> router.
>>>>     -# It will also capture packets on the physical interface to make
>>>>     sure that the
>>>>     -# GARPs have been sent out to the external network as well.
>>>>     -
>>>>     -# Create logical switches
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl ls-add pub
>>>>     -
>>>>     -# Created localnet port on public switch
>>>>     -ovn-nbctl lsp-add pub ln-pub
>>>>     -ovn-nbctl lsp-set-type ln-pub localnet
>>>>     -ovn-nbctl lsp-set-addresses ln-pub unknown
>>>>     -ovn-nbctl lsp-set-options ln-pub network_name=phys
>>>>     -
>>>>     -# Create logical routers and connect them to public switch
>>>>     -ovn-nbctl create Logical_Router name=lr0
>>>>     -ovn-nbctl create Logical_Router name=lr1
>>>>     -
>>>>     -ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
>>>>     <http://172.24.4.220/24>
>>>>     -ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port 
>>>> pub-lr0 \
>>>>     -    type=router options:router-port=lr0-pub
>>>>     options:nat-addresses="router" addresses="router"
>>>>     -ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
>>>>     <http://172.24.4.221/24>
>>>>     -ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port 
>>>> pub-lr1 \
>>>>     -    type=router options:router-port=lr1-pub
>>>>     options:nat-addresses="router" addresses="router"
>>>>     -
>>>>     -ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
>>>>     -ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
>>>>     -
>>>>     -# Connect sw0 and sw1 to lr0 and lr1
>>>>     -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>>>>     <http://10.0.0.254/24>
>>>>     -ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0
>>>>     type=router \
>>>>     -    options:router-port=lr0-sw0 addresses="router"
>>>>     -ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
>>>>     <http://20.0.0.254/24>
>>>>     -ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1
>>>>     type=router \
>>>>     -    options:router-port=lr1-sw1 addresses="router"
>>>>     -
>>>>     -
>>>>     -# Add SNAT rules
>>>>     -ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
>>>>     <http://10.0.0.0/24>
>>>>     -ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
>>>>     <http://20.0.0.0/24>
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 172.24.4.1
>>>>     -ovs-vsctl set open . 
>>>> external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -
>>>>     -ovs-vsctl add-port br-int vif0 -- set Interface vif0
>>>>     external-ids:iface-id=lp0
>>>>     -ovs-vsctl add-port br-int vif1 -- set Interface vif1
>>>>     external-ids:iface-id=lp1
>>>>     -
>>>>     -ovn-nbctl lsp-add sw0 lp0
>>>>     -ovn-nbctl lsp-add sw1 lp1
>>>>     -ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
>>>>     -ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
>>>>     -
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
>>>>     -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
>>>>     -
>>>>     -# Create two floating IPs, one for each VIF
>>>>     -ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
>>>>     -ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
>>>>     -
>>>>     -# Check that the MAC_Binding entries have been properly created
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>>     logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
>>>>     -OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding
>>>>     logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
>>>>     -
>>>>     -# Check that the GARPs went also to the external physical network
>>>>     -# Wait until at least 4 packets have arrived and copy them to a
>>>>     separate file as
>>>>     -# more GARPs are expected in the capture in order to avoid race
>>>>     conditions.
>>>>     -OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in
>>>>     <http://ovs-pcap.in>" hv1/br-phys-tx.pcap | wc -l` -gt 4])
>>>>     -$PYTHON "$top_srcdir/utilities/ovs-pcap.in <http://ovs-pcap.in>"
>>>>     hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
>>>>     -
>>>>     -# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
>>>>     -echo
>>>> "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464" 
>>>>
>>>>     > expout
>>>>     -# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
>>>>     -echo
>>>> "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc" 
>>>>
>>>>     >> expout
>>>>     -# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
>>>>     -echo
>>>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8" 
>>>>
>>>>     >> expout
>>>>     -# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
>>>>     -echo
>>>> "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd" 
>>>>
>>>>     >> expout
>>>>     -AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
>>>>     -#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ipam to non-ipam])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl --wait=hv set NB_Global .
>>>>     options:mac_prefix="0a:00:00:00:00:00"
>>>>     -ovn-nbctl ls-add sw0
>>>>     -ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
>>>>     -ovn-nbctl --wait=sb add Logical-Switch sw0 other_config
>>>>     subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>>>     dynamic_addresses], [0],
>>>>     -    ["0a:00:00:a8:01:03 192.168.1.2"
>>>>     -])
>>>>     -
>>>>     -ovn-nbctl --wait=sb lsp-set-addresses p0 router
>>>>     -
>>>>     -ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl get Logical-Switch-Port p0
>>>>     dynamic_addresses], [0], [[[]]
>>>>     -])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- ipam router ports])
>>>>     -ovn_start
>>>>     -
>>>>     -ovn-nbctl ls-add sw
>>>>     -ovn-nbctl set logical_switch sw
>>>>     other-config:subnet=192.168.1.0/24 <http://192.168.1.0/24>
>>>>     -
>>>>     -for i in 2 3 4; do
>>>>     -    ovn-nbctl lr-add ro$i
>>>>     -    ovn-nbctl lsp-add sw swp$i
>>>>     -    ovn-nbctl --wait=sb lsp-set-addresses swp$i
>>>>     "02:00:00:00:00:0$i dynamic"
>>>>     -    cidr=$(ovn-nbctl get logical_switch_port swp$i
>>>>     dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
>>>>     -    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 --
>>>>     set logical_switch_port swp$i type=router
>>>>     options:router-port=rop$i addresses=router;
>>>>     -    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i
>>>>     networks], [0], [[["192.168.1.$i/24"]]
>>>>     -])
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl list logical_switch_port
>>>>     -ovn-nbctl list logical_router_port
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- test transport zones])
>>>>     -ovn_start
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2 3 4 5; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.$i.1
>>>>     -done
>>>>     -
>>>>     -dnl Wait for the changes to be propagated
>>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -dnl Assert that each Chassis has a tunnel formed to every other
>>>>     Chassis
>>>>     -as hv1
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv2
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv3
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv4
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv5
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -]])
>>>>     -
>>>>     -dnl Let's now add some Chassis to different transport zones
>>>>     -dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
>>>>     -dnl   should have tunnels formed between the other two Chassis
>>>>     (hv2 and hv3)
>>>>     -dnl
>>>>     -dnl * hv2: Will be part of one transport zone: tz1. It should
>>>>     have a tunnel
>>>>     -dnl   to hv1 but not to hv3
>>>>     -dnl
>>>>     -dnl * hv3: Will be part of one transport zone: tz2. It should
>>>>     have a tunnel
>>>>     -dnl   to hv1 but not to hv2
>>>>     -dnl
>>>>     -dnl * hv4 and hv5: Will not have any TZ set so they will keep the
>>>>     tunnels
>>>>     -dnl   between themselves and remove the tunnels to other Chassis
>>>>     which now
>>>>     -dnl   belongs to some TZs
>>>>     -dnl
>>>>     -as hv1
>>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
>>>>     -
>>>>     -as hv2
>>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
>>>>     -
>>>>     -as hv3
>>>>     -ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
>>>>     -
>>>>     -dnl Wait for the changes to be propagated
>>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -as hv1
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -]])
>>>>     -
>>>>     -as hv2
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -]])
>>>>     -
>>>>     -as hv3
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -]])
>>>>     -
>>>>     -as hv4
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv5
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv4-0
>>>>     -]])
>>>>     -
>>>>     -dnl Removing the transport zones should make all Chassis to 
>>>> create
>>>>     -dnl tunnels between every other Chassis again
>>>>     -for i in 1 2 3; do
>>>>     -    as hv$i
>>>>     -    ovs-vsctl remove open . external-ids ovn-transport-zones
>>>>     -done
>>>>     -
>>>>     -dnl Wait for the changes to be propagated
>>>>     -ovn-nbctl --wait=sb --timeout=3 sync
>>>>     -ovn-nbctl --wait=hv --timeout=3 sync
>>>>     -
>>>>     -as hv1
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv2
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv3
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv4-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv4
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv5-0
>>>>     -]])
>>>>     -
>>>>     -as hv5
>>>>     -AT_CHECK([ovs-vsctl --bare --columns=name find interface
>>>>     type="geneve" | awk NF | sort], [0],
>>>>     -[[ovn-hv1-0
>>>>     -ovn-hv2-0
>>>>     -ovn-hv3-0
>>>>     -ovn-hv4-0
>>>>     -]])
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2], [hv3])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis
>>>>     mac])
>>>>     -ovn_start
>>>>     -
>>>>     -
>>>>     -# In this test cases we create 2 switches, all connected to same
>>>>     -# physical network (through br-phys on each HV). Each switch has
>>>>     -# 1 VIF. Each HV has 1 VIF port. The first digit
>>>>     -# of VIF port name indicates the hypervisor it is bound to, e.g.
>>>>     -# lp23 means VIF 3 on hv2.
>>>>     -#
>>>>     -# Each switch's VLAN tag and their logical switch ports are:
>>>>     -#   - ls1:
>>>>     -#       - tagged with VLAN 101
>>>>     -#       - ports: lp11
>>>>     -#   - ls2:
>>>>     -#       - tagged with VLAN 201
>>>>     -#       - ports: lp22
>>>>     -#
>>>>     -# Note: a localnet port is created for each switch to connect to
>>>>     -# physical network.
>>>>     -
>>>>     -for i in 1 2; do
>>>>     -    ls_name=ls$i
>>>>     -    ovn-nbctl ls-add $ls_name
>>>>     -    ln_port_name=ln$i
>>>>     -    if test $i -eq 1; then
>>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
>>>>     -    elif test $i -eq 2; then
>>>>     -        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
>>>>     -    fi
>>>>     -    ovn-nbctl lsp-set-addresses $ln_port_name unknown
>>>>     -    ovn-nbctl lsp-set-type $ln_port_name localnet
>>>>     -    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
>>>>     -done
>>>>     -
>>>>     -# lsp_to_ls LSP
>>>>     -#
>>>>     -# Prints the name of the logical switch that contains LSP.
>>>>     -lsp_to_ls () {
>>>>     -    case $1 in dnl (
>>>>     -        lp?[[11]]) echo ls1 ;; dnl (
>>>>     -        lp?[[12]]) echo ls2 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -vif_to_ls () {
>>>>     -    case $1 in dnl (
>>>>     -        vif?[[11]]) echo ls1 ;; dnl (
>>>>     -        vif?[[12]]) echo ls2 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -hv_to_num () {
>>>>     -    case $1 in dnl (
>>>>     -        hv1) echo 1 ;; dnl (
>>>>     -        hv2) echo 2 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -vif_to_num () {
>>>>     -    case $1 in dnl (
>>>>     -        vif22) echo 22 ;; dnl (
>>>>     -        vif21) echo 21 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -vif_to_hv () {
>>>>     -    case $1 in dnl (
>>>>     -        vif[[1]]?) echo hv1 ;; dnl (
>>>>     -        vif[[2]]?) echo hv2 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -vif_to_lrp () {
>>>>     -    echo router-to-`vif_to_ls $1`
>>>>     -}
>>>>     -
>>>>     -hv_to_chassis_mac () {
>>>>     -     case $1 in dnl (
>>>>     -        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
>>>>     -        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
>>>>     -        *) AT_FAIL_IF([:]) ;;
>>>>     -    esac
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -       printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -net_add n1
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovs-vsctl set open .
>>>>     external-ids:ovn-bridge-mappings=phys:br-phys
>>>>     -    ovs-vsctl set open .
>>>> external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    ovs-vsctl add-port br-int vif$i$i -- \
>>>>     -        set Interface vif$i$i external-ids:iface-id=lp$i$i \
>>>>     - options:tx_pcap=hv$i/vif$i$i-tx.pcap \
>>>>     - options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
>>>>     -                              ofport-request=$i$i
>>>>     -
>>>>     -    lsp_name=lp$i$i
>>>>     -    ls_name=$(lsp_to_ls $lsp_name)
>>>>     -
>>>>     -    ovn-nbctl lsp-add $ls_name $lsp_name
>>>>     -    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i
>>>>     192.168.$i.$i"
>>>>     -    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
>>>>     -
>>>>     -    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = 
>>>> xup])
>>>>     -
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl lr-add router
>>>>     -ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03
>>>>     192.168.1.3/24
>>>>     -ovn-nbctl <http://192.168.1.3/24-ovn-nbctl> lrp-add router
>>>>     router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 
>>>> <http://192.168.2.3/24>
>>>>     -
>>>>     -ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port
>>>>     ls1-to-router type=router options:router-port=router-to-ls1 --
>>>>     lsp-set-addresses ls1-to-router router
>>>>     -ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port
>>>>     ls2-to-router type=router options:router-port=router-to-ls2 --
>>>>     lsp-set-addresses ls2-to-router router
>>>>     -
>>>>     -ovn-nbctl --wait=sb sync
>>>>     -#ovn-sbctl dump-flows
>>>>     -
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -test_ip() {
>>>>     -    # This packet has bad checksums but logical L3 routing
>>>>     doesn't check.
>>>>     -    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>>>>     -    local
>>>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -    shift; shift; shift; shift; shift
>>>>     -    hv=`vif_to_hv $inport`
>>>>     -    hv_num=`hv_to_num $hv`
>>>>     -    chassis_mac=`hv_to_chassis_mac $hv`
>>>>     -    as $hv ovs-appctl netdev-dummy/receive $inport $packet
>>>>     -    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport 
>>>> $packet
>>>>     -    in_ls=`vif_to_ls $inport`
>>>>     -    in_lrp=`vif_to_lrp $inport`
>>>>     -    for outport; do
>>>>     -        out_ls=`vif_to_ls $outport`
>>>>     -        if test $in_ls = $out_ls; then
>>>>     -            # Ports on the same logical switch receive exactly
>>>>     the same packet.
>>>>     -            echo $packet
>>>>     -        else
>>>>     -            # Routing decrements TTL and updates source and 
>>>> dest MAC
>>>>     -            # (and checksum).
>>>>     -            outport_num=`vif_to_num $outport`
>>>>     -            out_lrp=`vif_to_lrp $outport`
>>>>     -            echo
>>>> f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 
>>>>
>>>>     -        fi >> $outport.expected
>>>>     -    done
>>>>     -}
>>>>     -
>>>>     -# Dump a bunch of info helpful for debugging if there's a 
>>>> failure.
>>>>     -
>>>>     -echo "------ OVN dump ------"
>>>>     -ovn-nbctl show
>>>>     -ovn-sbctl show
>>>>     -
>>>>     -echo "------ hv1 dump ------"
>>>>     -as hv1 ovs-vsctl show
>>>>     -as hv1 ovs-vsctl list Open_Vswitch
>>>>     -
>>>>     -echo "------ hv2 dump ------"
>>>>     -as hv2 ovs-vsctl show
>>>>     -as hv2 ovs-vsctl list Open_Vswitch
>>>>     -
>>>>     -echo "Send traffic"
>>>>     -sip=`ip_to_hex 192 168 1 1`
>>>>     -dip=`ip_to_hex 192 168 2 2`
>>>>     -test_ip vif11 f00000000011  000001010203 $sip $dip vif22
>>>>     -
>>>>     -echo "----------- Post Traffic hv1 dump -----------"
>>>>     -as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -as hv1 ovs-appctl fdb/show br-phys
>>>>     -
>>>>     -echo "----------- Post Traffic hv2 dump -----------"
>>>>     -as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
>>>>     -as hv2 ovs-appctl fdb/show br-phys
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1],[hv2])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -# Run ovn-nbctl in daemon mode, change to a backup database and
>>>>     verify that
>>>>     -# an insert operation is not allowed.
>>>>     -AT_SETUP([ovn -- can't write to a backup database server 
>>>> instance])
>>>>     -ovn_start
>>>>     -on_exit 'kill $(cat ovn-nbctl.pid)'
>>>>     -export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
>>>>     -
>>>>     -AT_CHECK([ovn-nbctl ls-add sw0])
>>>>     -as ovn-nb
>>>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>>>     grep active | wc -l], [0], [1
>>>>     -])
>>>>     -ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server
>>>>     tcp:192.0.2.2:6641 <http://192.0.2.2:6641>
>>>>     -ovs-appctl -t ovsdb-server 
>>>> ovsdb-server/connect-active-ovsdb-server
>>>>     -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status |
>>>>     grep -c backup], [0], [1
>>>>     -])
>>>>     -AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
>>>>     -[ovn-nbctl: transaction error: {"details":"insert operation not
>>>>     allowed when database server is in read only mode","error":"not
>>>>     allowed"}
>>>>     -])
>>>>     -
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- controller event])
>>>>     -AT_KEYWORDS([ovn_controller_event])
>>>>     -ovn_start
>>>>     -
>>>>     -# Create hypervisors hv[12].
>>>>     -# Add vif1[12] to hv1, vif2[12] to hv2
>>>>     -# Add all of the vifs to a single logical switch sw0.
>>>>     -
>>>>     -net_add n1
>>>>     -ovn-nbctl ls-add sw0
>>>>     -for i in 1 2; do
>>>>     -    sim_add hv$i
>>>>     -    as hv$i
>>>>     -    ovs-vsctl add-br br-phys
>>>>     -    ovn_attach n1 br-phys 192.168.0.$i
>>>>     -
>>>>     -    for j in 1 2; do
>>>>     -        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
>>>>     -                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j
>>>>     192.168.1.$i$j"
>>>>     -
>>>>     -        ovs-vsctl -- add-port br-int vif$i$j -- \
>>>>     -                set interface vif$i$j \
>>>>     -                external-ids:iface-id=sw0-p$i$j \
>>>>     -                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
>>>>     -                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
>>>>     -                ofport-request=$i$j
>>>>     -    done
>>>>     -done
>>>>     -
>>>>     -ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
>>>>     -ovn-nbctl lb-add lb0 192.168.1.100:80 
>>>> <http://192.168.1.100:80> ""
>>>>     -ovn-nbctl ls-lb-add sw0 lb0
>>>>     -uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer
>>>>     name=lb0)
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -ovn-nbctl --timeout=3 --wait=hv sync
>>>>     -ovn-sbctl lflow-list
>>>>     -as hv1 ovs-ofctl dump-flows br-int
>>>>     -
>>>>     -packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 &&
>>>>     eth.dst==00:00:00:00:00:21 &&
>>>>     -       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 &&
>>>>     ip4.dst==192.168.1.100 &&
>>>>     -       tcp && tcp.src==10000 && tcp.dst==80"
>>>>     -as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
>>>>     -
>>>>     -ovn-sbctl list controller_event
>>>>     -uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
>>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_type], 
>>>> [0], [dnl
>>>>     -empty_lb_backends
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip],
>>>>     [0], [dnl
>>>>     -"192.168.1.100:80 <http://192.168.1.100:80>"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid
>>>>     event_info:protocol], [0], [dnl
>>>>     -tcp
>>>>     -])
>>>>     -AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid
>>>>     event_info:load_balancer], [0], [dnl
>>>>     -"$uuid_lb"
>>>>     -])
>>>>     -AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], 
>>>> [dnl
>>>>     -1
>>>>     -])
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- IGMP snoop/querier])
>>>>     -AT_SKIP_IF([test $HAVE_PYTHON = no])
>>>>     -ovn_start
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two independent logical switches (sw1 and sw2).
>>>>     -# sw1:
>>>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>>     -#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
>>>>     -#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
>>>>     -# sw2:
>>>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>>     -#   - 1 port bound on hv1 (sw2-p1)
>>>>     -#   - 1 port bound on hv2 (sw2-p2)
>>>>     -#   - IGMP Querier from 20.0.0.254
>>>>     -
>>>>     -reset_pcap_file() {
>>>>     -    local iface=$1
>>>>     -    local pcap_file=$2
>>>>     -    ovs-vsctl -- set Interface $iface 
>>>> options:tx_pcap=dummy-tx.pcap \
>>>>     -options:rxq_pcap=dummy-rx.pcap
>>>>     -    rm -f ${pcap_file}*.pcap
>>>>     -    ovs-vsctl -- set Interface $iface
>>>>     options:tx_pcap=${pcap_file}-tx.pcap \
>>>>     -options:rxq_pcap=${pcap_file}-rx.pcap
>>>>     -}
>>>>     -
>>>>     -ip_to_hex() {
>>>>     -     printf "%02x%02x%02x%02x" "$@"
>>>>     -}
>>>>     -
>>>>     -#
>>>>     -# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP 
>>>> REC_TYPE
>>>>     -#                     IGMP_CSUM OUTFILE
>>>>     -#
>>>>     -# This shell function causes an IGMPv3 report to be received on
>>>>     INPORT of HV.
>>>>     -# The packet's content has Ethernet destination 01:00:5E:00:00:22
>>>>     and source
>>>>     -# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
>>>>     -# GROUP is the IP multicast group to be joined/to leave (based on
>>>>     REC_TYPE).
>>>>     -# REC_TYPE == 04: join GROUP
>>>>     -# REC_TYPE == 03: leave GROUP
>>>>     -# The packet hexdump is also stored in OUTFILE.
>>>>     -#
>>>>     -send_igmp_v3_report() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 
>>>> group=$6
>>>>     -    local rec_type=$7 igmp_chksum=$8 outfile=$9
>>>>     -
>>>>     -    local eth_dst=01005e000016
>>>>     -    local ip_dst=$(ip_to_hex 224 0 0 22)
>>>>     -    local ip_ttl=01
>>>>     -    local ip_ra_opt=94040000
>>>>     -
>>>>     -    local igmp_type=2200
>>>>     -    local num_rec=00000001
>>>>     -    local aux_dlen=00
>>>>     -    local num_src=0000
>>>>     -
>>>>     -    local eth=${eth_dst}${eth_src}0800
>>>>     -    local
>>>> ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt} 
>>>>
>>>>     -    local
>>>> igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group} 
>>>>
>>>>     -    local packet=${eth}${ip}${igmp}
>>>>     -
>>>>     -    echo ${packet} >> ${outfile}
>>>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>>>     -}
>>>>     -
>>>>     -#
>>>>     -# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
>>>>     -#
>>>>     -# This shell function builds an IGMPv3 general query from ETH_SRC
>>>>     and IP_SRC
>>>>     -# and stores the hexdump of the packet in OUTFILE.
>>>>     -#
>>>>     -store_igmp_v3_query() {
>>>>     -    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
>>>>     -
>>>>     -    local eth_dst=01005e000001
>>>>     -    local ip_dst=$(ip_to_hex 224 0 0 1)
>>>>     -    local ip_ttl=01
>>>>     -    local igmp_type=11
>>>>     -    local max_resp=0a
>>>>     -    local igmp_chksum=eeeb
>>>>     -    local addr=00000000
>>>>     -
>>>>     -    local eth=${eth_dst}${eth_src}0800
>>>>     -    local
>>>> ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
>>>>     -    local 
>>>> igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
>>>>     -    local packet=${eth}${ip}${igmp}
>>>>     -
>>>>     -    echo ${packet} >> ${outfile}
>>>>     -}
>>>>     -
>>>>     -#
>>>>     -# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST
>>>>     IP_LEN
>>>>     -#    IP_PROTO DATA OUTFILE
>>>>     -#
>>>>     -# This shell function causes an IP multicast packet to be
>>>>     received on INPORT
>>>>     -# of HV.
>>>>     -# The hexdump of the packet is stored in OUTFILE.
>>>>     -#
>>>>     -send_ip_multicast_pkt() {
>>>>     -    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 
>>>> ip_dst=$6
>>>>     -    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} 
>>>> outfile=${11}
>>>>     -
>>>>     -    local ip_ttl=20
>>>>     -
>>>>     -    local eth=${eth_dst}${eth_src}0800
>>>>     -    local
>>>> ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst} 
>>>>
>>>>     -    local packet=${eth}${ip}${data}
>>>>     -
>>>>     -    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
>>>>     -    echo ${packet} >> ${outfile}
>>>>     -}
>>>>     -
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl ls-add sw2
>>>>     -
>>>>     -ovn-nbctl lsp-add sw1 sw1-p11
>>>>     -ovn-nbctl lsp-add sw1 sw1-p12
>>>>     -ovn-nbctl lsp-add sw1 sw1-p21
>>>>     -ovn-nbctl lsp-add sw1 sw1-p22
>>>>     -ovn-nbctl lsp-add sw2 sw2-p1
>>>>     -ovn-nbctl lsp-add sw2 sw2-p2
>>>>     -
>>>>     -net_add n1
>>>>     -sim_add hv1
>>>>     -as hv1
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>>     -    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
>>>>     -    options:tx_pcap=hv1/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>>     -    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
>>>>     -    options:tx_pcap=hv1/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv1-vif3 -- \
>>>>     -    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
>>>>     -    options:tx_pcap=hv1/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv1/vif3-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -sim_add hv2
>>>>     -as hv2
>>>>     -ovs-vsctl add-br br-phys
>>>>     -ovn_attach n1 br-phys 192.168.0.2
>>>>     -ovs-vsctl -- add-port br-int hv2-vif1 -- \
>>>>     -    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
>>>>     -    options:tx_pcap=hv2/vif1-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif1-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv2-vif2 -- \
>>>>     -    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
>>>>     -    options:tx_pcap=hv2/vif2-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif2-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -ovs-vsctl -- add-port br-int hv2-vif3 -- \
>>>>     -    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
>>>>     -    options:tx_pcap=hv2/vif3-tx.pcap \
>>>>     -    options:rxq_pcap=hv2/vif3-rx.pcap \
>>>>     -    ofport-request=1
>>>>     -
>>>>     -OVN_POPULATE_ARP
>>>>     -
>>>>     -# Enable IGMP snooping on sw1.
>>>>     -ovn-nbctl set Logical_Switch sw1 
>>>> other_config:mcast_querier="false"
>>>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>>>     -
>>>>     -# No IGMP query should be generated by sw1 
>>>> (mcast_querier="false").
>>>>     -truncate -s 0 expected
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
>>>>     -
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p11.
>>>>     -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 IGMP Join for 239.0.1.68 on sw1-p21.
>>>>     -send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0
>>>>     2) f9f9 \
>>>>     -    $(ip_to_hex 239 0 1 68) 04 e9b9 \
>>>>     -    /dev/null
>>>>     -
>>>>     -# Check that the IGMP Group is learned on both hv.
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    test "${total_entries}" = "2"
>>>>     -])
>>>>     -
>>>>     -# Send traffic and make sure it gets forwarded only on the two
>>>>     ports that
>>>>     -# joined.
>>>>     -truncate -s 0 expected
>>>>     -truncate -s 0 expected_empty
>>>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>>>     -    000000000001 01005e000144 \
>>>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>>>     -    e518e518000a3b3a0000 \
>>>>     -    expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>>>     -
>>>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
>>>>     -send_igmp_v3_report hv1-vif1 hv1 \
>>>>     -    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
>>>>     -    $(ip_to_hex 239 0 1 68) 03 eab9 \
>>>>     -    /dev/null
>>>>     -
>>>>     -# Check IGMP_Group table on both HV.
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    test "${total_entries}" = "1"
>>>>     -])
>>>>     -
>>>>     -# Send traffic traffic and make sure it gets forwarded only on
>>>>     the port that
>>>>     -# joined.
>>>>     -as hv1 reset_pcap_file hv1-vif1 hv1/vif1
>>>>     -as hv2 reset_pcap_file hv2-vif1 hv2/vif1
>>>>     -truncate -s 0 expected
>>>>     -truncate -s 0 expected_empty
>>>>     -send_ip_multicast_pkt hv1-vif2 hv1 \
>>>>     -    000000000001 01005e000144 \
>>>>     -    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
>>>>     -    e518e518000a3b3a0000 \
>>>>     -    expected
>>>>     -
>>>>     -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
>>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
>>>>     -
>>>>     -# Flush IGMP groups.
>>>>     -ovn-sbctl ip-multicast-flush sw1
>>>>     -ovn-nbctl --wait=hv -t 3 sync
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    test "${total_entries}" = "0"
>>>>     -])
>>>>     -
>>>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>>>     to minimum.
>>>>     -ovn-nbctl set Logical_Switch sw2 \
>>>>     -    other_config:mcast_snoop="true" \
>>>>     -    other_config:mcast_querier="true" \
>>>>     -    other_config:mcast_query_interval=1 \
>>>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>>>     -
>>>>     -# Wait for 1 query interval (1 sec) and check that two queries
>>>>     are generated.
>>>>     -truncate -s 0 expected
>>>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>>>     expected
>>>>     -store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd
>>>>     expected
>>>>     -
>>>>     -sleep 1
>>>>     -OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
>>>>     -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
>>>>     -
>>>>     -OVN_CLEANUP([hv1], [hv2])
>>>>     -AT_CLEANUP
>>>>     diff --git a/tests/system-ovn.at <http://system-ovn.at>
>>>>     b/tests/system-ovn.at <http://system-ovn.at>
>>>>     deleted file mode 100644
>>>>     index f88ad31..0000000
>>>>     --- a/tests/system-ovn.at <http://system-ovn.at>
>>>>     +++ /dev/null
>>>>     @@ -1,1667 +0,0 @@
>>>>     -AT_BANNER([system-ovn])
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and
>>>>     DNAT])
>>>>     -AT_KEYWORDS([ovnnat])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>>> "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>>     -# to it.  R2 is a gateway router on which we add NAT rules.
>>>>     -#
>>>>     -#    foo -- R1 -- join - R2 -- alice
>>>>     -#           |
>>>>     -#    bar ----
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Static routes.
>>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>>     -"192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>>     -
>>>>     -# Add a DNAT rule.
>>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>>     logical_ip=192.168.1.2 \
>>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>>     logical_ip=192.168.2.2 \
>>>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -# wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>>     'nat(src=30.0.0.1)'])
>>>>     -
>>>>     -# 'alice1' should be able to ping 'foo1' directly.
>>>>     -NS_CHECK_EXEC([alice1], [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
>>>>     -])
>>>>     -
>>>>     -# North-South DNAT: 'alice1' should also be able to ping 'foo1'
>>>>     via 30.0.0.2
>>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# Check conntrack entries.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>>>     traffic
>>>>     -# from 30.0.0.1
>>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# Add static routes to handle east-west NAT.
>>>>     -ovn-nbctl lr-route-add R1 30.0.0.0/24 <http://30.0.0.0/24> 
>>>> 20.0.0.2
>>>>     -
>>>>     -# wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -
>>>>     -# Flush conntrack entries for easier output parsing of next test.
>>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>>     -
>>>>     -# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' 
>>>> receives it.
>>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# As we have a static route that sends all packets with 
>>>> destination
>>>>     -# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to
>>>>     192.168.1.2
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1,
>>>>     the source is
>>>>     -# SNATted and 'foo1' receives it.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy 
>>>> SNAT])
>>>>     -AT_KEYWORDS([ovnnat])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>>> "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) connected
>>>>     -# to it.  R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it.
>>>>     -# R2 is a gateway router on which we add NAT rules.
>>>>     -#
>>>>     -#    foo -- R1 -- join - R2 -- alice
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Static routes.
>>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>>     logical_ip=192.168.1.2 \
>>>>     -    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>>     'nat(src=172.16.1.1)'])
>>>>     -
>>>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>>>     traffic
>>>>     -# from 172.16.1.1
>>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
>>>>     -AT_KEYWORDS([ovnnat])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>>     LS "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it. Note how both alice and
>>>>     -# bob have the same subnet behind it.  We are trying to simulate
>>>>     external
>>>>     -# network via those 2 switches. In real world the switch ports of
>>>>     these
>>>>     -# switches will have addresses set as "unknown" to make them
>>>>     learning switches.
>>>>     -# Or those switches will be "localnet" ones.
>>>>     -#
>>>>     -#    foo -- R1 -- join - R2 -- alice
>>>>     -#           |          |
>>>>     -#    bar ----          - R3 --- bob
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add bob
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect bob to R3
>>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>>     <http://172.16.1.2/24>
>>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>>     -    type=router options:router-port=bob
>>>>     addresses=\"00:00:03:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Connect R3 to join
>>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>>     <http://20.0.0.3/24>
>>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>>> r3-join \
>>>>     -    type=router options:router-port=R3_join
>>>>     addresses='"00:00:04:01:02:05"'
>>>>     -
>>>>     -# Install static routes with source ip address as the policy for
>>>>     routing.
>>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>>     go via R3.
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>>     <http://192.168.1.0/24> 20.0.0.2
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>>     <http://192.168.2.0/24> 20.0.0.3
>>>>     -
>>>>     -# Static routes.
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>>>     -ovn-nbctl set logical_router R2 
>>>> options:dnat_force_snat_ip=20.0.0.2
>>>>     -ovn-nbctl set logical_router R3 
>>>> options:dnat_force_snat_ip=20.0.0.3
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>>     -"192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>>     -
>>>>     -# Logical port 'bob1' in switch 'bob'.
>>>>     -ADD_NAMESPACES(bob1)
>>>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>>>     -         "172.16.1.2")
>>>>     -ovn-nbctl lsp-add bob bob1 \
>>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>>     -
>>>>     -# Router R2
>>>>     -# Add a DNAT rule.
>>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>>     logical_ip=192.168.1.2 \
>>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>>     logical_ip=192.168.1.2 \
>>>>     -    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -# Router R3
>>>>     -# Add a DNAT rule.
>>>>     -ovn-nbctl -- --id=@nat create nat type="dnat"
>>>>     logical_ip=192.168.1.2 \
>>>>     -    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>>     logical_ip=192.168.2.2 \
>>>>     -    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
>>>>     -
>>>>     -# wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>>     'nat(src=30.0.0.4)'])
>>>>     -
>>>>     -# North-South DNAT: 'alice1' should be able to ping 'foo1' via
>>>>     30.0.0.2
>>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# Check conntrack entries.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.3) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# But foo1 should receive traffic from 20.0.0.2
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(20.0.0.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# North-South DNAT: 'bob1' should be able to ping 'foo1' via 
>>>> 30.0.0.3
>>>>     -NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# Check conntrack entries.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.4) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# But foo1 should receive traffic from 20.0.0.3
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(20.0.0.3) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives 
>>>> traffic
>>>>     -# from 30.0.0.4
>>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.4) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives
>>>>     traffic
>>>>     -# from 30.0.0.1
>>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- load-balancing])
>>>>     -AT_KEYWORDS([ovnlb])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# 2 logical switches "foo" (192.168.1.0/24
>>>>     <http://192.168.1.0/24>) and "bar" (172.16.1.0/24
>>>>     <http://172.16.1.0/24>)
>>>>     -# connected to a router R1.
>>>>     -# foo has foo1 to act as a client.
>>>>     -# bar has bar1, bar2, bar3 to act as servers.
>>>>     -#
>>>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Create logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:0f:01:02:03", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
>>>>     -
>>>>     -ADD_NAMESPACES(bar2)
>>>>     -ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24
>>>>     <http://172.16.1.3/24>", "f0:00:0f:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add bar bar2 \
>>>>     --- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
>>>>     -
>>>>     -ADD_NAMESPACES(bar3)
>>>>     -ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24
>>>>     <http://172.16.1.4/24>", "f0:00:0f:01:02:05", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add bar bar3 \
>>>>     --- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
>>>>     -
>>>>     -# Config OVN load-balancer with a VIP.
>>>>     -uuid=`ovn-nbctl  create load_balancer
>>>>     vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
>>>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>>>     -
>>>>     -# Create another load-balancer with another VIP.
>>>>     -uuid=`ovn-nbctl create load_balancer
>>>>     vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
>>>>     -ovn-nbctl add logical_switch foo load_balancer $uuid
>>>>     -
>>>>     -# Config OVN load-balancer with another VIP (this time with 
>>>> ports).
>>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>>     <http://30.0.0.2:8000>"'='"172.16.1.2:80
>>>>     <http://172.16.1.2:80>,172.16.1.3:80
>>>>     <http://172.16.1.3:80>,172.16.1.4:80 <http://172.16.1.4:80>"'
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>>     -grep 'nat(dst=172.16.1.4:80)'])
>>>>     -
>>>>     -# Start webservers in 'bar1', 'bar2' and 'bar3'.
>>>>     -OVS_START_L7([bar1], [http])
>>>>     -OVS_START_L7([bar2], [http])
>>>>     -OVS_START_L7([bar3], [http])
>>>>     -
>>>>     -dnl Should work with the virtual IP 30.0.0.1 address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Should work with the virtual IP 30.0.0.3 address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.3) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>>     wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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"])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- load-balancing - same subnet.])
>>>>     -AT_KEYWORDS([ovnlb])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# 1 logical switch "foo" (192.168.1.0/24 <http://192.168.1.0/24>)
>>>>     connected to router R1.
>>>>     -# foo has foo1, foo2, foo3, foo4 as logical ports.
>>>>     -#
>>>>     -# Loadbalancer VIPs in 30.0.0.0/24 <http://30.0.0.0/24> network.
>>>>     Router is needed for default
>>>>     -# gateway. We will test load-balancing with foo1 as a client and
>>>>     foo2, foo3 and
>>>>     -# foo4 as servers.
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl ls-add foo
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch
>>>>     'foo'.
>>>>     -ADD_NAMESPACES(foo1, foo2, foo3, foo4)
>>>>     -for i in `seq 1 4`; do
>>>>     -    j=`expr $i + 1`
>>>>     -    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24",
>>>>     "f0:00:00:01:02:0$j", \
>>>>     -             "192.168.1.1")
>>>>     -    ovn-nbctl lsp-add foo foo$i \
>>>>     -        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 
>>>> 192.168.1.$j"
>>>>     -done
>>>>     -
>>>>     -# Config OVN load-balancer with a VIP.
>>>>     -uuid=`ovn-nbctl  create load_balancer
>>>>     vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
>>>>     -ovn-nbctl set logical_switch foo load_balancer=$uuid
>>>>     -
>>>>     -# Config OVN load-balancer with another VIP (this time with 
>>>> ports).
>>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>>     <http://30.0.0.2:8000>"'='"192.168.1.3:80
>>>>     <http://192.168.1.3:80>,192.168.1.4:80
>>>>     <http://192.168.1.4:80>,192.168.1.5:80 <http://192.168.1.5:80>"'
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>>     -grep 'nat(dst=192.168.1.5:80)'])
>>>>     -
>>>>     -# Start webservers in 'foo2', 'foo3' and 'foo4'.
>>>>     -OVS_START_L7([foo2], [http])
>>>>     -OVS_START_L7([foo3], [http])
>>>>     -OVS_START_L7([foo4], [http])
>>>>     -
>>>>     -dnl Should work with the virtual IP address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000
>>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>>     wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(30.0.0.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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"])
>>>>     -AT_CLEANUP
>>>>     -
>>>>     -AT_SETUP([ovn -- load balancing in gateway router])
>>>>     -AT_KEYWORDS([ovnlb])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two LRs - R1 and R2 that are connected to each other via LS 
>>>> "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>>     -# to it.  R2 is a gateway router on which we add load-balancing
>>>>     rules.
>>>>     -#
>>>>     -#    foo -- R1 -- join - R2 -- alice
>>>>     -#           |
>>>>     -#    bar ----
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Static routes.
>>>>     -ovn-nbctl lr-route-add R1 172.16.1.0/24 <http://172.16.1.0/24>
>>>>     20.0.0.2
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>>     -"192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>>     -
>>>>     -# Config OVN load-balancer with a VIP.
>>>>     -uuid=`ovn-nbctl  create load_balancer
>>>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>>>     -
>>>>     -# Config OVN load-balancer with another VIP (this time with 
>>>> ports).
>>>>     -ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000
>>>>     <http://30.0.0.2:8000>"'='"192.168.1.2:80
>>>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>>>     -
>>>>     -# Add SNAT rule to make sure that Load-balancing still works with
>>>>     a SNAT rule.
>>>>     -ovn-nbctl -- --id=@nat create nat type="snat"
>>>>     logical_ip=192.168.2.2 \
>>>>     -    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
>>>>     -
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>>     -grep 'nat(dst=192.168.2.2:80)'])
>>>>     -
>>>>     -# Start webservers in 'foo1', 'bar1'.
>>>>     -OVS_START_L7([foo1], [http])
>>>>     -OVS_START_L7([bar1], [http])
>>>>     -
>>>>     -dnl Should work with the virtual IP address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000
>>>>     <http://30.0.0.2:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>>     wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- multiple gateway routers, load-balancing])
>>>>     -AT_KEYWORDS([ovnlb])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Three LRs - R1, R2 and R3 that are connected to each other via
>>>>     LS "join"
>>>>     -# in 20.0.0.0/24 <http://20.0.0.0/24> network. R1 has switchess
>>>>     foo (192.168.1.0/24 <http://192.168.1.0/24>) and
>>>>     -# bar (192.168.2.0/24 <http://192.168.2.0/24>) connected to it.
>>>>     R2 has alice (172.16.1.0/24 <http://172.16.1.0/24>) connected
>>>>     -# to it.  R3 has bob (172.16.1.0/24 <http://172.16.1.0/24>)
>>>>     connected to it. Note how both alice and
>>>>     -# bob have the same subnet behind it.  We are trying to simulate
>>>>     external
>>>>     -# network via those 2 switches. In real world the switch ports of
>>>>     these
>>>>     -# switches will have addresses set as "unknown" to make them
>>>>     learning switches.
>>>>     -# Or those switches will be "localnet" ones.
>>>>     -#
>>>>     -#    foo -- R1 -- join - R2 -- alice
>>>>     -#           |          |
>>>>     -#    bar ----          - R3 --- bob
>>>>     -
>>>>     -ovn-nbctl create Logical_Router name=R1
>>>>     -ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
>>>>     -ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -ovn-nbctl ls-add bob
>>>>     -ovn-nbctl ls-add join
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo
>>>>     addresses=\"00:00:01:01:02:03\"
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar
>>>>     addresses=\"00:00:01:01:02:04\"
>>>>     -
>>>>     -# Connect alice to R2
>>>>     -ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24>
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice
>>>>     addresses=\"00:00:02:01:02:03\"
>>>>     -
>>>>     -# Connect bob to R3
>>>>     -ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
>>>>     <http://172.16.1.2/24>
>>>>     -ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
>>>>     -    type=router options:router-port=bob
>>>>     addresses=\"00:00:03:01:02:03\"
>>>>     -
>>>>     -# Connect R1 to join
>>>>     -ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
>>>>     <http://20.0.0.1/24>
>>>>     -ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port 
>>>> r1-join \
>>>>     -    type=router options:router-port=R1_join
>>>>     addresses='"00:00:04:01:02:03"'
>>>>     -
>>>>     -# Connect R2 to join
>>>>     -ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
>>>>     <http://20.0.0.2/24>
>>>>     -ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port 
>>>> r2-join \
>>>>     -    type=router options:router-port=R2_join
>>>>     addresses='"00:00:04:01:02:04"'
>>>>     -
>>>>     -# Connect R3 to join
>>>>     -ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
>>>>     <http://20.0.0.3/24>
>>>>     -ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port 
>>>> r3-join \
>>>>     -    type=router options:router-port=R3_join
>>>>     addresses='"00:00:04:01:02:05"'
>>>>     -
>>>>     -# Install static routes with source ip address as the policy for
>>>>     routing.
>>>>     -# We want traffic from 'foo' to go via R2 and traffic of 'bar' to
>>>>     go via R3.
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24
>>>>     <http://192.168.1.0/24> 20.0.0.2
>>>>     -ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24
>>>>     <http://192.168.2.0/24> 20.0.0.3
>>>>     -
>>>>     -# Static routes.
>>>>     -ovn-nbctl lr-route-add R2 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -ovn-nbctl lr-route-add R3 192.168.0.0/16 <http://192.168.0.0/16>
>>>>     20.0.0.1
>>>>     -
>>>>     -# For gateway routers R2 and R3, set a force SNAT rule.
>>>>     -ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
>>>>     -ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24
>>>>     <http://172.16.1.3/24>", "f0:00:00:01:02:04", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:05", \
>>>>     -"192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
>>>>     -
>>>>     -# Logical port 'bob1' in switch 'bob'.
>>>>     -ADD_NAMESPACES(bob1)
>>>>     -ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24
>>>>     <http://172.16.1.4/24>", "f0:00:00:01:02:06", \
>>>>     -         "172.16.1.2")
>>>>     -ovn-nbctl lsp-add bob bob1 \
>>>>     --- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
>>>>     -
>>>>     -# Config OVN load-balancer with a VIP.
>>>>     -uuid=`ovn-nbctl  create load_balancer
>>>>     vips:30.0.0.1="192.168.1.2,192.168.2.2"`
>>>>     -ovn-nbctl set logical_router R2 load_balancer=$uuid
>>>>     -ovn-nbctl set logical_router R3 load_balancer=$uuid
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>>     -grep 'nat(dst=192.168.2.2)'])
>>>>     -
>>>>     -# Start webservers in 'foo1', 'bar1'.
>>>>     -OVS_START_L7([foo1], [http])
>>>>     -OVS_START_L7([bar1], [http])
>>>>     -
>>>>     -dnl Should work with the virtual IP address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Force SNAT should have worked.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- load balancing in router with gateway router 
>>>> port])
>>>>     -AT_KEYWORDS([ovnlb])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>>     <http://192.168.2.0/24>),
>>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>>     it.  The port between R1 and
>>>>     -# alice is the router gateway port where the R1 LB rules are 
>>>> applied.
>>>>     -#
>>>>     -#    foo -- R1 -- bar
>>>>     -#           |
>>>>     -#    alice ----
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24> \
>>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar \
>>>>     -    -- lsp-set-addresses rp-bar router
>>>>     -
>>>>     -# Connect alice to R1
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'foo2' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo2)
>>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo2 \
>>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>>     -
>>>>     -# Config OVN load-balancer with a VIP.
>>>>     -uuid=`ovn-nbctl  create load_balancer
>>>>     vips:172.16.1.10="192.168.1.2,192.168.2.2"`
>>>>     -ovn-nbctl set logical_router R1 load_balancer=$uuid
>>>>     -
>>>>     -# Config OVN load-balancer with another VIP (this time with 
>>>> ports).
>>>>     -ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000
>>>>     <http://172.16.1.11:8000>"'='"192.168.1.2:80
>>>>     <http://192.168.1.2:80>,192.168.2.2:80 <http://192.168.2.2:80>"'
>>>>     -
>>>>     -# Wait for ovn-controller to catch up.
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
>>>>     -grep 'nat(dst=192.168.2.2:80)'])
>>>>     -
>>>>     -# Start webservers in 'foo1', 'bar1'.
>>>>     -OVS_START_L7([foo1], [http])
>>>>     -OVS_START_L7([bar1], [http])
>>>>     -
>>>>     -dnl Should work with the virtual IP address through NAT
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1
>>>>     --retry-connrefused -v -o wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.10) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -dnl Test load-balancing that includes L4 ports in NAT.
>>>>     -for i in `seq 1 20`; do
>>>>     -    echo Request $i
>>>>     -    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000
>>>>     <http://172.16.1.11:8000> -t 5 -T 1 --retry-connrefused -v -o
>>>>     wget$i.log])
>>>>     -done
>>>>     -
>>>>     -dnl Each server should have at least one connection.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.11) |
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>> -tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>) 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
>>>>     -AT_KEYWORDS([ovnnat])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>>     <http://192.168.2.0/24>),
>>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>>     it.  The port between R1 and
>>>>     -# alice is the router gateway port where the R1 NAT rules are
>>>>     applied.
>>>>     -#
>>>>     -#    foo -- R1 -- alice
>>>>     -#           |
>>>>     -#    bar ----
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24> \
>>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar \
>>>>     -    -- lsp-set-addresses rp-bar router
>>>>     -
>>>>     -# Connect alice to R1
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'foo2' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo2)
>>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo2 \
>>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>>     -
>>>>     -# Add DNAT rules
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>>>     192.168.1.3 foo2 00:00:02:02:03:05])
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>>>     <http://192.168.0.0/16>])
>>>>     -
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>>     'nat(src=172.16.1.1)'])
>>>>     -
>>>>     -# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
>>>>     -NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that DNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.3) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives
>>>>     traffic
>>>>     -# from 172.16.1.4
>>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>>     -
>>>>     -# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives
>>>>     traffic
>>>>     -# from 172.16.1.1
>>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that SNAT indeed happened via 'dump-conntrack' 
>>>> command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
>>>>     -AT_KEYWORDS([ovnnat])
>>>>     -
>>>>     -CHECK_CONNTRACK()
>>>>     -CHECK_CONNTRACK_NAT()
>>>>     -ovn_start
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# One LR R1 with switches foo (192.168.1.0/24
>>>>     <http://192.168.1.0/24>), bar (192.168.2.0/24
>>>>     <http://192.168.2.0/24>),
>>>>     -# and alice (172.16.1.0/24 <http://172.16.1.0/24>) connected to
>>>>     it.  The port between R1 and
>>>>     -# alice is the router gateway port where the R1 NAT rules are
>>>>     applied.
>>>>     -#
>>>>     -#    foo -- R1 -- alice
>>>>     -#           |
>>>>     -#    bar ----
>>>>     -
>>>>     -ovn-nbctl lr-add R1
>>>>     -
>>>>     -ovn-nbctl ls-add foo
>>>>     -ovn-nbctl ls-add bar
>>>>     -ovn-nbctl ls-add alice
>>>>     -
>>>>     -ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
>>>>     <http://192.168.1.1/24>
>>>>     -ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
>>>>     <http://192.168.2.1/24>
>>>>     -ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
>>>>     <http://172.16.1.1/24> \
>>>>     -    -- set Logical_Router_Port alice options:redirect-chassis=hv1
>>>>     -
>>>>     -# Connect foo to R1
>>>>     -ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
>>>>     -    type=router options:router-port=foo \
>>>>     -    -- lsp-set-addresses rp-foo router
>>>>     -
>>>>     -# Connect bar to R1
>>>>     -ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
>>>>     -    type=router options:router-port=bar \
>>>>     -    -- lsp-set-addresses rp-bar router
>>>>     -
>>>>     -# Connect alice to R1
>>>>     -ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port
>>>>     rp-alice \
>>>>     -    type=router options:router-port=alice \
>>>>     -    -- lsp-set-addresses rp-alice router
>>>>     -
>>>>     -# Logical port 'foo1' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo1)
>>>>     -ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24
>>>>     <http://192.168.1.2/24>", "f0:00:00:01:02:03", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo1 \
>>>>     --- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
>>>>     -
>>>>     -# Logical port 'foo2' in switch 'foo'.
>>>>     -ADD_NAMESPACES(foo2)
>>>>     -ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24
>>>>     <http://192.168.1.3/24>", "f0:00:00:01:02:06", \
>>>>     -         "192.168.1.1")
>>>>     -ovn-nbctl lsp-add foo foo2 \
>>>>     --- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
>>>>     -
>>>>     -# Logical port 'bar1' in switch 'bar'.
>>>>     -ADD_NAMESPACES(bar1)
>>>>     -ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24
>>>>     <http://192.168.2.2/24>", "f0:00:00:01:02:04", \
>>>>     -         "192.168.2.1")
>>>>     -ovn-nbctl lsp-add bar bar1 \
>>>>     --- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
>>>>     -
>>>>     -# Logical port 'alice1' in switch 'alice'.
>>>>     -ADD_NAMESPACES(alice1)
>>>>     -ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24
>>>>     <http://172.16.1.2/24>", "f0:00:00:01:02:05", \
>>>>     -         "172.16.1.1")
>>>>     -ovn-nbctl lsp-add alice alice1 \
>>>>     --- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>>>>     -
>>>>     -# Add DNAT rules
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3
>>>>     192.168.1.2 foo1 00:00:02:02:03:04])
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4
>>>>     192.168.2.2 bar1 00:00:02:02:03:05])
>>>>     -
>>>>     -# Add a SNAT rule
>>>>     -AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16
>>>>     <http://192.168.0.0/16>])
>>>>     -
>>>>     -ovn-nbctl --wait=hv sync
>>>>     -OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep
>>>>     'nat(src=172.16.1.1)'])
>>>>     -
>>>>     -echo "------ hv dump ------"
>>>>     -ovs-ofctl show br-int
>>>>     -ovs-ofctl dump-flows br-int
>>>>     -echo "---------------------"
>>>>     -
>>>>     -# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
>>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>>     FORMAT_CT(192.168.2.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
>>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>>     FORMAT_CT(192.168.2.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
>>>>     -NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# We verify that no NAT happened via 'dump-conntrack' command.
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack |
>>>>     FORMAT_CT(192.168.2.2) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
>>>>     -])
>>>>     -
>>>>     -# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
>>>>     -NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# Check conntrack entries.  First SNAT of 'foo1' address happens.
>>>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.4) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>> -icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>>>>     -
>>>>     -# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
>>>>     -NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 |
>>>>     FORMAT_PING], \
>>>>     -[0], [dnl
>>>>     -3 packets transmitted, 3 received, 0% packet loss, time 0ms
>>>>     -])
>>>>     -
>>>>     -# Check conntrack entries.  First SNAT of 'foo2' address happens.
>>>>     -# Then DNAT of 'bar1' address happens (listed first below).
>>>>     -AT_CHECK([ovs-appctl dpctl/dump-conntrack | 
>>>> FORMAT_CT(172.16.1.1) | \
>>>>     -sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>>>> -icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>> -icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> 
>>>>
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     -
>>>>     -AT_SETUP([ovn -- 2 LSs IGMP])
>>>>     -AT_KEYWORDS([ovnigmp])
>>>>     -
>>>>     -ovn_start
>>>>     -
>>>>     -OVS_TRAFFIC_VSWITCHD_START()
>>>>     -ADD_BR([br-int])
>>>>     -
>>>>     -# Set external-ids in br-int needed for ovn-controller
>>>>     -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.0.0.1 \
>>>>     -        -- set bridge br-int fail-mode=secure
>>>>     other-config:disable-in-band=true
>>>>     -
>>>>     -# Start ovn-controller
>>>>     -start_daemon ovn-controller
>>>>     -
>>>>     -# Logical network:
>>>>     -# Two independent logical switches (sw1 and sw2).
>>>>     -# sw1:
>>>>     -#   - subnet 10.0.0.0/8 <http://10.0.0.0/8>
>>>>     -#   - 2 ports (sw1-p1 - sw1-p2)
>>>>     -# sw2:
>>>>     -#   - subnet 20.0.0.0/8 <http://20.0.0.0/8>
>>>>     -#   - 2 port (sw2-p1 - sw2-p2)
>>>>     -#   - IGMP Querier from 20.0.0.254
>>>>     -
>>>>     -ovn-nbctl ls-add sw1
>>>>     -ovn-nbctl ls-add sw2
>>>>     -
>>>>     -for i in `seq 1 2`
>>>>     -do
>>>>     -    ADD_NAMESPACES(sw1-p$i)
>>>>     -    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24",
>>>>     "00:00:00:00:01:0$i", \
>>>>     -            "10.0.0.254")
>>>>     -    ovn-nbctl lsp-add sw1 sw1-p$i \
>>>>     -        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 
>>>> 10.0.0.$i"
>>>>     -done
>>>>     -
>>>>     -for i in `seq 1 2`
>>>>     -do
>>>>     -    ADD_NAMESPACES(sw2-p$i)
>>>>     -    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24",
>>>>     "00:00:00:00:02:0$i", \
>>>>     -            "20.0.0.254")
>>>>     -    ovn-nbctl lsp-add sw2 sw2-p$i \
>>>>     -        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 
>>>> 20.0.0.$i"
>>>>     -done
>>>>     -
>>>>     -# Enable IGMP snooping on sw1.
>>>>     -ovn-nbctl set Logical_Switch sw1 
>>>> other_config:mcast_querier="false"
>>>>     -ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
>>>>     -
>>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p1.
>>>>     -NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32
>>>>     <http://239.0.1.68/32> autojoin], [0])
>>>>     -
>>>>     -# Inject IGMP Join for 239.0.1.68 on sw1-p2
>>>>     -NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32
>>>>     <http://239.0.1.68/32> autojoin], [0])
>>>>     -
>>>>     -# Check that the IGMP Group is learned.
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>>>     ":" | wc -w`
>>>>     -    test "${total_entries}" = "1"
>>>>     -    test "${ports}" = "2"
>>>>     -])
>>>>     -
>>>>     -# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
>>>>     -NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32
>>>>     <http://239.0.1.68/32>], [0])
>>>>     -
>>>>     -# Check that only one port is left in the group.
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d
>>>>     ":" | wc -w`
>>>>     -    test "${total_entries}" = "1"
>>>>     -    test "${ports}" = "1"
>>>>     -])
>>>>     -
>>>>     -# Flush IGMP groups.
>>>>     -ovn-sbctl ip-multicast-flush sw1
>>>>     -ovn-nbctl --wait=hv -t 3 sync
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68"
>>>>     | wc -l`
>>>>     -    test "${total_entries}" = "0"
>>>>     -])
>>>>     -
>>>>     -# Enable IGMP snooping and querier on sw2 and set query interval
>>>>     to minimum.
>>>>     -ovn-nbctl set Logical_Switch sw2 \
>>>>     -    other_config:mcast_snoop="true" \
>>>>     -    other_config:mcast_querier="true" \
>>>>     -    other_config:mcast_query_interval=1 \
>>>>     -    other_config:mcast_eth_src="00:00:00:00:02:fe" \
>>>>     -    other_config:mcast_ip4_src="20.0.0.254"
>>>>     -
>>>>     -# Check that queries are generated.
>>>>     -NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp >
>>>>     sw2-p1.pcap &])
>>>>     -
>>>>     -OVS_WAIT_UNTIL([
>>>>     -    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
>>>>     -    test "${total_queries}" = "2"
>>>>     -])
>>>>     -
>>>>     -OVS_APP_EXIT_AND_WAIT([ovn-controller])
>>>>     -
>>>>     -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
>>>>     diff --git a/tests/test-ovn.c b/tests/test-ovn.c
>>>>     deleted file mode 100644
>>>>     index 0b9e824..0000000
>>>>     --- a/tests/test-ovn.c
>>>>     +++ /dev/null
>>>>     @@ -1,1584 +0,0 @@
>>>>     -/*
>>>>     - * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
>>>>     - *
>>>>     - * Licensed under the Apache License, Version 2.0 (the 
>>>> "License");
>>>>     - * you may not use this file except in compliance with the 
>>>> License.
>>>>     - * You may obtain a copy of the License at:
>>>>     - *
>>>>     - * http://www.apache.org/licenses/LICENSE-2.0
>>>>     - *
>>>>     - * Unless required by applicable law or agreed to in writing,
>>>>     software
>>>>     - * distributed under the License is distributed on an "AS IS" 
>>>> BASIS,
>>>>     - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
>>>>     or implied.
>>>>     - * See the License for the specific language governing
>>>>     permissions and
>>>>     - * limitations under the License.
>>>>     - */
>>>>     -
>>>>     -#include <config.h>
>>>>     -#include <errno.h>
>>>>     -#include <getopt.h>
>>>>     -#include <sys/wait.h>
>>>>     -
>>>>     -#include "command-line.h"
>>>>     -#include "dp-packet.h"
>>>>     -#include "fatal-signal.h"
>>>>     -#include "flow.h"
>>>>     -#include "openvswitch/dynamic-string.h"
>>>>     -#include "openvswitch/match.h"
>>>>     -#include "openvswitch/ofp-actions.h"
>>>>     -#include "openvswitch/ofpbuf.h"
>>>>     -#include "openvswitch/vlog.h"
>>>>     -#include "ovn/actions.h"
>>>>     -#include "ovn/expr.h"
>>>>     -#include "ovn/lex.h"
>>>>     -#include "ovn/logical-fields.h"
>>>>     -#include "ovn/lib/ovn-l7.h"
>>>>     -#include "ovn/lib/extend-table.h"
>>>>     -#include "ovs-thread.h"
>>>>     -#include "ovstest.h"
>>>>     -#include "openvswitch/shash.h"
>>>>     -#include "simap.h"
>>>>     -#include "util.h"
>>>>     -
>>>>     -/* --relops: Bitmap of the relational operators to test, in
>>>>     exhaustive test. */
>>>>     -static unsigned int test_relops;
>>>>     -
>>>>     -/* --nvars: Number of numeric variables to test, in exhaustive
>>>>     test. */
>>>>     -static int test_nvars = 2;
>>>>     -
>>>>     -/* --svars: Number of string variables to test, in exhaustive
>>>>     test. */
>>>>     -static int test_svars = 2;
>>>>     -
>>>>     -/* --bits: Number of bits per variable, in exhaustive test. */
>>>>     -static int test_bits = 3;
>>>>     -
>>>>     -/* --operation: The operation to test, in exhaustive test. */
>>>>     -static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW }
>>>>     operation
>>>>     -    = OP_FLOW;
>>>>     -
>>>>     -/* --parallel: Number of parallel processes to use in test. */
>>>>     -static int test_parallel = 1;
>>>>     -
>>>>     -/* -m, --more: Message verbosity */
>>>>     -static int verbosity;
>>>>     -
>>>>     -static void
>>>>     -compare_token(const struct lex_token *a, const struct 
>>>> lex_token *b)
>>>>     -{
>>>>     -    if (a->type != b->type) {
>>>>     -        fprintf(stderr, "type differs: %d -> %d\n", a->type,
>>>>     b->type);
>>>>     -        return;
>>>>     -    }
>>>>     -
>>>>     -    if (!((a->s && b->s && !strcmp(a->s, b->s))
>>>>     -          || (!a->s && !b->s))) {
>>>>     -        fprintf(stderr, "string differs: %s -> %s\n",
>>>>     -                a->s ? a->s : "(null)",
>>>>     -                b->s ? b->s : "(null)");
>>>>     -        return;
>>>>     -    }
>>>>     -
>>>>     -    if (a->type == LEX_T_INTEGER || a->type ==
>>>>     LEX_T_MASKED_INTEGER) {
>>>>     -        if (memcmp(&a->value, &b->value, sizeof a->value)) {
>>>>     -            fprintf(stderr, "value differs\n");
>>>>     -            return;
>>>>     -        }
>>>>     -
>>>>     -        if (a->type == LEX_T_MASKED_INTEGER
>>>>     -            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
>>>>     -            fprintf(stderr, "mask differs\n");
>>>>     -            return;
>>>>     -        }
>>>>     -
>>>>     -        if (a->format != b->format
>>>>     -            && !(a->format == LEX_F_HEXADECIMAL
>>>>     -                 && b->format == LEX_F_DECIMAL
>>>>     -                 && a->value.integer == 0)) {
>>>>     -            fprintf(stderr, "format differs: %d -> %d\n",
>>>>     -                    a->format, b->format);
>>>>     -        }
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    struct ds input;
>>>>     -    struct ds output;
>>>>     -
>>>>     -    ds_init(&input);
>>>>     -    ds_init(&output);
>>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>>     -        struct lexer lexer;
>>>>     -
>>>>     -        lexer_init(&lexer, ds_cstr(&input));
>>>>     -        ds_clear(&output);
>>>>     -        while (lexer_get(&lexer) != LEX_T_END) {
>>>>     -            size_t len = output.length;
>>>>     -            lex_token_format(&lexer.token, &output);
>>>>     -
>>>>     -            /* Check that the formatted version can really be
>>>>     parsed back
>>>>     -             * losslessly. */
>>>>     -            if (lexer.token.type != LEX_T_ERROR) {
>>>>     -                const char *s = ds_cstr(&output) + len;
>>>>     -                struct lexer l2;
>>>>     -
>>>>     -                lexer_init(&l2, s);
>>>>     -                lexer_get(&l2);
>>>>     -                compare_token(&lexer.token, &l2.token);
>>>>     -                lexer_destroy(&l2);
>>>>     -            }
>>>>     -            ds_put_char(&output, ' ');
>>>>     -        }
>>>>     -        lexer_destroy(&lexer);
>>>>     -
>>>>     -        ds_chomp(&output, ' ');
>>>>     -        puts(ds_cstr(&output));
>>>>     -    }
>>>>     -    ds_destroy(&input);
>>>>     -    ds_destroy(&output);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -create_symtab(struct shash *symtab)
>>>>     -{
>>>>     -    ovn_init_symtab(symtab);
>>>>     -
>>>>     -    /* For negative testing. */
>>>>     -    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0,
>>>>     "xyzzy", false);
>>>>     -    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
>>>>     -                          "self_recurse != 0", false);
>>>>     -    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
>>>>     -                          "mutual_recurse_2 != 0", false);
>>>>     -    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
>>>>     -                          "mutual_recurse_1 != 0", false);
>>>>     -    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, 
>>>> NULL);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
>>>>     -                struct hmap *nd_ra_opts,
>>>>     -                struct controller_event_options *event_opts)
>>>>     -{
>>>>     -    hmap_init(dhcp_opts);
>>>>     -    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
>>>>     -    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
>>>>     -    dhcp_opt_add(dhcp_opts, "classless_static_route", 121,
>>>>     "static_routes");
>>>>     -    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
>>>>     -    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
>>>>     -    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
>>>>     -    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
>>>>     -    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
>>>>     -    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
>>>>     -    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
>>>>     -    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
>>>>     -    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
>>>>     -    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
>>>>     -    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
>>>>     -
>>>>     -    /* DHCPv6 options. */
>>>>     -    hmap_init(dhcpv6_opts);
>>>>     -    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
>>>>     -    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
>>>>     -    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
>>>>     -    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
>>>>     -
>>>>     -    /* IPv6 ND RA options. */
>>>>     -    hmap_init(nd_ra_opts);
>>>>     -    nd_ra_opts_init(nd_ra_opts);
>>>>     -
>>>>     -    /* OVN controller events options. */
>>>>     -    controller_event_opts_init(event_opts);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -create_addr_sets(struct shash *addr_sets)
>>>>     -{
>>>>     -    shash_init(addr_sets);
>>>>     -
>>>>     -    static const char *const addrs1[] = {
>>>>     -        "10.0.0.1", "10.0.0.2", "10.0.0.3",
>>>>     -    };
>>>>     -    static const char *const addrs2[] = {
>>>>     -        "::1", "::2", "::3",
>>>>     -    };
>>>>     -    static const char *const addrs3[] = {
>>>>     -        "00:00:00:00:00:01", "00:00:00:00:00:02",
>>>>     "00:00:00:00:00:03",
>>>>     -    };
>>>>     -    static const char *const addrs4[] = { NULL };
>>>>     -
>>>>     -    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
>>>>     -    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
>>>>     -    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
>>>>     -    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -create_port_groups(struct shash *port_groups)
>>>>     -{
>>>>     -    shash_init(port_groups);
>>>>     -
>>>>     -    static const char *const pg1[] = {
>>>>     -        "lsp1", "lsp2", "lsp3",
>>>>     -    };
>>>>     -    static const char *const pg2[] = { NULL };
>>>>     -
>>>>     -    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
>>>>     -    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
>>>>     -}
>>>>     -
>>>>     -static bool
>>>>     -lookup_port_cb(const void *ports_, const char *port_name,
>>>>     unsigned int *portp)
>>>>     -{
>>>>     -    const struct simap *ports = ports_;
>>>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>>>     -    if (!node) {
>>>>     -        return false;
>>>>     -    }
>>>>     -    *portp = node->data;
>>>>     -    return true;
>>>>     -}
>>>>     -
>>>>     -static bool
>>>>     -is_chassis_resident_cb(const void *ports_, const char *port_name)
>>>>     -{
>>>>     -    const struct simap *ports = ports_;
>>>>     -    const struct simap_node *node = simap_find(ports, port_name);
>>>>     -    if (node) {
>>>>     -        return true;
>>>>     -    }
>>>>     -    return false;
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_parse_expr__(int steps)
>>>>     -{
>>>>     -    struct shash symtab;
>>>>     -    struct shash addr_sets;
>>>>     -    struct shash port_groups;
>>>>     -    struct simap ports;
>>>>     -    struct ds input;
>>>>     -
>>>>     -    create_symtab(&symtab);
>>>>     -    create_addr_sets(&addr_sets);
>>>>     -    create_port_groups(&port_groups);
>>>>     -
>>>>     -    simap_init(&ports);
>>>>     -    simap_put(&ports, "eth0", 5);
>>>>     -    simap_put(&ports, "eth1", 6);
>>>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>>>     -    simap_put(&ports, "lsp1", 0x11);
>>>>     -    simap_put(&ports, "lsp2", 0x12);
>>>>     -    simap_put(&ports, "lsp3", 0x13);
>>>>     -
>>>>     -    ds_init(&input);
>>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>>     -        struct expr *expr;
>>>>     -        char *error;
>>>>     -
>>>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab,
>>>>     &addr_sets,
>>>>     -                                 &port_groups, NULL, &error);
>>>>     -        if (!error && steps > 0) {
>>>>     -            expr = expr_annotate(expr, &symtab, &error);
>>>>     -      �� }
>>>>     -        if (!error) {
>>>>     -            if (steps > 1) {
>>>>     -                expr = expr_simplify(expr,
>>>>     is_chassis_resident_cb, &ports);
>>>>     -            }
>>>>     -            if (steps > 2) {
>>>>     -                expr = expr_normalize(expr);
>>>>     -                ovs_assert(expr_is_normalized(expr));
>>>>     -            }
>>>>     -        }
>>>>     -        if (!error) {
>>>>     -            if (steps > 3) {
>>>>     -                struct hmap matches;
>>>>     -
>>>>     -                expr_to_matches(expr, lookup_port_cb, &ports,
>>>>     &matches);
>>>>     -                expr_matches_print(&matches, stdout);
>>>>     -                expr_matches_destroy(&matches);
>>>>     -            } else {
>>>>     -                struct ds output = DS_EMPTY_INITIALIZER;
>>>>     -                expr_format(expr, &output);
>>>>     -                puts(ds_cstr(&output));
>>>>     -                ds_destroy(&output);
>>>>     -            }
>>>>     -        } else {
>>>>     -            puts(error);
>>>>     -            free(error);
>>>>     -        }
>>>>     -        expr_destroy(expr);
>>>>     -    }
>>>>     -    ds_destroy(&input);
>>>>     -
>>>>     -    simap_destroy(&ports);
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -    expr_const_sets_destroy(&addr_sets);
>>>>     -    shash_destroy(&addr_sets);
>>>>     -    expr_const_sets_destroy(&port_groups);
>>>>     -    shash_destroy(&port_groups);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    test_parse_expr__(0);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    test_parse_expr__(1);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    test_parse_expr__(2);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    test_parse_expr__(3);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    test_parse_expr__(4);
>>>>     -}
>>>>     -
>>>>     -/* Print the symbol table. */
>>>>     -
>>>>     -static void
>>>>     -test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    struct shash symtab;
>>>>     -    create_symtab(&symtab);
>>>>     -
>>>>     -    const struct shash_node **nodes = shash_sort(&symtab);
>>>>     -    for (size_t i = 0; i < shash_count(&symtab); i++) {
>>>>     -        const struct expr_symbol *symbol = nodes[i]->data;
>>>>     -        struct ds s = DS_EMPTY_INITIALIZER;
>>>>     -        expr_symbol_format(symbol, &s);
>>>>     -        puts(ds_cstr(&s));
>>>>     -        ds_destroy(&s);
>>>>     -    }
>>>>     -
>>>>     -    free(nodes);
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -}
>>>>     -
>>>>     -/* Evaluate an expression. */
>>>>     -
>>>>     -static bool
>>>>     -lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
>>>>     -               unsigned int *portp)
>>>>     -{
>>>>     -    *portp = atoi(port_name);
>>>>     -    return true;
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_evaluate_expr(struct ovs_cmdl_context *ctx)
>>>>     -{
>>>>     -    struct shash symtab;
>>>>     -    struct ds input;
>>>>     -
>>>>     -    ovn_init_symtab(&symtab);
>>>>     -
>>>>     -    struct flow uflow;
>>>>     -    char *error = expr_parse_microflow(ctx->argv[1], &symtab,
>>>>     NULL, NULL,
>>>>     -                                       lookup_atoi_cb, NULL, 
>>>> &uflow);
>>>>     -    if (error) {
>>>>     -        ovs_fatal(0, "%s", error);
>>>>     -    }
>>>>     -
>>>>     -    ds_init(&input);
>>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>>     -        struct expr *expr;
>>>>     -
>>>>     -        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL,
>>>>     NULL, NULL,
>>>>     -                                 &error);
>>>>     -        if (!error) {
>>>>     -            expr = expr_annotate(expr, &symtab, &error);
>>>>     -        }
>>>>     -        if (!error) {
>>>>     -            printf("%d\n", expr_evaluate(expr, &uflow,
>>>>     lookup_atoi_cb, NULL));
>>>>     -        } else {
>>>>     -            puts(error);
>>>>     -            free(error);
>>>>     -        }
>>>>     -        expr_destroy(expr);
>>>>     -    }
>>>>     -    ds_destroy(&input);
>>>>     -
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -}
>>>>     -
>>>>     -/* Compositions.
>>>>     - *
>>>>     - * The "compositions" of a positive integer N are all of the ways
>>>>     that one can
>>>>     - * add up positive integers to sum to N.  For example, the
>>>>     compositions of 3
>>>>     - * are 3, 2+1, 1+2, and 1+1+1.
>>>>     - *
>>>>     - * We use compositions to find all the ways to break up N terms
>>>>     of a Boolean
>>>>     - * expression into subexpressions.  Suppose we want to generate
>>>>     all expressions
>>>>     - * with 3 terms.  The compositions of 3 (ignoring 3 itself)
>>>>     provide the
>>>>     - * possibilities (x && x) || x, x || (x && x), and x || x || x.
>>>>     (Of course one
>>>>     - * can exchange && for || in each case.)  One must recursively
>>>>     compose the
>>>>     - * sub-expressions whose values are 3 or greater; that is what
>>>>     the "tree shape"
>>>>     - * concept later covers.
>>>>     - *
>>>>     - * To iterate through all compositions of, e.g., 5:
>>>>     - *
>>>>     - *     unsigned int state;
>>>>     - *     int s[5];
>>>>     - *     int n;
>>>>     - *
>>>>     - *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n 
>>>> > 0;
>>>>     - *          n = next_composition(&state, s, n)) {
>>>>     - *          // Do something with composition 's' with 'n' 
>>>> elements.
>>>>     - *     }
>>>>     - *
>>>>     - * Algorithm from D. E. Knuth, _The Art of Computer Programming,
>>>>     Vol. 4A:
>>>>     - * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to
>>>>     exercise
>>>>     - * 12(a).
>>>>     - */
>>>>     -
>>>>     -/* Begins iteration through the compositions of 'n'. Initializes
>>>>     's' to the
>>>>     - * number of elements in the first composition of 'n' and returns
>>>>     that number
>>>>     - * of elements.  The first composition in fact is always 'n'
>>>>     itself, so the
>>>>     - * return value will be 1.
>>>>     - *
>>>>     - * Initializes '*state' to some internal state information.  The
>>>>     caller must
>>>>     - * maintain this state (and 's') for use by next_composition().
>>>>     - *
>>>>     - * 's' must have room for at least 'n' elements. */
>>>>     -static int
>>>>     -first_composition(int n, unsigned int *state, int s[])
>>>>     -{
>>>>     -    *state = 0;
>>>>     -    s[0] = n;
>>>>     -    return 1;
>>>>     -}
>>>>     -
>>>>     -/* Advances 's', with 'sn' elements, to the next composition and
>>>>     returns the
>>>>     - * number of elements in this new composition, or 0 if no
>>>>     compositions are
>>>>     - * left.  'state' is the same internal state passed to
>>>>     first_composition(). */
>>>>     -static int
>>>>     -next_composition(unsigned int *state, int s[], int sn)
>>>>     -{
>>>>     -    int j = sn - 1;
>>>>     -    if (++*state & 1) {
>>>>     -        if (s[j] > 1) {
>>>>     -            s[j]--;
>>>>     -            s[j + 1] = 1;
>>>>     -            j++;
>>>>     -        } else {
>>>>     -            j--;
>>>>     -            s[j]++;
>>>>     -        }
>>>>     -    } else {
>>>>     -        if (s[j - 1] > 1) {
>>>>     -            s[j - 1]--;
>>>>     -            s[j + 1] = s[j];
>>>>     -            s[j] = 1;
>>>>     -            j++;
>>>>     -        } else {
>>>>     -            j--;
>>>>     -            if (!j) {
>>>>     -                return 0;
>>>>     -            }
>>>>     -            s[j] = s[j + 1];
>>>>     -            s[j - 1]++;
>>>>     -        }
>>>>     -    }
>>>>     -    return j + 1;
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_composition(struct ovs_cmdl_context *ctx)
>>>>     -{
>>>>     -    int n = atoi(ctx->argv[1]);
>>>>     -    unsigned int state;
>>>>     -    int s[50];
>>>>     -
>>>>     -    for (int sn = first_composition(n, &state, s); sn;
>>>>     -         sn = next_composition(&state, s, sn)) {
>>>>     -        for (int i = 0; i < sn; i++) {
>>>>     -            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
>>>>     -        }
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -/* Tree shapes.
>>>>     - *
>>>>     - * This code generates all possible Boolean expressions with a
>>>>     specified number
>>>>     - * of terms N (equivalent to the number of external nodes in a 
>>>> tree).
>>>>     - *
>>>>     - * See test_tree_shape() for a simple example. */
>>>>     -
>>>>     -/* An array of these structures describes the shape of a tree.
>>>>     - *
>>>>     - * A single element of struct tree_shape describes a single node
>>>>     in the tree.
>>>>     - * The node has 'sn' direct children.  From left to right, for i
>>>>     in 0...sn-1,
>>>>     - * s[i] is 1 if the child is a leaf node, otherwise the child is
>>>>     a subtree and
>>>>     - * s[i] is the number of leaf nodes within that subtree. In the
>>>>     latter case,
>>>>     - * the subtree is described by another struct tree_shape within
>>>>     the enclosing
>>>>     - * array.  The tree_shapes are ordered in the array in in-order.
>>>>     - */
>>>>     -struct tree_shape {
>>>>     -    unsigned int state;
>>>>     -    int s[50];
>>>>     -    int sn;
>>>>     -};
>>>>     -
>>>>     -static int
>>>>     -init_tree_shape__(struct tree_shape ts[], int n)
>>>>     -{
>>>>     -    if (n <= 2) {
>>>>     -        return 0;
>>>>     -    }
>>>>     -
>>>>     -    int n_tses = 1;
>>>>     -    /* Skip the first composition intentionally. */
>>>>     -    ts->sn = first_composition(n, &ts->state, ts->s);
>>>>     -    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
>>>>     -    for (int i = 0; i < ts->sn; i++) {
>>>>     -        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
>>>>     -    }
>>>>     -    return n_tses;
>>>>     -}
>>>>     -
>>>>     -/* Initializes 'ts[]' as the first in the set of all of possible
>>>>     shapes of
>>>>     - * trees with 'n' leaves.  Returns the number of "struct
>>>>     tree_shape"s in the
>>>>     - * first tree shape. */
>>>>     -static int
>>>>     -init_tree_shape(struct tree_shape ts[], int n)
>>>>     -{
>>>>     -    switch (n) {
>>>>     -    case 1:
>>>>     -        ts->sn = 1;
>>>>     -        ts->s[0] = 1;
>>>>     -        return 1;
>>>>     -    case 2:
>>>>     -        ts->sn = 2;
>>>>     -        ts->s[0] = 1;
>>>>     -        ts->s[1] = 1;
>>>>     -        return 1;
>>>>     -    default:
>>>>     -        return init_tree_shape__(ts, n);
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -/* Advances 'ts', which currently has 'n_tses' elements, to the
>>>>     next possible
>>>>     - * tree shape with the number of leaves passed to
>>>>     init_tree_shape().  Returns
>>>>     - * the number of "struct tree_shape"s in the next shape, or 0 if
>>>>     all tree
>>>>     - * shapes have been visited. */
>>>>     -static int
>>>>     -next_tree_shape(struct tree_shape ts[], int n_tses)
>>>>     -{
>>>>     -    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1]
>>>>     == 1) {
>>>>     -        return 0;
>>>>     -    }
>>>>     -    while (n_tses > 0) {
>>>>     -        struct tree_shape *p = &ts[n_tses - 1];
>>>>     -        p->sn = p->sn > 1 ? next_composition(&p->state, p->s,
>>>>     p->sn) : 0;
>>>>     -        if (p->sn) {
>>>>     -            for (int i = 0; i < p->sn; i++) {
>>>>     -                n_tses += init_tree_shape__(&ts[n_tses], 
>>>> p->s[i]);
>>>>     -            }
>>>>     -            break;
>>>>     -        }
>>>>     -        n_tses--;
>>>>     -    }
>>>>     -    return n_tses;
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -print_tree_shape(const struct tree_shape ts[], int n_tses)
>>>>     -{
>>>>     -    for (int i = 0; i < n_tses; i++) {
>>>>     -        if (i) {
>>>>     -            printf(", ");
>>>>     -        }
>>>>     -        for (int j = 0; j < ts[i].sn; j++) {
>>>>     -            int k = ts[i].s[j];
>>>>     -            if (k > 9) {
>>>>     -                printf("(%d)", k);
>>>>     -            } else {
>>>>     -                printf("%d", k);
>>>>     -            }
>>>>     -        }
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_tree_shape(struct ovs_cmdl_context *ctx)
>>>>     -{
>>>>     -    int n = atoi(ctx->argv[1]);
>>>>     -    struct tree_shape ts[50];
>>>>     -    int n_tses;
>>>>     -
>>>>     -    for (n_tses = init_tree_shape(ts, n); n_tses;
>>>>     -         n_tses = next_tree_shape(ts, n_tses)) {
>>>>     -        print_tree_shape(ts, n_tses);
>>>>     -        putchar('\n');
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -/* Iteration through all possible terminal expressions (e.g.
>>>>     EXPR_T_CMP and
>>>>     - * EXPR_T_BOOLEAN expressions).
>>>>     - *
>>>>     - * Given a tree shape, this allows the code to try all possible
>>>>     ways to plug in
>>>>     - * terms.
>>>>     - *
>>>>     - * Example use:
>>>>     - *
>>>>     - *     struct expr terminal;
>>>>     - *     const struct expr_symbol *vars = ...;
>>>>     - *     int n_vars = ...;
>>>>     - *     int n_bits = ...;
>>>>     - *
>>>>     - *     init_terminal(&terminal, vars[0]);
>>>>     - *     do {
>>>>     - *         // Something with 'terminal'.
>>>>     - *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
>>>>     - */
>>>>     -
>>>>     -/* Sets 'expr' to the first possible terminal expression. 'var'
>>>>     should be the
>>>>     - * first variable in the ones to be tested. */
>>>>     -static void
>>>>     -init_terminal(struct expr *expr, int phase,
>>>>     -              const struct expr_symbol *nvars[], int n_nvars,
>>>>     -              const struct expr_symbol *svars[], int n_svars)
>>>>     -{
>>>>     -    if (phase < 1 && n_nvars) {
>>>>     -        expr->type = EXPR_T_CMP;
>>>>     -        expr->cmp.symbol = nvars[0];
>>>>     -        expr->cmp.relop = rightmost_1bit_idx(test_relops);
>>>>     -        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
>>>>     -        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
>>>>     -        expr->cmp.value.integer = htonll(0);
>>>>     -        expr->cmp.mask.integer = htonll(0);
>>>>     -        return;
>>>>     -    }
>>>>     -
>>>>     -    if (phase < 2 && n_svars) {
>>>>     -        expr->type = EXPR_T_CMP;
>>>>     -        expr->cmp.symbol = svars[0];
>>>>     -        expr->cmp.relop = EXPR_R_EQ;
>>>>     -        expr->cmp.string = xstrdup("0");
>>>>     -        return;
>>>>     -    }
>>>>     -
>>>>     -    expr->type = EXPR_T_BOOLEAN;
>>>>     -    expr->boolean = false;
>>>>     -}
>>>>     -
>>>>     -/* Returns 'x' with the rightmost contiguous string of 1s changed
>>>>     to 0s,
>>>>     - * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's
>>>>     Delight_, 2nd
>>>>     - * ed., section 2-1. */
>>>>     -static unsigned int
>>>>     -turn_off_rightmost_1s(unsigned int x)
>>>>     -{
>>>>     -    return ((x & -x) + x) & x;
>>>>     -}
>>>>     -
>>>>     -static const struct expr_symbol *
>>>>     -next_var(const struct expr_symbol *symbol,
>>>>     -         const struct expr_symbol *vars[], int n_vars)
>>>>     -{
>>>>     -    for (int i = 0; i < n_vars; i++) {
>>>>     -        if (symbol == vars[i]) {
>>>>     -            return i + 1 >= n_vars ? NULL : vars[i + 1];
>>>>     -        }
>>>>     -    }
>>>>     -    OVS_NOT_REACHED();
>>>>     -}
>>>>     -
>>>>     -static enum expr_relop
>>>>     -next_relop(enum expr_relop relop)
>>>>     -{
>>>>     -    unsigned int remaining_relops = test_relops & ~((1u << (relop
>>>>     + 1)) - 1);
>>>>     -    return (remaining_relops
>>>>     -            ? rightmost_1bit_idx(remaining_relops)
>>>>     -            : rightmost_1bit_idx(test_relops));
>>>>     -}
>>>>     -
>>>>     -/* Advances 'expr' to the next possible terminal expression
>>>>     within the 'n_vars'
>>>>     - * variables of 'n_bits' bits each in 'vars[]'. */
>>>>     -static bool
>>>>     -next_terminal(struct expr *expr,
>>>>     -              const struct expr_symbol *nvars[], int n_nvars, int
>>>>     n_bits,
>>>>     -              const struct expr_symbol *svars[], int n_svars)
>>>>     -{
>>>>     -    if (expr->type == EXPR_T_BOOLEAN) {
>>>>     -        if (expr->boolean) {
>>>>     -            return false;
>>>>     -        } else {
>>>>     -            expr->boolean = true;
>>>>     -            return true;
>>>>     -        }
>>>>     -    }
>>>>     -
>>>>     -    if (!expr->cmp.symbol->width) {
>>>>     -        int next_value = atoi(expr->cmp.string) + 1;
>>>>     -        free(expr->cmp.string);
>>>>     -        if (next_value > 1) {
>>>>     -            expr->cmp.symbol = next_var(expr->cmp.symbol, svars,
>>>>     n_svars);
>>>>     -            if (!expr->cmp.symbol) {
>>>>     -                init_terminal(expr, 2, nvars, n_nvars, svars,
>>>>     n_svars);
>>>>     -                return true;
>>>>     -            }
>>>>     -            next_value = 0;
>>>>     -        }
>>>>     -        expr->cmp.string = xasprintf("%d", next_value);
>>>>     -        return true;
>>>>     -    }
>>>>     -
>>>>     -    unsigned int next;
>>>>     -
>>>>     -    next = (ntohll(expr->cmp.value.integer)
>>>>     -            + (ntohll(expr->cmp.mask.integer) << n_bits));
>>>>     -    for (;;) {
>>>>     -        next++;
>>>>     -        unsigned m = next >> n_bits;
>>>>     -        unsigned v = next & ((1u << n_bits) - 1);
>>>>     -        if (next >= (1u << (2 * n_bits))) {
>>>>     -            enum expr_relop old_relop = expr->cmp.relop;
>>>>     -            expr->cmp.relop = next_relop(old_relop);
>>>>     -            if (expr->cmp.relop <= old_relop) {
>>>>     -                expr->cmp.symbol = next_var(expr->cmp.symbol,
>>>>     nvars, n_nvars);
>>>>     -                if (!expr->cmp.symbol) {
>>>>     -                    init_terminal(expr, 1, nvars, n_nvars, svars,
>>>>     n_svars);
>>>>     -                    return true;
>>>>     -                }
>>>>     -            }
>>>>     -            next = UINT_MAX;
>>>>     -        } else if (v & ~m) {
>>>>     -            /* Skip: 1-bits in value correspond to 0-bits in 
>>>> mask. */
>>>>     -        } else if ((!m || turn_off_rightmost_1s(m))
>>>>     -                   && (expr->cmp.relop != EXPR_R_EQ &&
>>>>     -                       expr->cmp.relop != EXPR_R_NE)) {
>>>>     -            /* Skip: can't have discontiguous or all-0 mask for >
>>>>     >= < <=. */
>>>>     -        } else {
>>>>     -            expr->cmp.value.integer = htonll(v);
>>>>     -            expr->cmp.mask.integer = htonll(m);
>>>>     -            return true;
>>>>     -        }
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -static struct expr *
>>>>     -make_terminal(struct expr ***terminalp)
>>>>     -{
>>>>     -    struct expr *e = expr_create_boolean(true);
>>>>     -    **terminalp = e;
>>>>     -    (*terminalp)++;
>>>>     -    return e;
>>>>     -}
>>>>     -
>>>>     -static struct expr *
>>>>     -build_simple_tree(enum expr_type type, int n, struct expr
>>>>     ***terminalp)
>>>>     -{
>>>>     -    if (n == 2) {
>>>>     -        struct expr *e = expr_create_andor(type);
>>>>     -        for (int i = 0; i < 2; i++) {
>>>>     -            struct expr *sub = make_terminal(terminalp);
>>>>     -            ovs_list_push_back(&e->andor, &sub->node);
>>>>     -        }
>>>>     -        return e;
>>>>     -    } else if (n == 1) {
>>>>     -        return make_terminal(terminalp);
>>>>     -    } else {
>>>>     -        OVS_NOT_REACHED();
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -static struct expr *
>>>>     -build_tree_shape(enum expr_type type, const struct tree_shape 
>>>> **tsp,
>>>>     -                 struct expr ***terminalp)
>>>>     -{
>>>>     -    const struct tree_shape *ts = *tsp;
>>>>     -    (*tsp)++;
>>>>     -
>>>>     -    struct expr *e = expr_create_andor(type);
>>>>     -    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : 
>>>> EXPR_T_AND;
>>>>     -    for (int i = 0; i < ts->sn; i++) {
>>>>     -        struct expr *sub = (ts->s[i] > 2
>>>>     -                            ? build_tree_shape(t, tsp, terminalp)
>>>>     -                            : build_simple_tree(t, ts->s[i],
>>>>     terminalp));
>>>>     -        ovs_list_push_back(&e->andor, &sub->node);
>>>>     -    }
>>>>     -    return e;
>>>>     -}
>>>>     -
>>>>     -struct test_rule {
>>>>     -    struct cls_rule cr;
>>>>     -};
>>>>     -
>>>>     -static void
>>>>     -free_rule(struct test_rule *test_rule)
>>>>     -{
>>>>     -    cls_rule_destroy(&test_rule->cr);
>>>>     -    free(test_rule);
>>>>     -}
>>>>     -
>>>>     -static bool
>>>>     -tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
>>>>     -                                  const char *port_name 
>>>> OVS_UNUSED)
>>>>     -{
>>>>     -    return true;
>>>>     -}
>>>>     -
>>>>     -static int
>>>>     -test_tree_shape_exhaustively(struct expr *expr, struct shash 
>>>> *symtab,
>>>>     -                             struct expr *terminals[], int
>>>>     n_terminals,
>>>>     -                             const struct expr_symbol *nvars[],
>>>>     int n_nvars,
>>>>     -                             int n_bits,
>>>>     -                             const struct expr_symbol *svars[],
>>>>     int n_svars)
>>>>     -{
>>>>     -    int n_tested = 0;
>>>>     -
>>>>     -    const unsigned int var_mask = (1u << n_bits) - 1;
>>>>     -    for (int i = 0; i < n_terminals; i++) {
>>>>     -        init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>>>     n_svars);
>>>>     -    }
>>>>     -
>>>>     -    struct ds s = DS_EMPTY_INITIALIZER;
>>>>     -    struct flow f;
>>>>     -    memset(&f, 0, sizeof f);
>>>>     -    for (;;) {
>>>>     -        for (int i = n_terminals - 1; ; i--) {
>>>>     -            if (!i) {
>>>>     -                ds_destroy(&s);
>>>>     -                return n_tested;
>>>>     -            }
>>>>     -            if (next_terminal(terminals[i], nvars, n_nvars, 
>>>> n_bits,
>>>>     -                              svars, n_svars)) {
>>>>     -                break;
>>>>  ��  -            }
>>>>     -            init_terminal(terminals[i], 0, nvars, n_nvars, svars,
>>>>     n_svars);
>>>>     -        }
>>>>     -        ovs_assert(expr_honors_invariants(expr));
>>>>     -
>>>>     -        n_tested++;
>>>>     -
>>>>     -        struct expr *modified;
>>>>     -        if (operation == OP_CONVERT) {
>>>>     -            ds_clear(&s);
>>>>     -            expr_format(expr, &s);
>>>>     -
>>>>     -            char *error;
>>>>     -            modified = expr_parse_string(ds_cstr(&s), symtab, 
>>>> NULL,
>>>>     -                                         NULL, NULL, &error);
>>>>     -            if (error) {
>>>>     -                fprintf(stderr, "%s fails to parse (%s)\n",
>>>>     -                        ds_cstr(&s), error);
>>>>     -                exit(EXIT_FAILURE);
>>>>     -            }
>>>>     -        } else if (operation >= OP_SIMPLIFY) {
>>>>     -            modified = expr_simplify(expr_clone(expr),
>>>>     -  tree_shape_is_chassis_resident_cb,
>>>>     -                                     NULL);
>>>>     - ovs_assert(expr_honors_invariants(modified));
>>>>     -
>>>>     -            if (operation >= OP_NORMALIZE) {
>>>>     -                modified = expr_normalize(modified);
>>>>     - ovs_assert(expr_honors_invariants(modified));
>>>>     - ovs_assert(expr_is_normalized(modified));
>>>>     -            }
>>>>     -        }
>>>>     -
>>>>     -        struct hmap matches;
>>>>     -        struct classifier cls;
>>>>     -        if (operation >= OP_FLOW) {
>>>>     -            struct expr_match *m;
>>>>     -            struct test_rule *test_rule;
>>>>     -
>>>>     -            expr_to_matches(modified, lookup_atoi_cb, NULL,
>>>>     &matches);
>>>>     -
>>>>     -            classifier_init(&cls, NULL);
>>>>     -            HMAP_FOR_EACH (m, hmap_node, &matches) {
>>>>     -                test_rule = xmalloc(sizeof *test_rule);
>>>>     -                cls_rule_init(&test_rule->cr, &m->match, 0);
>>>>     -                classifier_insert(&cls, &test_rule->cr,
>>>>     OVS_VERSION_MIN,
>>>>     -                                  m->conjunctions, m->n);
>>>>     -            }
>>>>     -        }
>>>>     -        for (int subst = 0; subst < 1 << (n_bits * n_nvars +
>>>>     n_svars);
>>>>     -             subst++) {
>>>>     -            for (int i = 0; i < n_nvars; i++) {
>>>>     -                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
>>>>     -            }
>>>>     -            for (int i = 0; i < n_svars; i++) {
>>>>     -                f.regs[n_nvars + i] = ((subst >> (n_nvars *
>>>>     n_bits + i))
>>>>     -                                       & 1);
>>>>     -            }
>>>>     -
>>>>     -            bool expected = expr_evaluate(expr, &f,
>>>>     lookup_atoi_cb, NULL);
>>>>     -            bool actual = expr_evaluate(modified, &f,
>>>>     lookup_atoi_cb, NULL);
>>>>     -            if (actual != expected) {
>>>>     -                struct ds expr_s, modified_s;
>>>>     -
>>>>     -                ds_init(&expr_s);
>>>>     -                expr_format(expr, &expr_s);
>>>>     -
>>>>     -                ds_init(&modified_s);
>>>>     -                expr_format(modified, &modified_s);
>>>>     -
>>>>     -                fprintf(stderr,
>>>>     -                        "%s evaluates to %d, but %s evaluates to
>>>>     %d, for",
>>>>     -                        ds_cstr(&expr_s), expected,
>>>>     -                        ds_cstr(&modified_s), actual);
>>>>     -                for (int i = 0; i < n_nvars; i++) {
>>>>     -                    if (i > 0) {
>>>>     -                        fputs(",", stderr);
>>>>     -                    }
>>>>     -                    fprintf(stderr, " n%d = 0x%x", i,
>>>>     -                            (subst >> (n_bits * i)) & var_mask);
>>>>     -                }
>>>>     -                for (int i = 0; i < n_svars; i++) {
>>>>     -                    fprintf(stderr, ", s%d = \"%d\"", i,
>>>>     -                            (subst >> (n_bits * n_nvars + i)) 
>>>> & 1);
>>>>     -                }
>>>>     -                putc('\n', stderr);
>>>>     -                exit(EXIT_FAILURE);
>>>>     -            }
>>>>     -
>>>>     -            if (operation >= OP_FLOW) {
>>>>     -                bool found = classifier_lookup(&cls, 
>>>> OVS_VERSION_MIN,
>>>>     -                                               &f, NULL) != NULL;
>>>>     -                if (expected != found) {
>>>>     -                    struct ds expr_s, modified_s;
>>>>     -
>>>>     -                    ds_init(&expr_s);
>>>>     -                    expr_format(expr, &expr_s);
>>>>     -
>>>>     -                    ds_init(&modified_s);
>>>>     -                    expr_format(modified, &modified_s);
>>>>     -
>>>>     -                    fprintf(stderr,
>>>>     -                            "%s and %s evaluate to %d, for",
>>>>     -                            ds_cstr(&expr_s),
>>>>     ds_cstr(&modified_s), expected);
>>>>     -                    for (int i = 0; i < n_nvars; i++) {
>>>>     -                        if (i > 0) {
>>>>     -                            fputs(",", stderr);
>>>>     -                        }
>>>>     -                        fprintf(stderr, " n%d = 0x%x", i,
>>>>     -                                (subst >> (n_bits * i)) & 
>>>> var_mask);
>>>>     -                    }
>>>>     -                    for (int i = 0; i < n_svars; i++) {
>>>>     -                        fprintf(stderr, ", s%d = \"%d\"", i,
>>>>     -                                (subst >> (n_bits * n_nvars + i))
>>>>     & 1);
>>>>     -                    }
>>>>     -                    fputs(".\n", stderr);
>>>>     -
>>>>     -                    fprintf(stderr, "Converted to 
>>>> classifier:\n");
>>>>     -                    expr_matches_print(&matches, stderr);
>>>>     -                    fprintf(stderr,
>>>>     -                            "However, %s flow was found in the
>>>>     classifier.\n",
>>>>     -                            found ? "a" : "no");
>>>>     -                    exit(EXIT_FAILURE);
>>>>     -                }
>>>>     -            }
>>>>     -        }
>>>>     -        if (operation >= OP_FLOW) {
>>>>     -            struct test_rule *test_rule;
>>>>     -
>>>>     -            CLS_FOR_EACH (test_rule, cr, &cls) {
>>>>     -                classifier_remove_assert(&cls, &test_rule->cr);
>>>>     -                ovsrcu_postpone(free_rule, test_rule);
>>>>     -            }
>>>>     -            classifier_destroy(&cls);
>>>>     -            ovsrcu_quiesce();
>>>>     -
>>>>     -            expr_matches_destroy(&matches);
>>>>     -        }
>>>>     -        expr_destroy(modified);
>>>>     -    }
>>>>     -}
>>>>     -
>>>>     -#ifndef _WIN32
>>>>     -static void
>>>>     -wait_pid(pid_t *pids, int *n)
>>>>     -{
>>>>     -    int status;
>>>>     -    pid_t pid;
>>>>     -
>>>>     -    pid = waitpid(-1, &status, 0);
>>>>     -    if (pid < 0) {
>>>>     -        ovs_fatal(errno, "waitpid failed");
>>>>     -    } else if (WIFEXITED(status)) {
>>>>     -        if (WEXITSTATUS(status)) {
>>>>     -            exit(WEXITSTATUS(status));
>>>>     -        }
>>>>     -    } else if (WIFSIGNALED(status)) {
>>>>     -        raise(WTERMSIG(status));
>>>>     -        exit(1);
>>>>     -    } else {
>>>>     -        OVS_NOT_REACHED();
>>>>     -    }
>>>>     -
>>>>     -    for (int i = 0; i < *n; i++) {
>>>>     -        if (pids[i] == pid) {
>>>>     -            pids[i] = pids[--*n];
>>>>     -            return;
>>>>     -        }
>>>>     -    }
>>>>     -    ovs_fatal(0, "waitpid returned unknown child");
>>>>     -}
>>>>     -#endif
>>>>     -
>>>>     -static void
>>>>     -test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    int n_terminals = atoi(ctx->argv[1]);
>>>>     -    struct tree_shape ts[50];
>>>>     -    int n_tses;
>>>>     -
>>>>     -    struct shash symtab;
>>>>     -    const struct expr_symbol *nvars[4];
>>>>     -    const struct expr_symbol *svars[4];
>>>>     -
>>>>     -    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
>>>>     -    ovs_assert(test_svars <= ARRAY_SIZE(svars));
>>>>     -    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
>>>>     -
>>>>     -    shash_init(&symtab);
>>>>     -    for (int i = 0; i < test_nvars; i++) {
>>>>     -        char *name = xasprintf("n%d", i);
>>>>     -        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0
>>>>     + i, NULL,
>>>>     -                                         false);
>>>>     -        free(name);
>>>>     -    }
>>>>     -    for (int i = 0; i < test_svars; i++) {
>>>>     -        char *name = xasprintf("s%d", i);
>>>>     -        svars[i] = expr_symtab_add_string(&symtab, name,
>>>>     -                                          MFF_REG0 + test_nvars +
>>>>     i, NULL);
>>>>     -        free(name);
>>>>     -    }
>>>>     -
>>>>     -#ifndef _WIN32
>>>>     -    pid_t *children = xmalloc(test_parallel * sizeof *children);
>>>>     -    int n_children = 0;
>>>>     -#endif
>>>>     -
>>>>     -    int n_tested = 0;
>>>>     -    for (int i = 0; i < 2; i++) {
>>>>     -        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
>>>>     -
>>>>     -        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
>>>>     -             n_tses = next_tree_shape(ts, n_tses)) {
>>>>     -            const struct tree_shape *tsp = ts;
>>>>     -            struct expr *terminals[50];
>>>>     -            struct expr **terminalp = terminals;
>>>>     -            struct expr *expr = build_tree_shape(base_type, &tsp,
>>>>     &terminalp);
>>>>     -            ovs_assert(terminalp == &terminals[n_terminals]);
>>>>     -
>>>>     -            if (verbosity > 0) {
>>>>     -                print_tree_shape(ts, n_tses);
>>>>     -                printf(": ");
>>>>     -                struct ds s = DS_EMPTY_INITIALIZER;
>>>>     -                expr_format(expr, &s);
>>>>     -                puts(ds_cstr(&s));
>>>>     -                ds_destroy(&s);
>>>>     -            }
>>>>     -
>>>>     -#ifndef _WIN32
>>>>     -            if (test_parallel > 1) {
>>>>     -                pid_t pid = xfork();
>>>>     -                if (!pid) {
>>>>     -                    test_tree_shape_exhaustively(expr, &symtab,
>>>>     -  terminals,
>>>>     n_terminals,
>>>>     -                                                 nvars,
>>>>     test_nvars, test_bits,
>>>>     -                                                 svars, 
>>>> test_svars);
>>>>     -                    expr_destroy(expr);
>>>>     -                    exit(0);
>>>>     -                } else {
>>>>     -                    if (n_children >= test_parallel) {
>>>>     -                        wait_pid(children, &n_children);
>>>>     -                    }
>>>>     -                    children[n_children++] = pid;
>>>>     -                }
>>>>     -            } else
>>>>     -#endif
>>>>     -            {
>>>>     -                n_tested += test_tree_shape_exhaustively(
>>>>     -                    expr, &symtab, terminals, n_terminals,
>>>>     -                    nvars, test_nvars, test_bits,
>>>>     -                    svars, test_svars);
>>>>     -            }
>>>>     -            expr_destroy(expr);
>>>>     -        }
>>>>     -    }
>>>>     -#ifndef _WIN32
>>>>     -    while (n_children > 0) {
>>>>     -        wait_pid(children, &n_children);
>>>>     -    }
>>>>     -    free(children);
>>>>     -#endif
>>>>     -
>>>>     -    printf("Tested ");
>>>>     -    switch (operation) {
>>>>     -    case OP_CONVERT:
>>>>     -        printf("converting");
>>>>     -        break;
>>>>     -    case OP_SIMPLIFY:
>>>>     -        printf("simplifying");
>>>>     -        break;
>>>>     -    case OP_NORMALIZE:
>>>>     -        printf("normalizing");
>>>>     -        break;
>>>>     -    case OP_FLOW:
>>>>     -        printf("converting to flows");
>>>>     -        break;
>>>>     -    }
>>>>     -    if (n_tested) {
>>>>     -        printf(" %d expressions of %d terminals", n_tested,
>>>>     n_terminals);
>>>>     -    } else {
>>>>     -        printf(" all %d-terminal expressions", n_terminals);
>>>>     -    }
>>>>     -    if (test_nvars || test_svars) {
>>>>     -        printf(" with");
>>>>     -        if (test_nvars) {
>>>>     -            printf(" %d numeric vars (each %d bits) in terms of
>>>>     operators",
>>>>     -                   test_nvars, test_bits);
>>>>     -            for (unsigned int relops = test_relops; relops;
>>>>     -                 relops = zero_rightmost_1bit(relops)) {
>>>>     -                enum expr_relop r = rightmost_1bit_idx(relops);
>>>>     -                printf(" %s", expr_relop_to_string(r));
>>>>     -            }
>>>>     -        }
>>>>     -        if (test_nvars && test_svars) {
>>>>     -            printf (" and");
>>>>     -        }
>>>>     -        if (test_svars) {
>>>>     -            printf(" %d string vars", test_svars);
>>>>     -        }
>>>>     -    } else {
>>>>     -        printf(" in terms of Boolean constants only");
>>>>     -    }
>>>>     -    printf(".\n");
>>>>     -
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    struct shash symtab;
>>>>     -    struct ds input;
>>>>     -
>>>>     -    create_symtab(&symtab);
>>>>     -
>>>>     -    ds_init(&input);
>>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>>     -        struct flow uflow;
>>>>     -        char *error = expr_parse_microflow(ds_cstr(&input),
>>>>     &symtab, NULL,
>>>>     -                                           NULL, lookup_atoi_cb,
>>>>     NULL, &uflow);
>>>>     -        if (error) {
>>>>     -            puts(error);
>>>>     -            free(error);
>>>>     -            continue;
>>>>     -        }
>>>>     -
>>>>     -        uint64_t packet_stub[128 / 8];
>>>>     -        struct dp_packet packet;
>>>>     -        dp_packet_use_stub(&packet, packet_stub, sizeof 
>>>> packet_stub);
>>>>     -        flow_compose(&packet, &uflow, NULL, 64);
>>>>     -
>>>>     -        struct ds output = DS_EMPTY_INITIALIZER;
>>>>     -        const uint8_t *buf = dp_packet_data(&packet);
>>>>     -        for (int i = 0; i < dp_packet_size(&packet); i++) {
>>>>     -            uint8_t val = buf[i];
>>>>     -            ds_put_format(&output, "%02"PRIx8, val);
>>>>     -        }
>>>>     -        puts(ds_cstr(&output));
>>>>     -        ds_destroy(&output);
>>>>     -
>>>>     -        dp_packet_uninit(&packet);
>>>>     -    }
>>>>     -    ds_destroy(&input);
>>>>     -
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -}
>>>>     -
>>>>     -/* Actions. */
>>>>     -
>>>>     -static void
>>>>     -test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
>>>>     -{
>>>>     -    struct shash symtab;
>>>>     -    struct hmap dhcp_opts;
>>>>     -    struct hmap dhcpv6_opts;
>>>>     -    struct hmap nd_ra_opts;
>>>>     -    struct controller_event_options event_opts;
>>>>     -    struct simap ports;
>>>>     -    struct ds input;
>>>>     -    bool ok = true;
>>>>     -
>>>>     -    create_symtab(&symtab);
>>>>     -    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
>>>>     &event_opts);
>>>>     -
>>>>     -    /* Initialize group ids. */
>>>>     -    struct ovn_extend_table group_table;
>>>>     -    ovn_extend_table_init(&group_table);
>>>>     -
>>>>     -    /* Initialize meter ids for QoS. */
>>>>     -    struct ovn_extend_table meter_table;
>>>>     -    ovn_extend_table_init(&meter_table);
>>>>     -
>>>>     -    simap_init(&ports);
>>>>     -    simap_put(&ports, "eth0", 5);
>>>>     -    simap_put(&ports, "eth1", 6);
>>>>     -    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
>>>>     -
>>>>     -    ds_init(&input);
>>>>     -    while (!ds_get_test_line(&input, stdin)) {
>>>>     -        struct ofpbuf ovnacts;
>>>>     -        struct expr *prereqs;
>>>>     -        char *error;
>>>>     -
>>>>     -        puts(ds_cstr(&input));
>>>>     -
>>>>     -        ofpbuf_init(&ovnacts, 0);
>>>>     -
>>>>     -        const struct ovnact_parse_params pp = {
>>>>     -            .symtab = &symtab,
>>>>     -            .dhcp_opts = &dhcp_opts,
>>>>     -            .dhcpv6_opts = &dhcpv6_opts,
>>>>     -            .nd_ra_opts = &nd_ra_opts,
>>>>     -            .controller_event_opts = &event_opts,
>>>>     -            .n_tables = 24,
>>>>     -            .cur_ltable = 10,
>>>>     -        };
>>>>     -        error = ovnacts_parse_string(ds_cstr(&input), &pp,
>>>>     &ovnacts, &prereqs);
>>>>     -        if (!error) {
>>>>     -            /* Convert the parsed representation back to a string
>>>>     and print it,
>>>>     -             * if it's different from the input. */
>>>>     -            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
>>>>     -            ovnacts_format(ovnacts.data, ovnacts.size, 
>>>> &ovnacts_s);
>>>>     -            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
>>>>     -                printf("    formats as %s\n", 
>>>> ds_cstr(&ovnacts_s));
>>>>     -            }
>>>>     -
>>>>     -            /* Encode the actions into OpenFlow and print. */
>>>>     -            const struct ovnact_encode_params ep = {
>>>>     -                .lookup_port = lookup_port_cb,
>>>>     -                .aux = &ports,
>>>>     -                .is_switch = true,
>>>>     -                .group_table = &group_table,
>>>>     -                .meter_table = &meter_table,
>>>>     -
>>>>     -                .pipeline = OVNACT_P_INGRESS,
>>>>     -                .ingress_ptable = 8,
>>>>     -                .egress_ptable = 40,
>>>>     -                .output_ptable = 64,
>>>>     -                .mac_bind_ptable = 65,
>>>>     -            };
>>>>     -            struct ofpbuf ofpacts;
>>>>     -            ofpbuf_init(&ofpacts, 0);
>>>>     -            ovnacts_encode(ovnacts.data, ovnacts.size, &ep,
>>>>     &ofpacts);
>>>>     -            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
>>>>     -            struct ofpact_format_params fp = { .s = &ofpacts_s };
>>>>     -            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
>>>>     -            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
>>>>     -            ds_destroy(&ofpacts_s);
>>>>     -            ofpbuf_uninit(&ofpacts);
>>>>     -
>>>>     -            /* Print prerequisites if any. */
>>>>     -            if (prereqs) {
>>>>     -                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
>>>>     -                expr_format(prereqs, &prereqs_s);
>>>>     -                printf("    has prereqs %s\n", 
>>>> ds_cstr(&prereqs_s));
>>>>     -                ds_destroy(&prereqs_s);
>>>>     -            }
>>>>     -
>>>>     -            /* Now re-parse and re-format the string to verify
>>>>     that it's
>>>>     -             * round-trippable. */
>>>>     -            struct ofpbuf ovnacts2;
>>>>     -            struct expr *prereqs2;
>>>>     -            ofpbuf_init(&ovnacts2, 0);
>>>>     -            error = ovnacts_parse_string(ds_cstr(&ovnacts_s),
>>>>     &pp, &ovnacts2,
>>>>     -  &prereqs2);
>>>>     -            if (!error) {
>>>>     -                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
>>>>     -                ovnacts_format(ovnacts2.data, ovnacts2.size,
>>>>     &ovnacts2_s);
>>>>     -                if (strcmp(ds_cstr(&ovnacts_s),
>>>>     ds_cstr(&ovnacts2_s))) {
>>>>     -                    printf("    bad reformat: %s\n",
>>>>     ds_cstr(&ovnacts2_s));
>>>>     -                    ok = false;
>>>>     -                }
>>>>     -                ds_destroy(&ovnacts2_s);
>>>>     -            } else {
>>>>     -                printf("    reparse error: %s\n", error);
>>>>     -                free(error);
>>>>     -                ok = false;
>>>>     -            }
>>>>     -            expr_destroy(prereqs2);
>>>>     -
>>>>     -            ovnacts_free(ovnacts2.data, ovnacts2.size);
>>>>     -            ofpbuf_uninit(&ovnacts2);
>>>>     -            ds_destroy(&ovnacts_s);
>>>>     -        } else {
>>>>     -            printf("    %s\n", error);
>>>>     -            free(error);
>>>>     -        }
>>>>     -
>>>>     -        expr_destroy(prereqs);
>>>>     -        ovnacts_free(ovnacts.data, ovnacts.size);
>>>>     -        ofpbuf_uninit(&ovnacts);
>>>>     -    }
>>>>     -    ds_destroy(&input);
>>>>     -
>>>>     -    simap_destroy(&ports);
>>>>     -    expr_symtab_destroy(&symtab);
>>>>     -    shash_destroy(&symtab);
>>>>     -    dhcp_opts_destroy(&dhcp_opts);
>>>>     -    dhcp_opts_destroy(&dhcpv6_opts);
>>>>     -    nd_ra_opts_destroy(&nd_ra_opts);
>>>>     -    controller_event_opts_destroy(&event_opts);
>>>>     -    ovn_extend_table_destroy(&group_table);
>>>>     -    ovn_extend_table_destroy(&meter_table);
>>>>     -    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
>>>>     -}
>>>>     -
>>>>     -static unsigned int
>>>>     -parse_relops(const char *s)
>>>>     -{
>>>>     -    unsigned int relops = 0;
>>>>     -    struct lexer lexer;
>>>>     -
>>>>     -    lexer_init(&lexer, s);
>>>>     -    lexer_get(&lexer);
>>>>     -    do {
>>>>     -        enum expr_relop relop;
>>>>     -
>>>>     -        if (expr_relop_from_token(lexer.token.type, &relop)) {
>>>>     -            relops |= 1u << relop;
>>>>     -            lexer_get(&lexer);
>>>>     -        } else {
>>>>     -            ovs_fatal(0, "%s: relational operator expected at
>>>>     `%.*s'",
>>>>     -                      s, (int) (lexer.input - lexer.start),
>>>>     lexer.start);
>>>>     -        }
>>>>     -        lexer_match(&lexer, LEX_T_COMMA);
>>>>     -    } while (lexer.token.type != LEX_T_END);
>>>>     -    lexer_destroy(&lexer);
>>>>     -
>>>>     -    return relops;
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -usage(void)
>>>>     -{
>>>>     -    printf("\
>>>>     -%s: OVN test utility\n\
>>>>     -usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
>>>>     -\n\
>>>>     -lex\n\
>>>>     -  Lexically analyzes OVN input from stdin and print them back on
>>>>     stdout.\n\
>>>>     -\n\
>>>>     -parse-expr\n\
>>>>     -annotate-expr\n\
>>>>     -simplify-expr\n\
>>>>     -normalize-expr\n\
>>>>     -expr-to-flows\n\
>>>>     -  Parses OVN expressions from stdin and prints them back on
>>>>     stdout after\n\
>>>>     -  differing degrees of analysis.  Available fields are based on
>>>>     packet\n\
>>>>     -  headers.\n\
>>>>     -\n\
>>>>     -expr-to-packets\n\
>>>>     -  Parses OVN expressions from stdin and prints out matching
>>>>     packets in\n\
>>>>     -  hexadecimal on stdout.\n\
>>>>     -\n\
>>>>     -evaluate-expr MICROFLOW\n\
>>>>     -  Parses OVN expressions from stdin and evaluates them against
>>>>     the flow\n\
>>>>     -  specified in MICROFLOW, which must be an expression that
>>>>     constrains\n\
>>>>     -  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with
>>>>     source\n\
>>>>     -  port 80, and prints the results on stdout, either 1 for true or
>>>>     0 for\n\
>>>>     -  false.  Use quoted integers, e.g. \"123\", for string 
>>>> fields.\n\
>>>>     -\n\
>>>>     -  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type
>>>>     == 0x800\"\n\
>>>>     -  evaluates to true, \"udp\" evaluates to false, and \"udp ||
>>>>     tcp\"\n\
>>>>     -  evaluates to true.\n\
>>>>     -\n\
>>>>     -composition N\n\
>>>>     -  Prints all the compositions of N on stdout.\n\
>>>>     -\n\
>>>>     -tree-shape N\n\
>>>>     -  Prints all the tree shapes with N terminals on stdout.\n\
>>>>     -\n\
>>>>     -exhaustive N\n\
>>>>     -  Tests that all possible Boolean expressions with N terminals
>>>>     are properly\n\
>>>>     -  simplified, normalized, and converted to flows. Available
>>>>     options:\n\
>>>>     -   Overall options:\n\
>>>>     -    --operation=OPERATION  Operation to test, one of: convert,
>>>>     simplify,\n\
>>>>     -        normalize, flow.  Default: flow.  'normalize' includes
>>>>     'simplify',\n\
>>>>     -        'flow' includes 'simplify' and 'normalize'.\n\
>>>>     -    --parallel=N  Number of processes to use in parallel, default
>>>>     1.\n\
>>>>     -   Numeric vars:\n\
>>>>     -    --nvars=N  Number of numeric vars to test, in range 0...4,
>>>>     default 2.\n\
>>>>     -    --bits=N  Number of bits per variable, in range 1...3,
>>>>     default 3.\n\
>>>>     -    --relops=OPERATORS   Test only the specified Boolean
>>>>     operators.\n\
>>>>     -                         OPERATORS may include == != < <= > >=,
>>>>     space or\n\
>>>>     -                         comma separated.  Default is all
>>>>     operators.\n\
>>>>     -   String vars:\n\
>>>>     -    --svars=N  Number of string vars to test, in range 0...4,
>>>>     default 2.\n\
>>>>     -\n\
>>>>     -parse-actions\n\
>>>>     -  Parses OVN actions from stdin and prints the equivalent
>>>>     OpenFlow actions\n\
>>>>     -  on stdout.\n\
>>>>     -",
>>>>     -           program_name, program_name);
>>>>     -    exit(EXIT_SUCCESS);
>>>>     -}
>>>>     -
>>>>     -static void
>>>>     -test_ovn_main(int argc, char *argv[])
>>>>     -{
>>>>     -    enum {
>>>>     -        OPT_RELOPS = UCHAR_MAX + 1,
>>>>     -        OPT_NVARS,
>>>>     -        OPT_SVARS,
>>>>     -        OPT_BITS,
>>>>     -        OPT_OPERATION,
>>>>     -        OPT_PARALLEL
>>>>     -    };
>>>>     -    static const struct option long_options[] = {
>>>>     -        {"relops", required_argument, NULL, OPT_RELOPS},
>>>>     -        {"nvars", required_argument, NULL, OPT_NVARS},
>>>>     -        {"svars", required_argument, NULL, OPT_SVARS},
>>>>     -        {"bits", required_argument, NULL, OPT_BITS},
>>>>     -        {"operation", required_argument, NULL, OPT_OPERATION},
>>>>     -        {"parallel", required_argument, NULL, OPT_PARALLEL},
>>>>     -        {"more", no_argument, NULL, 'm'},
>>>>     -        {"help", no_argument, NULL, 'h'},
>>>>     -        {NULL, 0, NULL, 0},
>>>>     -    };
>>>>     -    char *short_options =
>>>>     ovs_cmdl_long_options_to_short_options(long_options);
>>>>     -
>>>>     -    set_program_name(argv[0]);
>>>>     -
>>>>     -    test_relops = parse_relops("== != < <= > >=");
>>>>     -    for (;;) {
>>>>     -        int option_index = 0;
>>>>     -        int c = getopt_long (argc, argv, short_options, 
>>>> long_options,
>>>>     -                             &option_index);
>>>>     -
>>>>     -        if (c == -1) {
>>>>     -            break;
>>>>     -        }
>>>>     -        switch (c) {
>>>>     -        case OPT_RELOPS:
>>>>     -            test_relops = parse_relops(optarg);
>>>>     -            break;
>>>>     -
>>>>     -        case OPT_NVARS:
>>>>     -            test_nvars = atoi(optarg);
>>>>     -            if (test_nvars < 0 || test_nvars > 4) {
>>>>     -                ovs_fatal(0, "number of numeric variables must 
>>>> be "
>>>>     -                          "between 0 and 4");
>>>>     -            }
>>>>     -            break;
>>>>     -
>>>>     -        case OPT_SVARS:
>>>>     -            test_svars = atoi(optarg);
>>>>     -            if (test_svars < 0 || test_svars > 4) {
>>>>     -                ovs_fatal(0, "number of string variables must 
>>>> be "
>>>>     -                          "between 0 and 4");
>>>>     -            }
>>>>     -            break;
>>>>     -
>>>>     -        case OPT_BITS:
>>>>     -            test_bits = atoi(optarg);
>>>>     -            if (test_bits < 1 || test_bits > 3) {
>>>>     -                ovs_fatal(0, "number of bits must be between 1
>>>>     and 3");
>>>>     -            }
>>>>     -            break;
>>>>     -
>>>>     -        case OPT_OPERATION:
>>>>     -            if (!strcmp(optarg, "convert")) {
>>>>     -                operation = OP_CONVERT;
>>>>     -            } else if (!strcmp(optarg, "simplify")) {
>>>>     -                operation = OP_SIMPLIFY;
>>>>     -            } else if (!strcmp(optarg, "normalize")) {
>>>>     -                operation = OP_NORMALIZE;
>>>>     -            } else if (!strcmp(optarg, "flow")) {
>>>>     -                operation = OP_FLOW;
>>>>     -            } else {
>>>>     -                ovs_fatal(0, "%s: unknown operation", optarg);
>>>>     -            }
>>>>     -            break;
>>>>     -
>>>>     -        case OPT_PARALLEL:
>>>>     -            test_parallel = atoi(optarg);
>>>>     -            break;
>>>>     -
>>>>     -        case 'm':
>>>>     -            verbosity++;
>>>>     -            break;
>>>>     -
>>>>     -        case 'h':
>>>>     -            usage();
>>>>     -            /* fall through */
>>>>     -
>>>>     -        case '?':
>>>>     -            exit(1);
>>>>     -
>>>>     -        default:
>>>>     -            abort();
>>>>     -        }
>>>>     -    }
>>>>     -    free(short_options);
>>>>     -
>>>>     -    static const struct ovs_cmdl_command commands[] = {
>>>>     -        /* Lexer. */
>>>>     -        {"lex", NULL, 0, 0, test_lex, OVS_RO},
>>>>     -
>>>>     -        /* Symbol table. */
>>>>     -        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
>>>>     -
>>>>     -        /* Expressions. */
>>>>     -        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
>>>>     -        {"annotate-expr", NULL, 0, 0, test_annotate_expr, 
>>>> OVS_RO},
>>>>     -        {"simplify-expr", NULL, 0, 0, test_simplify_expr, 
>>>> OVS_RO},
>>>>     -        {"normalize-expr", NULL, 0, 0, test_normalize_expr, 
>>>> OVS_RO},
>>>>     -        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, 
>>>> OVS_RO},
>>>>     -        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, 
>>>> OVS_RO},
>>>>     -        {"composition", NULL, 1, 1, test_composition, OVS_RO},
>>>>     -        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
>>>>     -        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
>>>>     -        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets,
>>>>     OVS_RO},
>>>>     -
>>>>     -        /* Actions. */
>>>>     -        {"parse-actions", NULL, 0, 0, test_parse_actions, 
>>>> OVS_RO},
>>>>     -
>>>>     -        {NULL, NULL, 0, 0, NULL, OVS_RO},
>>>>     -    };
>>>>     -    struct ovs_cmdl_context ctx;
>>>>     -    ctx.argc = argc - optind;
>>>>     -    ctx.argv = argv + optind;
>>>>     -    ovs_cmdl_run_command(&ctx, commands);
>>>>     -}
>>>>     -
>>>>     -OVSTEST_REGISTER("test-ovn", test_ovn_main);
>>>>     diff --git a/tests/testsuite.at <http://testsuite.at>
>>>>     b/tests/testsuite.at <http://testsuite.at>
>>>>     index 4d5e816..e759123 100644
>>>>     --- a/tests/testsuite.at <http://testsuite.at>
>>>>     +++ b/tests/testsuite.at <http://testsuite.at>
>>>>     @@ -19,7 +19,6 @@ m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
>>>>      m4_include([tests/ovs-macros.at <http://ovs-macros.at>])
>>>>      m4_include([tests/ovsdb-macros.at <http://ovsdb-macros.at>])
>>>>      m4_include([tests/ofproto-macros.at <http://ofproto-macros.at>])
>>>>     -m4_include([tests/ovn-macros.at <http://ovn-macros.at>])
>>>>
>>>>      m4_include([tests/completion.at <http://completion.at>])
>>>>      m4_include([tests/checkpatch.at <http://checkpatch.at>])
>>>>     @@ -74,13 +73,6 @@ m4_include([tests/rstp.at <http://rstp.at>])
>>>>      m4_include([tests/vlog.at <http://vlog.at>])
>>>>      m4_include([tests/vtep-ctl.at <http://vtep-ctl.at>])
>>>>      m4_include([tests/auto-attach.at <http://auto-attach.at>])
>>>>     -m4_include([tests/ovn.at <http://ovn.at>])
>>>>     -m4_include([tests/ovn-northd.at <http://ovn-northd.at>])
>>>>     -m4_include([tests/ovn-nbctl.at <http://ovn-nbctl.at>])
>>>>     -m4_include([tests/ovn-sbctl.at <http://ovn-sbctl.at>])
>>>>     -m4_include([tests/ovn-controller.at <http://ovn-controller.at>])
>>>>     -m4_include([tests/ovn-controller-vtep.at
>>>>     <http://ovn-controller-vtep.at>])
>>>>      m4_include([tests/mcast-snooping.at <http://mcast-snooping.at>])
>>>>      m4_include([tests/packet-type-aware.at
>>>>     <http://packet-type-aware.at>])
>>>>      m4_include([tests/nsh.at <http://nsh.at>])
>>>>     -m4_include([tests/ovn-performance.at 
>>>> <http://ovn-performance.at>])
>>>>     --     1.8.3.1
>>>>
>>>>     _______________________________________________
>>>>     dev mailing list
>>>>     dev@openvswitch.org <mailto:dev@openvswitch.org>
>>>>     https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>>>
>>>
>>> _______________________________________________
>>> dev mailing list
>>> dev@openvswitch.org
>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>
diff mbox series

Patch

diff --git a/tests/automake.mk b/tests/automake.mk
index d6ab517..decca46 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -23,8 +23,7 @@  EXTRA_DIST += \
 COMMON_MACROS_AT = \
 	tests/ovsdb-macros.at \
 	tests/ovs-macros.at \
-	tests/ofproto-macros.at \
-	tests/ovn-macros.at
+	tests/ofproto-macros.at
 
 TESTSUITE_AT = \
 	tests/testsuite.at \
@@ -104,16 +103,9 @@  TESTSUITE_AT = \
 	tests/vlog.at \
 	tests/vtep-ctl.at \
 	tests/auto-attach.at \
-	tests/ovn.at \
-	tests/ovn-northd.at \
-	tests/ovn-nbctl.at \
-	tests/ovn-sbctl.at \
-	tests/ovn-controller.at \
-	tests/ovn-controller-vtep.at \
 	tests/mcast-snooping.at \
 	tests/packet-type-aware.at \
-	tests/nsh.at \
-	tests/ovn-performance.at
+	tests/nsh.at
 
 EXTRA_DIST += $(FUZZ_REGRESSION_TESTS)
 FUZZ_REGRESSION_TESTS = \
@@ -158,7 +150,6 @@  SYSTEM_KMOD_TESTSUITE_AT = \
 
 SYSTEM_USERSPACE_TESTSUITE_AT = \
 	tests/system-userspace-testsuite.at \
-	tests/system-ovn.at \
 	tests/system-userspace-macros.at \
 	tests/system-userspace-packet-type-aware.at
 
@@ -169,7 +160,6 @@  SYSTEM_AFXDP_TESTSUITE_AT = \
 
 SYSTEM_TESTSUITE_AT = \
 	tests/system-common-macros.at \
-	tests/system-ovn.at \
 	tests/system-layer3-tunnels.at \
 	tests/system-traffic.at \
 	tests/system-interface.at
@@ -197,7 +187,7 @@  SYSTEM_DPDK_TESTSUITE = $(srcdir)/tests/system-dpdk-testsuite
 OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite
 DISTCLEANFILES += tests/atconfig tests/atlocal
 
-AUTOTEST_PATH = utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller
+AUTOTEST_PATH = utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR)
 
 check-local:
 	set $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH); \
@@ -238,10 +228,6 @@  check-lcov: all $(check_DATA) clean-lcov
 # valgrind support
 
 valgrind_wrappers = \
-	tests/valgrind/ovn-controller \
-	tests/valgrind/ovn-nbctl \
-	tests/valgrind/ovn-northd \
-	tests/valgrind/ovn-sbctl \
 	tests/valgrind/ovs-appctl \
 	tests/valgrind/ovs-ofctl \
 	tests/valgrind/ovs-vsctl \
@@ -446,7 +432,6 @@  tests_ovstest_SOURCES = \
 	tests/test-netflow.c \
 	tests/test-odp.c \
 	tests/test-ofpbuf.c \
-	tests/test-ovn.c \
 	tests/test-packets.c \
 	tests/test-random.c \
 	tests/test-rcu.c \
@@ -474,7 +459,7 @@  tests_ovstest_SOURCES += \
 	tests/test-netlink-conntrack.c
 endif
 
-tests_ovstest_LDADD = lib/libopenvswitch.la ovn/lib/libovn.la
+tests_ovstest_LDADD = lib/libopenvswitch.la
 
 noinst_PROGRAMS += tests/test-stream
 tests_test_stream_SOURCES = tests/test-stream.c
diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at
deleted file mode 100644
index a3fe8cb..0000000
--- a/tests/ovn-controller-vtep.at
+++ /dev/null
@@ -1,467 +0,0 @@ 
-AT_BANNER([ovn_controller_vtep])
-
-# OVN_CONTROLLER_VTEP_START
-#
-# Starts the test with a setup with vtep device.  Each test case must first
-# call this macro.
-#
-# Uses vtep-ovs to simulate the vtep switch 'br-vtep' with two physical ports
-# 'p0', 'p1'.
-#
-# Configures ovn-nb with a logical switch 'br-test'.
-#
-#
-m4_define([OVN_CONTROLLER_VTEP_START],
-  [
-   AT_KEYWORDS([ovn])
-   # this will cause skip when 'make check' using Windows setup.
-   AT_SKIP_IF([test $HAVE_PYTHON = no])
-
-   dnl Create databases (ovn-nb, ovn-sb, vtep).
-   AT_CHECK([ovsdb-tool create vswitchd.db $abs_top_srcdir/vswitchd/vswitch.ovsschema])
-   for daemon in ovn-nb ovn-sb vtep; do
-      AT_CHECK([ovsdb-tool create $daemon.db $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
-   done
-
-   dnl Start ovsdb-server.
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock vswitchd.db vtep.db], [0], [], [stderr])
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovsdb-nb-server.pid --log-file=ovsdb-nb-server.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovsdb-sb-server.pid --log-file=ovsdb-sb-server.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db ovn-sb.db], [0], [], [stderr])
-   on_exit "kill `cat ovsdb-server.pid` `cat ovsdb-nb-server.pid` `cat ovsdb-sb-server.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d
-/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
-   AT_CAPTURE_FILE([ovsdb-server.log])
-
-   dnl Start ovs-vswitchd.
-   AT_CHECK([ovs-vswitchd --enable-dummy=system --disable-system --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif], [0], [], [stderr])
-   AT_CAPTURE_FILE([ovs-vswitchd.log])
-   on_exit "kill `cat ovs-vswitchd.pid`"
-   AT_CHECK([[sed < stderr '
-/ovs_numa|INFO|Discovered /d
-/vlog|INFO|opened log file/d
-/vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d
-/reconnect|INFO|/d
-/ofproto|INFO|using datapath ID/d
-/netlink_socket|INFO|netlink: could not enable listening to all nsid/d
-/ofproto|INFO|datapath ID changed to fedcba9876543210/d']])
-   AT_CHECK([ovs-vsctl -- add-br br-vtep \
-              -- set bridge br-vtep datapath-type=dummy other-config:datapath-id=fedcba9876543210 other-config:hwaddr=aa:55:aa:55:00:00 protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] fail-mode=secure \
-              -- add-port br-vtep p0 -- set Interface p0 type=dummy ofport_request=1 \
-              -- add-port br-vtep p1 -- set Interface p1 type=dummy ofport_request=2])
-
-   dnl Start ovs-vtep.
-   AT_CHECK([vtep-ctl add-ps br-vtep -- set Physical_Switch br-vtep tunnel_ips=1.2.3.4])
-   AT_CHECK([ovs-vtep --log-file=ovs-vtep.log --pidfile=ovs-vtep.pid --detach --no-chdir br-vtep \], [0], [], [stderr])
-   on_exit "kill `cat ovs-vtep.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d']])
-   # waits until ovs-vtep starts up.
-   OVS_WAIT_UNTIL([test -n "`vtep-ctl show | grep Physical_Port`"])
-
-   dnl Start ovn-northd.
-   AT_CHECK([ovn-nbctl ls-add br-test])
-   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file], [0], [], [stderr])
-   on_exit "kill `cat ovn-northd.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d']])
-   AT_CAPTURE_FILE([ovn-northd.log])
-
-   dnl Start ovn-controllger-vtep.
-   AT_CHECK([ovn-controller-vtep --detach --no-chdir --pidfile --log-file --vtep-db=unix:$OVS_RUNDIR/db.sock --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
-   AT_CAPTURE_FILE([ovn-controller-vtep.log])
-   on_exit "kill `cat ovn-controller-vtep.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d
-/reconnect|INFO|/d']])
-])
-
-# OVN_CONTROLLER_VTEP_STOP
-#
-# So many exits... Yeah, we started a lot daemons~
-#
-m4_define([OVN_CONTROLLER_VTEP_STOP],
-  [AT_CHECK([check_logs "$1"])
-   OVS_APP_EXIT_AND_WAIT([ovs-vtep])
-   OVS_APP_EXIT_AND_WAIT([ovn-northd])
-   OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
-   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-   OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])])
-
-# Adds logical port for a vtep gateway chassis in ovn-nb database.
-#
-# $1: logical switch name in ovn-nb database
-# $2: logical port name
-# $3: physical vtep gateway name
-# $4: logical switch name on vtep gateway chassis
-m4_define([OVN_NB_ADD_VTEP_PORT], [
-AT_CHECK([ovn-nbctl lsp-add $1 $2])
-
-AT_CHECK([ovn-nbctl lsp-set-type $2 vtep])
-AT_CHECK([ovn-nbctl lsp-set-options $2 vtep-physical-switch=$3 vtep-logical-switch=$4])
-])
-
-##############################################
-
-# tests chassis related updates.
-AT_SETUP([ovn-controller-vtep - chassis])
-OVN_CONTROLLER_VTEP_START
-
-# verifies the initial ovn-sb db configuration.
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep Chassis`"])
-AT_CHECK([ovn-sbctl show], [0], [dnl
-Chassis br-vtep
-    Encap vxlan
-        ip: "1.2.3.4"
-        options: {csum="false"}
-])
-
-# deletes the chassis via ovn-sbctl and check that it is readded back
-# with the log.
-AT_CHECK([ovn-sbctl chassis-del br-vtep])
-OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
-AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log], [0], [dnl
-|WARN|Chassis for VTEP physical switch (br-vtep) disappears, maybe deleted by ovn-sbctl, adding it back
-])
-
-# changes the tunnel_ip on physical switch, watches the update of chassis's
-# encap.
-AT_CHECK([vtep-ctl set Physical_Switch br-vtep tunnel_ips=1.2.3.5])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl show | grep 1\.2\.3\.5`"])
-AT_CHECK([ovn-sbctl --columns=ip list Encap | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-"1.2.3.5"
-])
-
-# adds vlan_bindings to physical ports.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 -- bind-ls br-vtep p0 200 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch0`"])
-AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
-[[lswitch0]]
-])
-
-# adds another logical switch and new vlan_bindings.
-AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 300 lswitch1])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Chassis | grep -- lswitch1`"])
-AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-[[lswitch0,lswitch1]]
-])
-
-# unbinds one port from lswitch0, nothing should change.
-AT_CHECK([vtep-ctl unbind-ls br-vtep p0 200])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=vlan_bindings list physical_port p0 | grep -- '200='`"])
-AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
-[[lswitch0,lswitch1]]
-])
-
-# unbinds all ports from lswitch0.
-AT_CHECK([vtep-ctl unbind-ls br-vtep p0 100 -- unbind-ls br-vtep p1 300])
-OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch0`"])
-AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' ' ], [0], [dnl
-[[lswitch1]]
-])
-
-# unbinds all ports from lswitch1.
-AT_CHECK([vtep-ctl unbind-ls br-vtep p0 300])
-OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch1`"])
-AT_CHECK([ovn-sbctl --columns=vtep_logical_switches list Chassis | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-[[]]
-])
-
-OVN_CONTROLLER_VTEP_STOP([/Chassis for VTEP physical switch (br-vtep) disappears/d])
-AT_CLEANUP
-
-
-# Tests binding updates.
-AT_SETUP([ovn-controller-vtep - binding 1])
-OVN_CONTROLLER_VTEP_START
-
-# adds logical switch 'lswitch0' and vlan_bindings.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0 -- bind-ls br-vtep p1 300 lswitch0])
-# adds logical switch port in ovn-nb database, and sets the type and options.
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
-ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0 chassis!='[[]]'
-# should see one binding, associated to chassis of 'br-vtep'.
-chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d ':' -f2 | tr -d ' ')
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-${chassis_uuid}
-])
-
-# adds another logical switch 'lswitch1' and vlan_bindings.
-AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
-# adds logical switch port in ovn-nb database for lswitch1.
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch1], [br-vtep], [lswitch1])
-ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch1 chassis!='[[]]'
-# This is allowed, but not recommended, to have two vlan_bindings (to different vtep logical switches)
-# from one vtep gateway physical port in one ovn-nb logical swithch.
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
-
-${chassis_uuid}
-${chassis_uuid}
-])
-
-# adds another logical switch port in ovn-nb database for lswitch0.
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0_dup], [br-vtep], [lswitch0])
-ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0_dup chassis!='[[]]'
-# it is not allowed to have more than one ovn-nb logical port for the same
-# vtep logical switch on a vtep gateway chassis, so should still see only
-# two port_binding entries bound.
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort | sort -d], [0], [dnl
-
-
-[[]]
-${chassis_uuid}
-${chassis_uuid}
-])
-# confirms the warning log.
-AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g' | uniq], [0], [dnl
-|WARN|logical switch (), on vtep gateway chassis () has already been associated with logical port (), ignore logical port ()
-])
-
-# deletes physical ports from vtep.
-AT_CHECK([ovs-vsctl del-port p0 -- del-port p1])
-OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Chassis | grep -- br-vtep_lswitch`"])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p0`"])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl list physical_port p1`"])
-# should see empty chassis column in both binding entries.
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding | cut -d ':' -f2 | tr -d ' ' | sort], [0], [dnl
-
-
-[[]]
-[[]]
-[[]]
-])
-
-OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical port/d])
-AT_CLEANUP
-
-
-# Tests corner case: Binding the vtep logical switch from two different
-# datapath.
-AT_SETUP([ovn-controller-vtep - binding 2])
-OVN_CONTROLLER_VTEP_START
-
-# adds logical switch 'lswitch0' and vlan_bindings.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
-# adds logical switch port in ovn-nb database, and sets the type and options.
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
-ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0 chassis!='[[]]'
-
-# adds another lswitch 'br-void' in ovn-nb database.
-AT_CHECK([ovn-nbctl ls-add br-void])
-# adds another vtep pswitch 'br-vtep-void' in vtep database.
-AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0-void -- bind-ls br-vtep-void p0-void 100 lswitch0])
-# adds a conflicting logical port (both br-vtep_lswitch0 and br-vtep-void_lswitch0
-# are bound to the same logical switch, but they are on different datapath).
-OVN_NB_ADD_VTEP_PORT([br-void], [br-vtep-void_lswitch0], [br-vtep-void], [lswitch0])
-ovn-sbctl --timeout=10 wait-until Port_Binding br-vtep_lswitch0
-OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
-# confirms the warning log.
-AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_0-9a-z]][[-_0-9a-z]]*)/()/g;s/(with tunnel key [[0-9]][[0-9]]*)/()/g' | uniq], [0], [dnl
-|WARN|logical switch (), on vtep gateway chassis () has already been associated with logical datapath (), ignore logical port () which belongs to logical datapath ()
-])
-
-# then deletes 'br-void' and 'br-vtep-void', should see 'br-vtep_lswitch0'
-# bound correctly.
-AT_CHECK([ovn-nbctl ls-del br-void])
-# adds another vtep pswitch 'br-vtep-void' in vtep database.
-AT_CHECK([vtep-ctl del-ps br-vtep-void])
-OVS_WAIT_UNTIL([test -z "`ovn-sbctl list Port_Binding | grep br-vtep-void_lswitch0`"])
-chassis_uuid=$(ovn-sbctl --columns=_uuid list Chassis br-vtep | cut -d ':' -f2 | tr -d ' ')
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=chassis list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-${chassis_uuid}
-])
-
-OVN_CONTROLLER_VTEP_STOP([/has already been associated with logical datapath/d])
-AT_CLEANUP
-
-
-# Tests vtep module vtep logical switch tunnel key update.
-AT_SETUP([ovn-controller-vtep - vtep-lswitch])
-OVN_CONTROLLER_VTEP_START
-
-# creates the logical switch in vtep and adds the corresponding logical
-# port to 'br-test'.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep_lswitch0`"])
-
-# retrieves the expected tunnel key.
-datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
-tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
-OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 0`"])
-# checks the vtep logical switch tunnel key configuration.
-AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-${tunnel_key}
-])
-
-# creates a second physical switch in vtep database, and binds its p0 vlan-100
-# to the same logical switch 'lswitch0'.
-AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0 -- bind-ls br-vtep-void p0 100 lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0], [br-vtep-void], [lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep-void_lswitch0`"])
-
-# checks the vtep logical switch tunnel key configuration.
-AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-${tunnel_key}
-])
-
-# now, deletes br-vtep-void.
-AT_CHECK([vtep-ctl del-ps br-vtep-void])
-OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
-# checks the vtep logical switch tunnel key configuration.
-AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-${tunnel_key}
-])
-
-# changes the ovn-nb logical port type so that it is no longer
-# vtep port.
-AT_CHECK([ovn-nbctl lsp-set-type br-vtep_lswitch0 ""])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 1`"])
-# now should see the tunnel key reset.
-AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-0
-])
-
-OVN_CONTROLLER_VTEP_STOP
-AT_CLEANUP
-
-
-# Tests vtep module 'Ucast_Macs_Remote's.
-AT_SETUP([ovn-controller-vtep - vtep-macs 1])
-OVN_CONTROLLER_VTEP_START
-
-# creates a simple logical network with the vtep device and a fake hv chassis
-# 'ch0'.
-AT_CHECK([ovn-nbctl lsp-add br-test vif0])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
-AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
-AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
-
-# creates the logical switch in vtep and adds the corresponding logical
-# port to 'br-test'.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-vtep_lswitch0`"])
-
-# adds another lswitch 'br-void' in ovn-nb database.
-AT_CHECK([ovn-nbctl ls-add br-void])
-# adds fake hv chassis 'ch1'.
-AT_CHECK([ovn-nbctl lsp-add br-void vif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
-AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
-AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
-
-# checks Ucast_Macs_Remote creation.
-OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' '], [0], [dnl
-"f0:ab:cd:ef:01:02"
-])
-
-# checks physical locator creation.
-OVS_WAIT_UNTIL([test -n "`vtep-ctl list Physical_Locator | grep _uuid`"])
-AT_CHECK([vtep-ctl --columns=dst_ip list Physical_Locator | cut -d ':' -f2 | tr -d ' ' | grep -v 1.2.3.4 | sed '/^$/d'], [0], [dnl
-"1.2.3.5"
-])
-
-# checks tunnel creation by ovs-vtep.
-OVS_WAIT_UNTIL([test -n "`ovs-vsctl list Interface bfd1.2.3.5`"])
-AT_CHECK([ovs-vsctl --columns=options list Interface bfd1.2.3.5 | cut -d ':' -f2 | tr -d ' '], [0], [dnl
-{remote_ip="1.2.3.5"}
-])
-
-# adds another mac to logical switch port.
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02 f0:ab:cd:ef:01:03])
-OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep 03`"])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
-
-"f0:ab:cd:ef:01:02"
-"f0:ab:cd:ef:01:03"
-])
-
-# removes one mac to logical switch port.
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:03])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 02`"])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
-"f0:ab:cd:ef:01:03"
-])
-
-# migrates mac to logical switch port vif1 on 'br-void'.
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
-OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 03`"])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
-])
-
-OVN_CONTROLLER_VTEP_STOP
-AT_CLEANUP
-
-
-# Tests vtep module 'Ucast_Macs_Remote's (corner cases).
-AT_SETUP([ovn-controller-vtep - vtep-macs 2])
-OVN_CONTROLLER_VTEP_START
-
-# creates a simple logical network with the vtep device and a fake hv chassis
-# 'ch0'.
-AT_CHECK([ovn-nbctl lsp-add br-test vif0])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
-AT_CHECK([ovn-sbctl chassis-add ch0 vxlan 1.2.3.5])
-AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
-
-# creates another vif in the same logical switch with duplicate mac.
-AT_CHECK([ovn-nbctl lsp-add br-test vif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
-AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
-
-# creates the logical switch in vtep and adds the corresponding logical
-# port to 'br-test'.
-AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
-OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-vtep_lswitch0`"])
-
-# checks Ucast_Macs_Remote creation.  Should still only be one entry, since duplicate
-# mac in the same logical switch is not allowed.
-OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Remote | grep _uuid`"])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' '], [0], [dnl
-"f0:ab:cd:ef:01:02"
-])
-# confirms the warning log.
-OVS_WAIT_UNTIL([test -n "`grep WARN ovn-controller-vtep.log`"])
-AT_CHECK([sed -n 's/^.*\(|WARN|.*\)$/\1/p' ovn-controller-vtep.log | sed 's/([[-_:0-9a-z]][[-_:0-9a-z]]*)/()/g' | uniq], [0], [dnl
-|WARN|MAC address () has already been known to be on logical port () in the same logical datapath, so just ignore this logical port ()
-])
-
-# deletes vif1.
-AT_CHECK([ovn-nbctl lsp-del vif1])
-
-# adds another lswitch 'br-void' in ovn-nb database.
-AT_CHECK([ovn-nbctl ls-add br-void])
-# adds fake hv chassis 'ch1' and vif1 with same mac address as vif0.
-AT_CHECK([ovn-nbctl lsp-add br-void vif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-nbctl --timeout=10 --wait=sb sync])
-AT_CHECK([ovn-sbctl chassis-add ch1 vxlan 1.2.3.6])
-AT_CHECK([ovn-sbctl lsp-bind vif1 ch1])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding | grep vif1`"])
-
-# creates another logical switch in vtep and adds the corresponding logical
-# port to 'br-void'.
-AT_CHECK([vtep-ctl add-ls lswitch1 -- bind-ls br-vtep p0 200 lswitch1])
-OVN_NB_ADD_VTEP_PORT([br-void], [br-void_lswitch1], [br-vtep], [lswitch1])
-OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep br-void_lswitch1`"])
-
-# checks Ucast_Macs_Remote creation.  Should see two entries since it is allowed
-# to have duplicate macs in different logical switches.
-OVS_WAIT_UNTIL([test `vtep-ctl --columns=MAC list Ucast_Macs_Remote | grep 02 | wc -l` -gt 1])
-AT_CHECK([vtep-ctl --columns=MAC list Ucast_Macs_Remote | cut -d ':' -f2- | tr -d ' ' | sort], [0], [dnl
-
-"f0:ab:cd:ef:01:02"
-"f0:ab:cd:ef:01:02"
-])
-
-OVN_CONTROLLER_VTEP_STOP([/has already been known to be on logical port/d])
-AT_CLEANUP
diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
deleted file mode 100644
index 343c2ab..0000000
--- a/tests/ovn-controller.at
+++ /dev/null
@@ -1,294 +0,0 @@ 
-AT_BANNER([ovn-controller])
-
-AT_SETUP([ovn-controller - ovn-bridge-mappings])
-AT_KEYWORDS([ovn])
-ovn_init_db ovn-sb
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0 \
-    -- add-br br-eth1 \
-    -- add-br br-eth2
-ovn_attach n1 br-phys 192.168.0.1
-
-# Waits until the OVS database contains exactly the specified patch ports.
-# Each argument should be of the form BRIDGE PORT PEER.
-check_patches () {
-    # Generate code to check that the set of patch ports is exactly as
-    # specified.
-    echo 'ovs-vsctl -f csv -d bare --no-headings --columns=name find Interface type=patch | sort' > query
-    for patch
-    do
-        echo $patch
-    done | cut -d' ' -f 2 | sort > expout
-
-    # Generate code to verify that the configuration of each patch
-    # port is correct.
-    for patch
-    do
-        set $patch; bridge=$1 port=$2 peer=$3
-        echo >>query "ovs-vsctl iface-to-br $port -- get Interface $port type options"
-        echo >>expout "$bridge
-patch
-{peer=$peer}"
-    done
-
-    # Run the query until we get the expected result (or until a timeout).
-    #
-    # (We use sed to drop all "s from output because ovs-vsctl quotes some
-    # of the port names but not others.)
-    AT_CAPTURE_FILE([query])
-    AT_CAPTURE_FILE([expout])
-    AT_CAPTURE_FILE([stdout])
-    OVS_WAIT_UNTIL([. ./query | sed 's/"//g' > stdout #"
-                    diff -u stdout expout >/dev/null])
-}
-
-# Make sure that the configured bridge mappings in the Open_vSwitch db
-# is mirrored into the Chassis record in the OVN_Southbound db.
-check_bridge_mappings () {
-    local_mappings=$1
-    sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
-    OVS_WAIT_UNTIL([test x"${local_mappings}" = x$(ovn-sbctl get Chassis ${sysid} external_ids:ovn-bridge-mappings | sed -e 's/\"//g')])
-}
-
-# Initially there should be no patch ports.
-check_patches
-
-# Configure two ovn-bridge mappings, but no patch ports should be created yet
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1])
-check_bridge_mappings "physnet1:br-eth0,physnet2:br-eth1"
-check_patches
-
-# Create a localnet port, but we should still have no patch ports, as they
-# won't be created until there's a localnet port on a logical switch with
-# another logical port bound to this chassis.
-ovn-sbctl \
-    -- --id=@dp101 create Datapath_Binding tunnel_key=101 \
-    -- create Port_Binding datapath=@dp101 logical_port=localnet1 tunnel_key=1 \
-        type=localnet options:network_name=physnet1
-check_patches
-
-# Create a localnet port on a logical switch with a port bound to this chassis.
-# Now we should get some patch ports created.
-ovn-sbctl \
-    -- --id=@dp102 create Datapath_Binding tunnel_key=102 \
-    -- create Port_Binding datapath=@dp102 logical_port=localnet2 tunnel_key=1 \
-        type=localnet options:network_name=physnet1 \
-    -- create Port_Binding datapath=@dp102 logical_port=localvif2 tunnel_key=2
-ovs-vsctl add-port br-int localvif2 -- set Interface localvif2 external_ids:iface-id=localvif2
-check_patches \
-    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
-    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
-
-# Add logical patch ports to connect new logical datapath.
-#
-# OVN no longer uses OVS patch ports to implement logical patch ports, so
-# the set of OVS patch ports doesn't change.
-AT_CHECK([ovn-sbctl \
-    -- --id=@dp1 create Datapath_Binding tunnel_key=1 \
-    -- --id=@dp2 create Datapath_Binding tunnel_key=2 \
-    -- create Port_Binding datapath=@dp1 logical_port=foo tunnel_key=1 type=patch options:peer=bar \
-    -- create Port_Binding datapath=@dp2 logical_port=bar tunnel_key=2 type=patch options:peer=foo \
-    -- create Port_Binding datapath=@dp1 logical_port=dp1vif tunnel_key=3 \
-| uuidfilt], [0], [<0>
-<1>
-<2>
-<3>
-<4>
-])
-ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif external_ids:iface-id=dp1vif
-check_patches \
-    'br-int  patch-br-int-to-localnet2 patch-localnet2-to-br-int' \
-    'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2'
-
-# Delete the mapping and the ovn-bridge-mapping patch ports should go away.
-AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids ovn-bridge-mappings])
-check_bridge_mappings
-check_patches
-
-# Gracefully terminate daemons
-OVN_CLEANUP_SBOX([hv])
-OVN_CLEANUP_VSWITCH([main])
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-AT_CLEANUP
-
-# Checks that ovn-controller populates datapath-type and iface-types
-# correctly in the Chassis external-ids column.
-AT_SETUP([ovn-controller - Chassis external_ids])
-AT_KEYWORDS([ovn])
-ovn_init_db ovn-sb
-
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0 \
-    -- add-br br-eth1 \
-    -- add-br br-eth2
-ovn_attach n1 br-phys 192.168.0.1
-
-sysid=$(ovs-vsctl get Open_vSwitch . external_ids:system-id)
-
-# Make sure that the datapath_type set in the Bridge table
-# is mirrored into the Chassis record in the OVN_Southbound db.
-check_datapath_type () {
-    datapath_type=$1
-    chassis_datapath_type=$(ovn-sbctl get Chassis ${sysid} external_ids:datapath-type | sed -e 's/"//g') #"
-    test "${datapath_type}" = "${chassis_datapath_type}"
-}
-
-OVS_WAIT_UNTIL([check_datapath_type ""])
-
-ovs-vsctl set Bridge br-int datapath-type=foo
-OVS_WAIT_UNTIL([check_datapath_type foo])
-
-# Change "ovn-bridge-mappings" value. It should not change the "datapath-type".
-ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-mappings=foo-mapping
-check_datapath_type foo
-
-ovs-vsctl set Bridge br-int datapath-type=bar
-OVS_WAIT_UNTIL([check_datapath_type bar])
-
-ovs-vsctl set Bridge br-int datapath-type=\"\"
-OVS_WAIT_UNTIL([check_datapath_type ""])
-
-# Set the datapath_type in external_ids:ovn-bridge-datapath-type.
-ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-datapath-type=foo
-OVS_WAIT_UNTIL([check_datapath_type foo])
-
-# Change the br-int's datapath type to bar.
-# It should be reset to foo since ovn-bridge-datapath-type is configured.
-ovs-vsctl set Bridge br-int datapath-type=bar
-OVS_WAIT_UNTIL([test foo=`ovs-vsctl get Bridge br-int datapath-type`])
-OVS_WAIT_UNTIL([check_datapath_type foo])
-
-ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-datapath-type=foobar
-OVS_WAIT_UNTIL([test foobar=`ovs-vsctl get Bridge br-int datapath-type`])
-OVS_WAIT_UNTIL([check_datapath_type foobar])
-
-expected_iface_types=$(ovs-vsctl get Open_vSwitch . iface_types | tr -d '[[]] ""')
-echo "expected_iface_types = ${expected_iface_types}"
-chassis_iface_types=$(ovn-sbctl get Chassis ${sysid} external_ids:iface-types | sed -e 's/\"//g')
-echo "chassis_iface_types = ${chassis_iface_types}"
-AT_CHECK([test "${expected_iface_types}" = "${chassis_iface_types}"])
-
-# Change the value of external_ids:iface-types using ovn-sbctl.
-# ovn-controller should again set it back to proper one.
-ovn-sbctl set Chassis ${sysid} external_ids:iface-types="foo"
-OVS_WAIT_UNTIL([
-    chassis_iface_types=$(ovn-sbctl get Chassis ${sysid} external_ids:iface-types | sed -e 's/\"//g')
-    echo "chassis_iface_types = ${chassis_iface_types}"
-    test "${expected_iface_types}" = "${chassis_iface_types}"
-])
-
-# Change the value of external_ids:system-id and make sure it's mirrored
-# in the Chassis record in the OVN_Southbound database.
-sysid=${sysid}-foo
-ovs-vsctl set Open_vSwitch . external-ids:system-id="${sysid}"
-OVS_WAIT_UNTIL([
-    chassis_id=$(ovn-sbctl get Chassis "${sysid}" name)
-    test "${sysid}" = "${chassis_id}"
-])
-
-# Gracefully terminate daemons
-OVN_CLEANUP_SBOX([hv])
-OVN_CLEANUP_VSWITCH([main])
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-AT_CLEANUP
-
-# Checks that ovn-controller correctly maintains the mapping from the Encap
-# table in the Southbound database to OVS in the face of changes on both sides
-AT_SETUP([ovn-controller - change Encap properties])
-AT_KEYWORDS([ovn])
-ovn_init_db ovn-sb
-
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0 \
-    -- add-br br-eth1 \
-    -- add-br br-eth2
-ovn_attach n1 br-phys 192.168.0.1
-
-check_tunnel_property () {
-    test "`ovs-vsctl get interface ovn-fakech-0 $1`" = "$2"
-}
-
-# Start off with a remote chassis supporting STT
-ovn-sbctl chassis-add fakechassis stt 192.168.0.2
-OVS_WAIT_UNTIL([check_tunnel_property type stt])
-
-# See if we switch to Geneve as the first choice when it is available
-# With multi-VTEP support we support tunnels with different IPs to the
-# same chassis, and hence use the IP to annotate the tunnel (along with
-# the chassis-id in ovn-chassis-id); if we supply a different IP here
-# we won't be able to co-relate this to the tunnel port that was created
-# in the previous step and, as a result, will end up creating another tunnel,
-# ie. we can't just lookup using "ovn-fakech-0". So, need to use the same IP
-# as above, i.e 192.168.0.2, here.
-encap_uuid=$(ovn-sbctl add chassis fakechassis encaps @encap -- --id=@encap create encap type=geneve ip="192.168.0.2")
-OVS_WAIT_UNTIL([check_tunnel_property type geneve])
-
-# Check that changes within an encap row are propagated
-ovn-sbctl set encap ${encap_uuid} ip=192.168.0.2
-OVS_WAIT_UNTIL([check_tunnel_property options:remote_ip "\"192.168.0.2\""])
-
-# Change the type on the OVS side and check than OVN fixes it
-ovs-vsctl set interface ovn-fakech-0 type=vxlan
-OVS_WAIT_UNTIL([check_tunnel_property type geneve])
-
-# Delete the port entirely and it should be resurrected
-ovs-vsctl del-port ovn-fakech-0
-OVS_WAIT_UNTIL([check_tunnel_property type geneve])
-
-# Gracefully terminate daemons
-OVN_CLEANUP_SBOX([hv])
-OVN_CLEANUP_VSWITCH([main])
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-AT_CLEANUP
-
-# Check ovn-controller connection status to Southbound database
-AT_SETUP([ovn-controller - check sbdb connection])
-AT_KEYWORDS([ovn])
-ovn_init_db ovn-sb
-
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0 \
-    -- add-br br-eth1 \
-    -- add-br br-eth2
-ovn_attach n1 br-phys 192.168.0.1
-
-check_sbdb_connection () {
-    test "$(ovs-appctl -t ovn-controller connection-status)" = "$1"
-}
-
-OVS_WAIT_UNTIL([check_sbdb_connection connected])
-
-ovs-vsctl set open . external_ids:ovn-remote=tcp:192.168.0.10:6642
-OVS_WAIT_UNTIL([check_sbdb_connection 'not connected'])
-
-# reset the remote for clean-up
-ovs-vsctl set open . external_ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
-# Gracefully terminate daemons
-OVN_CLEANUP_SBOX([hv])
-OVN_CLEANUP_VSWITCH([main])
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-AT_CLEANUP
diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
deleted file mode 100644
index 7dba42c..0000000
--- a/tests/ovn-macros.at
+++ /dev/null
@@ -1,180 +0,0 @@ 
-# OVN_CLEANUP_VSWITCH(sim)
-#
-# Gracefully terminate vswitch daemons in the
-# specified sandbox.
-m4_define([OVN_CLEANUP_VSWITCH],[
-    as $1
-    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
-    OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-])
-
-# OVN_CLEANUP_SBOX(sbox)
-#
-# Gracefully terminate OVN daemons in the specified
-# sandbox instance. The sandbox name "vtep" is treated
-# as a special case, and is assumed to have ovn-controller-vtep
-# and ovs-vtep daemons running instead of ovn-controller.
-m4_define([OVN_CLEANUP_SBOX],[
-    as $1
-    if test "$1" = "vtep"; then
-        OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep])
-        OVS_APP_EXIT_AND_WAIT([ovs-vtep])
-    else
-        OVS_APP_EXIT_AND_WAIT([ovn-controller])
-    fi
-    OVN_CLEANUP_VSWITCH([$1])
-])
-
-# OVN_CLEANUP(sim [, sim ...])
-#
-# Gracefully terminate all OVN daemons, including those in the
-# specified sandbox instances.
-m4_define([OVN_CLEANUP],[
-    m4_foreach([sbox], [$@], [
-        OVN_CLEANUP_SBOX([sbox])
-    ])
-    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 northd-backup
-    OVS_APP_EXIT_AND_WAIT([ovn-northd])
-
-    OVN_CLEANUP_VSWITCH([main])
-])
-
-m4_divert_push([PREPARE_TESTS])
-
-# ovn_init_db DATABASE
-#
-# Creates and initializes the given DATABASE (one of "ovn-sb" or "ovn-nb"),
-# starts its ovsdb-server instance, and sets the appropriate environment
-# variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or ovn-nbctl uses the
-# database by default.
-#
-# Usually invoked from ovn_start.
-ovn_init_db () {
-    echo "creating $1 database"
-    local d=$ovs_base/$1
-    mkdir "$d" || return 1
-    : > "$d"/.$1.db.~lock~
-    as $1 ovsdb-tool create "$d"/$1.db "$abs_top_srcdir"/ovn/$1.ovsschema
-    as $1 start_daemon ovsdb-server --remote=punix:"$d"/$1.sock "$d"/$1.db
-    local var=`echo $1_db | tr a-z- A-Z_`
-    AS_VAR_SET([$var], [unix:$ovs_base/$1/$1.sock]); export $var
-}
-
-# ovn_start
-#
-# Creates and initializes ovn-sb and ovn-nb databases and starts their
-# ovsdb-server instance, sets appropriate environment variables so that
-# ovn-sbctl and ovn-nbctl use them by default, and starts ovn-northd running
-# against them.
-ovn_start () {
-    ovn_init_db ovn-sb; ovn-sbctl init
-    ovn_init_db ovn-nb; ovn-nbctl init
-
-    echo "starting ovn-northd"
-    mkdir "$ovs_base"/northd
-    as northd start_daemon ovn-northd -v \
-               --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
-               --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-
-    echo "starting backup ovn-northd"
-    mkdir "$ovs_base"/northd-backup
-    as northd-backup start_daemon ovn-northd -v \
-               --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
-               --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-}
-
-# Interconnection networks.
-#
-# When multiple sandboxed Open vSwitch instances exist, one will inevitably
-# want to connect them together.  These commands allow for that.  Conceptually,
-# an interconnection network is a switch for which these functions make it easy
-# to plug into other switches in other sandboxed Open vSwitch instances.
-# Interconnection networks are implemented as bridges in a switch named "main",
-# so to use interconnection networks please avoid working with that switch
-# directly.
-
-# net_add NETWORK
-#
-# Creates a new interconnection network named NETWORK.
-net_add () {
-    test -d "$ovs_base"/main || sim_add main || return 1
-    as main ovs-vsctl add-br "$1"
-}
-
-# net_attach NETWORK BRIDGE
-#
-# Adds a new port to BRIDGE in the default sandbox (as set with as()) and plugs
-# it into the NETWORK interconnection network.  NETWORK must already have been
-# created by a previous invocation of net_add.  The default sandbox must not be
-# "main".
-net_attach () {
-    local net=$1 bridge=$2
-
-    local port=${sandbox}_$bridge
-    as main ovs-vsctl \
-        -- add-port $net $port \
-        -- set Interface $port options:pstream="punix:$ovs_base/main/$port.sock" options:rxq_pcap="$ovs_base/main/$port-rx.pcap" options:tx_pcap="$ovs_base/main/$port-tx.pcap" \
-        || return 1
-
-    ovs-vsctl \
-        -- set Interface $bridge options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap" options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \
-        -- add-port $bridge ${bridge}_$net \
-        -- set Interface ${bridge}_$net options:stream="unix:$ovs_base/main/$port.sock" options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap" options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \
-        || return 1
-}
-
-# ovn_attach NETWORK BRIDGE IP [MASKLEN]
-#
-# First, this command attaches BRIDGE to interconnection network NETWORK, just
-# like "net_attach NETWORK BRIDGE".  Second, it configures (simulated) IP
-# address IP (with network mask length MASKLEN, which defaults to 24) on
-# BRIDGE.  Finally, it configures the Open vSwitch database to work with OVN
-# and starts ovn-controller.
-ovn_attach() {
-    local net=$1 bridge=$2 ip=$3 masklen=${4-24}
-    net_attach $net $bridge || return 1
-
-    mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g`
-    arp_table="$arp_table $sandbox,$bridge,$ip,$mac"
-    ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen >/dev/null || return 1
-    ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null || return 1
-    ovs-vsctl \
-        -- set Open_vSwitch . external-ids:system-id=$sandbox \
-        -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
-        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve,vxlan \
-        -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \
-        -- add-br br-int \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \
-        || return 1
-    start_daemon ovn-controller || return 1
-}
-
-# OVN_POPULATE_ARP
-#
-# This pre-populates the ARP tables of all of the OVN instances that have been
-# started with ovn_attach().  That means that packets sent from one hypervisor
-# to another never get dropped or delayed by ARP resolution, which makes
-# testing easier.
-ovn_populate_arp__() {
-    for e1 in $arp_table; do
-        set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4
-        for e2 in $arp_table; do
-            set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2
-            if test $sb1,$br1 != $sb2,$br2; then
-                as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac || return 1
-            fi
-        done
-    done
-}
-m4_divert_pop([PREPARE_TESTS])
-
-m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0], [ignore])])
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
deleted file mode 100644
index d99d3af..0000000
--- a/tests/ovn-nbctl.at
+++ /dev/null
@@ -1,1660 +0,0 @@ 
-AT_BANNER([ovn-nbctl])
-
-OVS_START_SHELL_HELPERS
-# OVN_NBCTL_TEST_START
-m4_define([OVN_NBCTL_TEST_START],
-  [AT_KEYWORDS([ovn])
-   AT_CAPTURE_FILE([ovsdb-server.log])
-   ovn_nbctl_test_start $1])
-ovn_nbctl_test_start() {
-   dnl Create ovn-nb database.
-   AT_CHECK([ovsdb-tool create ovn-nb.db $abs_top_srcdir/ovn/ovn-nb.ovsschema])
-
-   dnl Start ovsdb-server.
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
-   on_exit "kill `cat ovsdb-server.pid`"
-   AS_CASE([$1],
-     [daemon],
-       [export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach --no-chdir --log-file -vsocket_util:off)
-        on_exit "kill `cat ovn-nbctl.pid`"],
-     [direct], [],
-     [*], [AT_FAIL_IF(:)])
-   AT_CHECK([ovn-nbctl init])
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d
-/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
-}
-
-# OVN_NBCTL_TEST_STOP
-m4_define([OVN_NBCTL_TEST_STOP], [ovn_nbctl_test_stop])
-ovn_nbctl_test_stop() {
-   AT_CHECK([check_logs "$1"])
-   OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-}
-OVS_END_SHELL_HELPERS
-
-# OVN_NBCTL_TEST(NAME, TITLE, COMMANDS)
-m4_define([OVN_NBCTL_TEST],
-   [OVS_START_SHELL_HELPERS
-    $1() {
-      $3
-    }
-    OVS_END_SHELL_HELPERS
-
-    AT_SETUP([ovn-nbctl - $2 - direct])
-    OVN_NBCTL_TEST_START direct
-    $1
-    OVN_NBCTL_TEST_STOP
-    AT_CLEANUP
-
-    AT_SETUP([ovn-nbctl - $2 - daemon])
-    OVN_NBCTL_TEST_START daemon
-    $1
-    OVN_NBCTL_TEST_STOP
-    AT_CLEANUP])
-
-OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
-<0> (ls0)
-])
-
-AT_CHECK([ovn-nbctl ls-add ls1])
-AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
-<0> (ls0)
-<1> (ls1)
-])
-
-AT_CHECK([ovn-nbctl ls-del ls0])
-AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
-<0> (ls1)
-])
-
-AT_CHECK([ovn-nbctl show ls0])
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
-  [switch <0> (ls0)
-])
-AT_CHECK([ovn-nbctl ls-add ls0], [1], [],
-  [ovn-nbctl: ls0: a switch with this name already exists
-])
-AT_CHECK([ovn-nbctl --may-exist ls-add ls0])
-AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0],
-  [switch <0> (ls0)
-])
-AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0])
-AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], [1], [],
-  [ovn-nbctl: --may-exist and --add-duplicate may not be used together
-])
-AT_CHECK([ovn-nbctl ls-del ls0], [1], [],
-  [ovn-nbctl: Multiple logical switches named 'ls0'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl ls-del ls2], [1], [],
-  [ovn-nbctl: ls2: switch name not found
-])
-AT_CHECK([ovn-nbctl --if-exists ls-del ls2])
-
-AT_CHECK([ovn-nbctl ls-add])
-AT_CHECK([ovn-nbctl ls-add])
-AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [],
-  [ovn-nbctl: --add-duplicate requires specifying a name
-])
-AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [],
-  [ovn-nbctl: --may-exist requires specifying a name
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_basic_lsp], [basic logical switch port commands], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0], [1], [],
-  [ovn-nbctl: lp0: a port with this name already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp0])
-AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
-<0> (lp0)
-])
-
-AT_CHECK([ovn-nbctl lsp-add ls0 lp1])
-AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
-<0> (lp0)
-<1> (lp1)
-])
-
-AT_CHECK([ovn-nbctl ls-add ls1])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp1], [1], [],
-  [ovn-nbctl: lp1: a port with this name already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls1 lp1], [1], [],
-  [ovn-nbctl: lp1: port already exists but in switch ls0
-])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp1 lp0 5], [1], [],
-  [ovn-nbctl: lp1: port already exists but has no parent
-])
-
-AT_CHECK([ovn-nbctl lsp-del lp1])
-AT_CHECK([ovn-nbctl lsp-list ls0 | uuidfilt], [0], [dnl
-<0> (lp0)
-])
-
-AT_CHECK([ovn-nbctl lsp-add ls0 lp2 lp3 5])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp4 5], [1], [],
-  [ovn-nbctl: lp2: port already exists with different parent lp3
-])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 10], [1], [],
-  [ovn-nbctl: lp2: port already exists with different tag_request 5
-])
-AT_CHECK([ovn-nbctl clear Logical_Switch_Port lp2 tag_request])
-AT_CHECK([ovn-nbctl --may-exist lsp-add ls0 lp2 lp3 5], [1], [],
-  [ovn-nbctl: lp2: port already exists but has no tag_request
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lsp_get_ls], [lsp get ls], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-
-AT_CHECK([ovn-nbctl lsp-get-ls lp0 | uuidfilt], [0], [dnl
-<0> (ls0)
-])
-
-AT_CHECK([ovn-nbctl lsp-get-ls lp1], [1], [],
-  [ovn-nbctl: lp1: port name not found
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lport_addresses], [lport addresses], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
-])
-
-AT_CHECK([ovn-nbctl lsp-set-addresses lp0 00:11:22:33:44:55 unknown])
-AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
-00:11:22:33:44:55
-unknown
-])
-
-AT_CHECK([ovn-nbctl lsp-set-addresses lp0])
-AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_port_security], [port security], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-AT_CHECK([ovn-nbctl lsp-get-addresses lp0], [0], [dnl
-])
-
-AT_CHECK([ovn-nbctl lsp-set-port-security lp0 aa:bb:cc:dd:ee:ff 00:11:22:33:44:55])
-AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
-00:11:22:33:44:55
-aa:bb:cc:dd:ee:ff
-])
-
-AT_CHECK([ovn-nbctl lsp-set-port-security lp0])
-AT_CHECK([ovn-nbctl lsp-get-port-security lp0], [0], [dnl
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_acls], [ACLs], [
-ovn_nbctl_test_acl() {
-   AT_CHECK([ovn-nbctl $2 --log acl-add $1 from-lport 600 udp drop])
-   AT_CHECK([ovn-nbctl $2 --log --name=test --severity=info acl-add $1 to-lport 500 udp drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 300 tcp drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop])
-   dnl Add duplicated ACL
-   AT_CHECK([ovn-nbctl $2 acl-add $1 to-lport 100 ip drop], [1], [], [stderr])
-   AT_CHECK([grep 'already existed' stderr], [0], [ignore])
-   AT_CHECK([ovn-nbctl $2 --may-exist acl-add $1 to-lport 100 ip drop])
-
-   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
-from-lport   600 (udp) drop log()
-from-lport   400 (tcp) drop
-from-lport   200 (ip) drop
-  to-lport   500 (udp) drop log(name=test,severity=info)
-  to-lport   300 (tcp) drop
-  to-lport   100 (ip) drop
-])
-
-   dnl Delete in one direction.
-   AT_CHECK([ovn-nbctl $2 acl-del $1 to-lport])
-   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
-from-lport   600 (udp) drop log()
-from-lport   400 (tcp) drop
-from-lport   200 (ip) drop
-])
-
-   dnl Delete all ACLs.
-   AT_CHECK([ovn-nbctl $2 acl-del $1])
-   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
-])
-
-   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 600 udp drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 400 tcp drop])
-   AT_CHECK([ovn-nbctl $2 acl-add $1 from-lport 200 ip drop])
-
-   dnl Delete a single flow.
-   AT_CHECK([ovn-nbctl $2 acl-del $1 from-lport 400 tcp])
-   AT_CHECK([ovn-nbctl $2 acl-list $1], [0], [dnl
-from-lport   600 (udp) drop
-from-lport   200 (ip) drop
-])
-}
-
-AT_CHECK([ovn-nbctl ls-add ls0])
-ovn_nbctl_test_acl ls0
-AT_CHECK([ovn-nbctl ls-add ls1])
-ovn_nbctl_test_acl ls1 --type=switch
-AT_CHECK([ovn-nbctl create port_group name=pg0], [0], [ignore])
-ovn_nbctl_test_acl pg0 --type=port-group
-
-dnl Test when port group doesn't exist
-AT_CHECK([ovn-nbctl --type=port-group acl-add pg1 to-lport 100 ip drop], [1], [], [dnl
-ovn-nbctl: pg1: port group name not found
-])
-
-dnl Test when same name exists in logical switches and portgroups
-AT_CHECK([ovn-nbctl create port_group name=ls0], [0], [ignore])
-AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop], [1], [], [stderr])
-AT_CHECK([grep 'exists in both' stderr], [0], [ignore])
-AT_CHECK([ovn-nbctl --type=port-group acl-add ls0 to-lport 100 ip drop], [0], [ignore])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_qos], [QoS], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 tcp dscp=63])
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 500 udp rate=100 burst=1000])
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=0 rate=300 burst=3000])
-AT_CHECK([ovn-nbctl qos-add ls0 to-lport 300 tcp dscp=48])
-AT_CHECK([ovn-nbctl qos-add ls0 to-lport 200 ip rate=101])
-AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=13 rate=301 burst=30000])
-
-dnl Add duplicated qos
-AT_CHECK([ovn-nbctl qos-add ls0 to-lport 100 ip4 dscp=11 rate=302 burst=30002], [1], [], [stderr])
-AT_CHECK([grep 'already existed' stderr], [0], [ignore])
-AT_CHECK([ovn-nbctl --may-exist qos-add ls0 to-lport 100 ip4 dscp=11 rate=302 burst=30002])
-
-AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
-from-lport   600 (tcp) dscp=63
-from-lport   500 (udp) rate=100 burst=1000
-from-lport   400 (tcp) rate=300 burst=3000 dscp=0
-  to-lport   300 (tcp) dscp=48
-  to-lport   200 (ip) rate=101
-  to-lport   100 (ip4) rate=301 burst=30000 dscp=13
-])
-
-dnl Delete in one direction.
-AT_CHECK([ovn-nbctl qos-del ls0 to-lport])
-AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
-from-lport   600 (tcp) dscp=63
-from-lport   500 (udp) rate=100 burst=1000
-from-lport   400 (tcp) rate=300 burst=3000 dscp=0
-])
-
-dnl Delete all qos_rules.
-AT_CHECK([ovn-nbctl qos-del ls0])
-AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=1000101])
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 400 tcp dscp=44])
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 200 ip burst=1000102 rate=301 dscp=19])
-
-dnl Delete a single flow.
-AT_CHECK([ovn-nbctl qos-del ls0 from-lport 400 tcp])
-AT_CHECK([ovn-nbctl qos-list ls0], [0], [dnl
-from-lport   600 (ip) rate=1000101
-from-lport   200 (ip) rate=301 burst=1000102 dscp=19
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip rate=100010111111], [1], [],
-[ovn-nbctl: 100010111111: rate must be in the range 1...4294967295
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=100010111112 rate=100010], [1], [],
-[ovn-nbctl: 100010111112: burst must be in the range 1...4294967295
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscp=-1], [1], [],
-[ovn-nbctl: -1: dscp must be in the range 0...63
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip dscpa=-1], [1], [],
-[ovn-nbctl: dscpa=-1: supported arguments are "dscp=", "rate=", and "burst="
-])
-
-AT_CHECK([ovn-nbctl qos-add ls0 from-lport 600 ip burst=123], [1], [],
-[ovn-nbctl: Either "rate" and/or "dscp" must be specified
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_meters], [meters], [
-AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps])
-AT_CHECK([ovn-nbctl meter-add meter2 drop 3 kbps 2])
-AT_CHECK([ovn-nbctl meter-add meter3 drop 100 kbps 200])
-AT_CHECK([ovn-nbctl meter-add meter4 drop 10 pktps 30])
-
-dnl Add duplicate meter name
-AT_CHECK([ovn-nbctl meter-add meter1 drop 10 kbps], [1], [], [stderr])
-AT_CHECK([grep 'already exists' stderr], [0], [ignore])
-
-dnl Add reserved meter name
-AT_CHECK([ovn-nbctl meter-add __meter1 drop 10 kbps], [1], [], [stderr])
-AT_CHECK([grep 'reserved' stderr], [0], [ignore])
-
-dnl Add meter with invalid rates
-AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 kbps], [1], [],
-[ovn-nbctl: rate must be in the range 1...4294967295
-])
-
-dnl Add meter with invalid rates
-AT_CHECK([ovn-nbctl meter-add meter5 drop 100010111111 foo], [1], [],
-[ovn-nbctl: rate must be in the range 1...4294967295
-])
-
-AT_CHECK([ovn-nbctl meter-add meter5 drop 0 kbps], [1], [],
-[ovn-nbctl: rate must be in the range 1...4294967295
-])
-
-dnl Add meter with invalid burst
-AT_CHECK([ovn-nbctl meter-add meter5 drop 10 100010111111 kbps], [1], [],
-[ovn-nbctl: unit must be "kbps" or "pktps"
-])
-
-AT_CHECK([ovn-nbctl meter-list], [0], [dnl
-meter1: bands:
-  drop: 10 kbps
-meter2: bands:
-  drop: 3 kbps, 2 kb burst
-meter3: bands:
-  drop: 100 kbps, 200 kb burst
-meter4: bands:
-  drop: 10 pktps, 30 packet burst
-])
-
-dnl Delete a single meter.
-AT_CHECK([ovn-nbctl meter-del meter2])
-AT_CHECK([ovn-nbctl meter-list], [0], [dnl
-meter1: bands:
-  drop: 10 kbps
-meter3: bands:
-  drop: 100 kbps, 200 kb burst
-meter4: bands:
-  drop: 10 pktps, 30 packet burst
-])
-
-dnl Delete all meters.
-AT_CHECK([ovn-nbctl meter-del])
-AT_CHECK([ovn-nbctl meter-list], [0], [dnl
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_nats], [NATs], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snatt 30.0.0.2 192.168.1.2], [1], [],
-[ovn-nbctl: snatt: type must be one of "dnat", "snat" and "dnat_and_snat".
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2a 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0.2a: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2/24 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0.2/24: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2:80 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0.2:80: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2a], [1], [],
-[ovn-nbctl: 192.168.1.2a: should be an IPv4 address or network.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1], [1], [],
-[ovn-nbctl: 192.168.1: should be an IPv4 address or network.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2:80], [1], [],
-[ovn-nbctl: 192.168.1.2:80: should be an IPv4 address or network.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2/a], [1], [],
-[ovn-nbctl: 192.168.1.2/a: should be an IPv4 address or network.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2a], [1], [],
-[ovn-nbctl: 192.168.1.2a: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1], [1], [],
-[ovn-nbctl: 192.168.1: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2:80], [1], [],
-[ovn-nbctl: 192.168.1.2:80: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2/24], [1], [],
-[ovn-nbctl: 192.168.1.2/24: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2/24], [1], [],
-[ovn-nbctl: 192.168.1.2/24: should be an IPv4 address.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0], [1], [],
-[ovn-nbctl: lr-nat-add with logical_port must also specify external_mac.
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
-[ovn-nbctl: logical_port and external_mac are only valid when type is "dnat_and_snat".
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
-[ovn-nbctl: logical_port and external_mac are only valid when type is "dnat_and_snat".
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0 00:00:00:01:02:03], [1], [],
-[ovn-nbctl: lp0: port name not found
-])
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0 00:00:00:01:02], [1], [],
-[ovn-nbctl: invalid mac address 00:00:00:01:02.
-])
-
-dnl Add snat and dnat
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0 00:00:00:01:02:03])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC         LOGICAL_PORT
-dnat             30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.2           192.168.1.3           00:00:00:01:02:03    lp0
-snat             30.0.0.1           192.168.1.0/24
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24], [1], [],
-[ovn-nbctl: 30.0.0.1, 192.168.1.0/24: a NAT with this external_ip and logical_ip already exists
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.10/24], [1], [],
-[ovn-nbctl: 30.0.0.1, 192.168.1.0/24: a NAT with this external_ip and logical_ip already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.0/24], [1], [],
-[ovn-nbctl: a NAT with this type (snat) and logical_ip (192.168.1.0/24) already exists
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0.1, 192.168.1.2: a NAT with this external_ip and logical_ip already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.3], [1], [],
-[ovn-nbctl: a NAT with this type (dnat) and external_ip (30.0.0.1) already exists
-])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2], [1], [],
-[ovn-nbctl: 30.0.0.1, 192.168.1.2: a NAT with this external_ip and logical_ip already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.3], [1], [],
-[ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip (30.0.0.1) already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0 00:00:00:04:05:06])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC         LOGICAL_PORT
-dnat             30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.2           192.168.1.3           00:00:00:04:05:06    lp0
-snat             30.0.0.1           192.168.1.0/24
-])
-AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC         LOGICAL_PORT
-dnat             30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.2           192.168.1.3
-snat             30.0.0.1           192.168.1.0/24
-])
-
-dnl Deletes the NATs
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
-[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and external_ip (30.0.0.3)
-])
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
-[ovn-nbctl: no matching NAT with the type (dnat) and external_ip (30.0.0.2)
-])
-AT_CHECK([ovn-nbctl lr-nat-del lr0 snat 192.168.10.0/24], [1], [],
-[ovn-nbctl: no matching NAT with the type (snat) and logical_ip (192.168.10.0/24)
-])
-AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat 192.168.10.0/24])
-
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC         LOGICAL_PORT
-dnat             30.0.0.1           192.168.1.2
-dnat_and_snat    30.0.0.2           192.168.1.3
-snat             30.0.0.1           192.168.1.0/24
-])
-
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
-TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC         LOGICAL_PORT
-dnat_and_snat    30.0.0.2           192.168.1.3
-snat             30.0.0.1           192.168.1.0/24
-])
-
-AT_CHECK([ovn-nbctl lr-nat-del lr0])
-AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [])
-AT_CHECK([ovn-nbctl lr-nat-del lr0])
-AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lbs], [LBs], [
-dnl Add two LBs.
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
-[ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
-[ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20 tcp], [1], [],
-[ovn-nbctl: 192.168.10.20: should be an IP address and a port number with : as a separator.
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a 192.168.10.10:80,192.168.10.20:80], [1], [],
-[ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0 192.168.10.10:80,192.168.10.20:80], [1], [],
-[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10,192.168.10.20:80], [1], [],
-[ovn-nbctl: 192.168.10.20:80: should be an IP address.
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:a80], [1], [],
-[ovn-nbctl: 192.168.10.10:a80: should be an IP address.
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:], [1], [],
-[ovn-nbctl: 192.168.10.10:: should be an IP address.
-])
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.1a], [1], [],
-[ovn-nbctl: 192.168.10.1a: should be an IP address.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10: 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:900 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-dnl Add ips to lb
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 ,,,192.168.10.10:80,,,,,])
-AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 ,,,192.168.10.10:80,,,,192.168.10.20:80,,,,])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80
-<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-])
-AT_CHECK([ovn-nbctl lb-del lb0])
-AT_CHECK([ovn-nbctl lb-del lb1])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80])
-AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 tcp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-])
-
-dnl Update the VIP of the lb1.
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80 192.168.10.10:80,192.168.10.20:8080])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:8080
-])
-
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80 192.168.10.10:80,192.168.10.20:8080 udp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:8080
-])
-
-dnl Config lb1 with another VIP.
-AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.20:80 192.168.10.10:80 udp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:8080
-                                                            udp        30.0.0.20:80    192.168.10.10:80
-])
-
-AT_CHECK([ovn-nbctl lb-del lb1 30.0.0.20:80])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:8080
-])
-
-dnl Add LBs whose vip is just an IP address.
-AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.30 192.168.10.10])
-AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.30 192.168.10.10])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:8080
-<2>    lb2                 tcp/udp    30.0.0.30       192.168.10.10
-<3>    lb3                 tcp/udp    30.0.0.30       192.168.10.10
-])
-AT_CHECK([ovn-nbctl lb-del lb2 30.0.0.30])
-AT_CHECK([ovn-nbctl lb-del lb3 30.0.0.30])
-
-AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080 192.168.10.10:80,192.168.10.20:80 tcp])
-AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 30.0.0.10:8080 192.168.10.10:80,192.168.10.20:80 tcp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP               IPs
-<0>    lb0                 tcp        30.0.0.10:80      192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80      192.168.10.10:80,192.168.10.20:8080
-<2>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,192.168.10.20:80
-<3>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,192.168.10.20:80
-])
-
-dnl If there are multiple load balancers with the same name, use a UUID to update/delete.
-AT_CHECK([ovn-nbctl lb-add lb2 30.0.0.10:8080 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:80 192.168.10.10:8080,192.168.10.20:8080 udp])
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:8080 192.168.10.10:8080,192.168.10.20:8080 udp])
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 30.0.0.10:9090 192.168.10.10:8080,192.168.10.20:8080 udp])
-AT_CHECK([ovn-nbctl lb-del lb0 30.0.0.10:80])
-AT_CHECK([ovn-nbctl lb-del lb1])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP               IPs
-<0>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,192.168.10.20:80
-<1>    lb2                 tcp        30.0.0.10:8080    192.168.10.10:80,192.168.10.20:80
-])
-
-dnl Add load balancer to logical switch.
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80])
-AT_CHECK([ovn-nbctl lb-add lb1 30.0.0.10:80 192.168.10.10:80,192.168.10.20:80 udp])
-AT_CHECK([ovn-nbctl lb-add lb3 30.0.0.10 192.168.10.10,192.168.10.20])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
-
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<2>    lb3                 tcp/udp    30.0.0.10       192.168.10.10,192.168.10.20
-])
-
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb3                 tcp/udp    30.0.0.10       192.168.10.10,192.168.10.20
-])
-
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
-AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
-
-dnl Remove all load balancers from logical switch.
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
-AT_CHECK([ovn-nbctl ls-lb-del ls0])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
-
-dnl Add load balancer to logical router.
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
-
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb0                 tcp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<2>    lb3                 tcp/udp    30.0.0.10       192.168.10.10,192.168.10.20
-])
-
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP             IPs
-<0>    lb1                 udp        30.0.0.10:80    192.168.10.10:80,192.168.10.20:80
-<1>    lb3                 tcp/udp    30.0.0.10       192.168.10.10,192.168.10.20
-])
-
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
-AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
-
-dnl Remove all load balancers from logical router.
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
-AT_CHECK([ovn-nbctl lr-lb-del lr0])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
-
-dnl Remove load balancers after adding them to a logical router/switch.
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl lb-del lb0])
-AT_CHECK([ovn-nbctl lb-del lb1])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lbs_ipv6], [LBs IPv6], [
-dnl A bunch of commands that should fail
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
-[ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
-[ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80 [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
-[ovn-nbctl: fd0f::20: should be an IP address and a port number with : as a separator.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
-[ovn-nbctl: ae0f::10fff: should be an IP address (or an IP address and a port number with : as a separator).
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
-[ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 fd0f::10,[[fd0f::20]]:80], [1], [],
-[ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:a80], [1], [],
-[ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:], [1], [],
-[ovn-nbctl: [[fd0f::10]]:: should be an IP address.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 fd0f::1001a], [1], [],
-[ovn-nbctl: fd0f::1001a: should be an IP address.
-])
-
-
-AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]: [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:900 tcp], [1], [],
-[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
-[ovn-nbctl: 192.168.10.10: IP address family is different from VIP ae0f::10.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 192.168.10.10], [1], [],
-[ovn-nbctl: 192.168.10.10: IP address family is different from VIP ae0f::10.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 192.168.10.10:80], [1], [],
-[ovn-nbctl: 192.168.10.10:80: IP address family is different from VIP [[ae0f::10]]:80.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 ae0f::10], [1], [],
-[ovn-nbctl: ae0f::10: IP address family is different from VIP 30.0.0.10.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 [[ae0f::10]]:80], [1], [],
-[ovn-nbctl: [[ae0f::10]]:80: IP address family is different from VIP 30.0.0.10:80.
-])
-
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10])
-AT_CHECK([ovn-nbctl lb-add lb0 ae0f:0000:0000:0000:0000:0000:0000:0010 fd0f::20],
-[1], [], [ovn-nbctl: lb0: a load balancer with this vip (ae0f::10) already exists
-])
-
-AT_CHECK([ovn-nbctl lb-del lb0])
-
-dnl Add ips to lb
-AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 ,,,[[fd0f::10]]:80,,,,,])
-AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80 ,,,[[fd0f::10]]:80,,,,[[fd0f::20]]:80,,,,])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80
-<1>    lb1                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-])
-AT_CHECK([ovn-nbctl lb-del lb0])
-AT_CHECK([ovn-nbctl lb-del lb1])
-
-
-AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:80])
-AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-])
-
-dnl Update the VIP of the lb1.
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:8080])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:8080
-])
-
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:8080 udp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:8080
-])
-
-dnl Config lb1 with another VIP.
-AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::20]]:80 [[fd0f::10]]:80 udp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:8080
-                                                            udp        [[ae0f::20]]:80    [[fd0f::10]]:80
-])
-
-AT_CHECK([ovn-nbctl lb-del lb1 [[ae0f::20]]:80])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:8080
-])
-
-dnl Add LBs whose vip is just an IP address.
-AT_CHECK([ovn-nbctl lb-add lb2 ae0f::30 fd0f::10])
-AT_CHECK([ovn-nbctl lb-add lb3 ae0f::30 fd0f::10])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:8080
-<2>    lb2                 tcp/udp    ae0f::30         fd0f::10
-<3>    lb3                 tcp/udp    ae0f::30         fd0f::10
-])
-AT_CHECK([ovn-nbctl lb-del lb2 ae0f::30])
-AT_CHECK([ovn-nbctl lb-del lb3 ae0f::30])
-
-AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
-AT_CHECK([ovn-nbctl --add-duplicate lb-add lb2 [[ae0f::10]]:8080 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP                IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80      [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80      [[fd0f::10]]:80,[[fd0f::20]]:8080
-<2>    lb2                 tcp        [[ae0f::10]]:8080    [[fd0f::10]]:80,[[fd0f::20]]:80
-<3>    lb2                 tcp        [[ae0f::10]]:8080    [[fd0f::10]]:80,[[fd0f::20]]:80
-])
-
-dnl If there are multiple load balancers with the same name, use a UUID to update/delete.
-AT_CHECK([ovn-nbctl lb-add lb2 [[ae0f::10]]:8080 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl lb-del lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:80 [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:8080 [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
-AT_CHECK([ovn-nbctl --may-exist lb-add lb1 [[ae0f::10]]:9090 [[fd0f::10]]:8080,[[fd0f::20]]:8080 udp])
-AT_CHECK([ovn-nbctl lb-del lb0 [[ae0f::10]]:80])
-AT_CHECK([ovn-nbctl lb-del lb1])
-AT_CHECK([ovn-nbctl lb-list | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP                IPs
-<0>    lb2                 tcp        [[ae0f::10]]:8080    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb2                 tcp        [[ae0f::10]]:8080    [[fd0f::10]]:80,[[fd0f::20]]:80
-])
-
-dnl Add load balancer to logical switch.
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:80])
-AT_CHECK([ovn-nbctl lb-add lb1 [[ae0f::10]]:80 [[fd0f::10]]:80,[[fd0f::20]]:80 udp])
-AT_CHECK([ovn-nbctl lb-add lb3 ae0f::10 fd0f::10,fd0f::20])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl --may-exist ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
-
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<2>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
-])
-
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
-])
-
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-del ls0 lb3])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
-AT_CHECK([ovn-nbctl --if-exists ls-lb-del ls0 lb1])
-
-dnl Remove all load balancers from logical switch.
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb0])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb1])
-AT_CHECK([ovn-nbctl ls-lb-add ls0 lb3])
-AT_CHECK([ovn-nbctl ls-lb-del ls0])
-AT_CHECK([ovn-nbctl ls-lb-list ls0 | uuidfilt], [0], [])
-
-dnl Add load balancer to logical router.
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl --may-exist lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb2], [1], [],
-[ovn-nbctl: Multiple load balancers named 'lb2'.  Use a UUID.
-])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
-
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb0                 tcp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<2>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
-])
-
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [dnl
-UUID                                    LB                  PROTO      VIP              IPs
-<0>    lb1                 udp        [[ae0f::10]]:80    [[fd0f::10]]:80,[[fd0f::20]]:80
-<1>    lb3                 tcp/udp    ae0f::10         fd0f::10,fd0f::20
-])
-
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-del lr0 lb3])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])
-AT_CHECK([ovn-nbctl --if-exists lr-lb-del lr0 lb1])
-
-dnl Remove all load balancers from logical router.
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb3])
-AT_CHECK([ovn-nbctl lr-lb-del lr0])
-AT_CHECK([ovn-nbctl lr-lb-list lr0 | uuidfilt], [0], [])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_basic_lr], [basic logical router commands], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
-<0> (lr0)
-])
-
-AT_CHECK([ovn-nbctl lr-add lr1])
-AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
-<0> (lr0)
-<1> (lr1)
-])
-
-AT_CHECK([ovn-nbctl lr-del lr0])
-AT_CHECK([ovn-nbctl lr-list | uuidfilt], [0], [dnl
-<0> (lr1)
-])
-
-AT_CHECK([ovn-nbctl show lr0])
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
-  [router <0> (lr0)
-])
-AT_CHECK([ovn-nbctl lr-add lr0], [1], [],
-  [ovn-nbctl: lr0: a router with this name already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lr-add lr0])
-AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0],
-  [router <0> (lr0)
-])
-AT_CHECK([ovn-nbctl --add-duplicate lr-add lr0])
-AT_CHECK([ovn-nbctl --may-exist --add-duplicate lr-add lr0], [1], [],
-  [ovn-nbctl: --may-exist and --add-duplicate may not be used together
-])
-AT_CHECK([ovn-nbctl lr-del lr0], [1], [],
-  [ovn-nbctl: Multiple logical routers named 'lr0'.  Use a UUID.
-])
-
-AT_CHECK([ovn-nbctl lr-del lr2], [1], [],
-  [ovn-nbctl: lr2: router name not found
-])
-AT_CHECK([ovn-nbctl --if-exists lr-del lr2])
-
-AT_CHECK([ovn-nbctl lr-add])
-AT_CHECK([ovn-nbctl lr-add])
-AT_CHECK([ovn-nbctl --add-duplicate lr-add], [1], [],
-  [ovn-nbctl: --add-duplicate requires specifying a name
-])
-AT_CHECK([ovn-nbctl --may-exist lr-add], [1], [],
-  [ovn-nbctl: --may-exist requires specifying a name
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_basic_lrp], [basic logical router port commands], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02
-])
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03:04 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp0: invalid mac address 00:00:00:01:02:03:04
-])
-
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
-
-AT_CHECK([ovn-nbctl show lr0 | uuidfilt], [0], [dnl
-router <0> (lr0)
-    port lrp0
-        mac: "00:00:00:01:02:03"
-        networks: [["192.168.1.1/24"]]
-])
-
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp0: a port with this name already exists
-])
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
-AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
-<0> (lrp0)
-])
-
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24 peer=lrp1-peer])
-AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
-<0> (lrp0)
-<1> (lrp1)
-])
-
-AT_CHECK([ovn-nbctl lr-add lr1])
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp1: a port with this name already exists
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr1 lrp1 00:00:00:01:02:03 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp1: port already exists but in router lr0
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:04:05:06 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp1: port already exists with mac 00:00:00:01:02:03
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24], [1], [],
-  [ovn-nbctl: lrp1: port already exists with mismatching peer
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 10.0.0.1/24 peer=lrp1-peer], [1], [],
-  [ovn-nbctl: lrp1: port already exists with different network
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24 peer=lrp1-peer])
-
-AT_CHECK([ovn-nbctl lrp-del lrp1])
-AT_CHECK([ovn-nbctl lrp-list lr0 | uuidfilt], [0], [dnl
-<0> (lrp0)
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24 10.0.0.1/24 peer=lrp1-peer])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 192.168.1.1/24 172.16.0.1/24 peer=lrp1-peer], [1], [],
-  [ovn-nbctl: lrp1: port already exists with different network
-])
-
-AT_CHECK([ovn-nbctl --may-exist lrp-add lr0 lrp1 00:00:00:01:02:03 10.0.0.1/24 192.168.1.1/24 peer=lrp1-peer])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lrp_gw_chassi], [logical router port gateway chassis], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [])
-
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], [],
-[ovn-nbctl: lp0: port name not found
-])
-
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [],
-[ovn-nbctl: lp0: port name not found
-])
-
-AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], [],
-[ovn-nbctl: lp0: port name not found
-])
-
-AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], [1], [],
-[ovn-nbctl: chassis chassis1 is not added to logical port lrp0
-])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1])
-
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis1     0
-])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10])
-
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis1    10
-])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20])
-
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis1    20
-])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5])
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis1    20
-lrp0-chassis2     5
-])
-
-AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1])
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis2     5
-])
-
-AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2])
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0])
-
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 1])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 10])
-AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis3 5])
-AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl
-lrp0-chassis2    10
-lrp0-chassis3     5
-lrp0-chassis1     1
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lrp_enable], [logical router port enable and disable], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24])
-AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
-])
-
-AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 disabled])
-AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [disabled
-])
-
-AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 enabled])
-AT_CHECK([ovn-nbctl lrp-get-enabled lrp0], [0], [enabled
-])
-
-AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [],
-  [ovn-nbctl: xyzzy: state must be "enabled" or "disabled"
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_routes], [routes], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-
-dnl Check IPv4 routes
-AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.0/24 11.0.1.1 lp0])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.2])
-
-dnl Add overlapping route with 10.0.0.1/24
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1], [1], [],
-  [ovn-nbctl: duplicate prefix: 10.0.0.0/24
-])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111a/24 11.0.0.1], [1], [],
-  [ovn-nbctl: bad prefix argument: 10.0.0.111a/24
-])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24a 11.0.0.1], [1], [],
-  [ovn-nbctl: bad prefix argument: 10.0.0.111/24a
-])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1a], [1], [],
-  [ovn-nbctl: bad next hop argument: 11.0.0.1a
-])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.111/24 11.0.0.1/24], [1], [],
-  [ovn-nbctl: bad IPv4 nexthop argument: 11.0.0.1/24
-])
-AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1/64], [1], [],
-  [ovn-nbctl: bad IPv6 nexthop argument: 2001:0db8:0:f103::1/64
-])
-
-AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24 11.0.0.1])
-AT_CHECK([ovn-nbctl --policy=src-ip lr-route-add lr0 9.16.1.0/24 11.0.0.1])
-
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv4 Routes
-              10.0.0.0/24                  11.0.0.1 dst-ip
-              10.0.1.0/24                  11.0.1.1 dst-ip lp0
-              9.16.1.0/24                  11.0.0.1 src-ip
-                0.0.0.0/0               192.168.0.1 dst-ip
-])
-
-AT_CHECK([ovn-nbctl --may-exist lr-route-add lr0 10.0.0.111/24 11.0.0.1 lp1])
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv4 Routes
-              10.0.0.0/24                  11.0.0.1 dst-ip lp1
-              10.0.1.0/24                  11.0.1.1 dst-ip lp0
-              9.16.1.0/24                  11.0.0.1 src-ip
-                0.0.0.0/0               192.168.0.1 dst-ip
-])
-
-dnl Delete non-existent prefix
-AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.2.1/24], [1], [],
-  [ovn-nbctl: no matching prefix: 10.0.2.0/24
-])
-AT_CHECK([ovn-nbctl --if-exists lr-route-del lr0 10.0.2.1/24])
-
-AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24])
-AT_CHECK([ovn-nbctl lr-route-del lr0 9.16.1.0/24])
-
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv4 Routes
-              10.0.0.0/24                  11.0.0.1 dst-ip lp1
-                0.0.0.0/0               192.168.0.1 dst-ip
-])
-
-AT_CHECK([ovn-nbctl lr-route-del lr0])
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-])
-
-dnl Check IPv6 routes
-AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0 2001:0db8:0:f101::1])
-AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0])
-AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1])
-
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv6 Routes
-            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
-          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
-                     ::/0        2001:db8:0:f101::1 dst-ip
-])
-
-AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64])
-
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv6 Routes
-          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
-                     ::/0        2001:db8:0:f101::1 dst-ip
-])
-
-AT_CHECK([ovn-nbctl lr-route-del lr0])
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-])
-
-dnl Check IPv4 and IPv6 routes
-AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0])
-AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.1])
-AT_CHECK([ovn-nbctl lr-route-add lr0 0:0:0:0:0:0:0:0/0 2001:0db8:0:f101::1])
-AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0])
-AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1])
-
-AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl
-IPv4 Routes
-              10.0.0.0/24                  11.0.0.1 dst-ip
-              10.0.1.0/24                  11.0.1.1 dst-ip lp0
-                0.0.0.0/0               192.168.0.1 dst-ip
-
-IPv6 Routes
-            2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
-          2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
-                     ::/0        2001:db8:0:f101::1 dst-ip
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
-AT_CHECK([ovn-nbctl lr-add lr0])
-
-dnl Add policies with allow and drop actions
-AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24" drop])
-AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24" allow])
-AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24" allow])
-AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" drop])
-AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64" drop])
-
-dnl Add duplicated policy
-AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24" drop], [1], [],
-  [ovn-nbctl: Same routing policy already existed on the logical router lr0.
-])
-
-dnl Add duplicated policy
-AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 1.1.1.0/24" deny], [1], [],
-  [ovn-nbctl: deny: action must be one of "allow", "drop", and "reroute"
-])
-
-dnl Delete by priority and match string
-AT_CHECK([ovn-nbctl lr-policy-del lr0 100 "ip4.src == 1.1.1.0/24"])
-AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
-Routing Policies
-       101                              ip4.src == 2.1.1.0/24           allow
-       101                              ip4.src == 2.1.2.0/24            drop
-       101                               ip6.src == 2002::/64            drop
-       100                              ip4.src == 1.1.2.0/24           allow
-])
-
-dnl Delete all policies for given priority
-AT_CHECK([ovn-nbctl lr-policy-del lr0 101])
-AT_CHECK([ovn-nbctl lr-policy-list lr0], [0], [dnl
-Routing Policies
-       100                              ip4.src == 1.1.2.0/24           allow
-])
-
-dnl Add policy with reroute action
-AT_CHECK([ovn-nbctl lr-policy-add lr0 102 "ip4.src == 3.1.2.0/24" reroute 3.3.3.3])
-
-dnl Add policy with invalid reroute ip
-AT_CHECK([ovn-nbctl lr-policy-add lr0 103 "ip4.src == 3.1.2.0/24" reroute 3.3.3.x], [1], [],
-  [ovn-nbctl: bad next hop argument: 3.3.3.x
-])
-
-dnl Add policy with reroute action
-AT_CHECK([ovn-nbctl lr-policy-add lr0 104 "ip6.src == 2001::/64" reroute 2002::5])
-
-dnl Add policy with invalid reroute ip
-AT_CHECK([ovn-nbctl lr-policy-add lr0 105 "ip6.src == 2001::/64" reroute 2002::x], [1], [],
-  [ovn-nbctl: bad next hop argument: 2002::x
-])
-
-])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_lsp_types], [lsp types], [
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
-
-dnl switchport type defaults to empty
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-
-])
-
-dnl The following are the valid entries for
-dnl switchport type
-AT_CHECK([ovn-nbctl lsp-set-type lp0 l2gateway])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-l2gateway
-])
-
-AT_CHECK([ovn-nbctl lsp-set-type lp0 router])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-router
-])
-
-AT_CHECK([ovn-nbctl lsp-set-type lp0 localnet])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-localnet
-])
-
-AT_CHECK([ovn-nbctl lsp-set-type lp0 localport])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-localport
-])
-
-AT_CHECK([ovn-nbctl lsp-set-type lp0 vtep])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-vtep
-])
-
-dnl All of these are valid southbound port types but
-dnl should be rejected for northbound logical switch
-dnl ports.
-AT_CHECK([ovn-nbctl lsp-set-type lp0 l3gateway], [1], [], [dnl
-ovn-nbctl: Logical switch port type 'l3gateway' is unrecognized. Not setting type.
-])
-AT_CHECK([ovn-nbctl lsp-set-type lp0 patch], [1], [], [dnl
-ovn-nbctl: Logical switch port type 'patch' is unrecognized. Not setting type.
-])
-AT_CHECK([ovn-nbctl lsp-set-type lp0 chassisredirect], [1], [], [dnl
-ovn-nbctl: Logical switch port type 'chassisredirect' is unrecognized. Not setting type.
-])
-
-dnl switch port type should still be "vtep" since previous
-dnl commands failed.
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-vtep
-])
-
-dnl Attempt a nonsense type
-AT_CHECK([ovn-nbctl lsp-set-type lp0 eggs], [1], [], [dnl
-ovn-nbctl: Logical switch port type 'eggs' is unrecognized. Not setting type.
-])
-
-dnl Empty string should work too
-AT_CHECK([ovn-nbctl lsp-set-type lp0 ""])
-AT_CHECK([ovn-nbctl lsp-get-type lp0], [0], [dnl
-
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_connection], [connection], [
-AT_CHECK([ovn-nbctl --inactivity-probe=30000 set-connection ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnnb_db.sock])
-AT_CHECK([ovn-nbctl list connection | grep inactivity_probe], [0], [dnl
-inactivity_probe    : 30000
-inactivity_probe    : 30000
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [
-dnl Check that dry run has no permanent effect.
-AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt], [0], [dnl
-<0> (ls0)
-])
-AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
-])
-
-dnl Check that dry-run mode is not sticky.
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl
-<0> (ls0)
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_oneline_output], [oneline output], [
-AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1])
-
-dnl Expect one line for one command.
-AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl
-<0> (ls0)\n<1> (ls1)
-])
-
-dnl Expect lines for two commands.
-AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt], [0], [dnl
-<0> (ls0)\n<1> (ls1)
-<0> (ls0)\n<1> (ls1)
-])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_error_paths], [commands parser error paths], [
-dnl FIXME: Duplicate options are allowed when passed with global options.
-dnl        For example: ovn-nbctl --if-exists --if-exists list Logical_Switch
-
-dnl Duplicate option
-AT_CHECK([ovn-nbctl -- --if-exists --if-exists list Logical_Switch], [1], [], [stderr])
-AT_CHECK([grep 'option specified multiple times' stderr], [0], [ignore])
-
-dnl Missing command
-AT_CHECK([ovn-nbctl], [1], [], [stderr])
-AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl --if-exists], [1], [], [stderr])
-AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl --], [1], [], [stderr])
-AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- --if-exists], [1], [], [stderr])
-AT_CHECK([grep 'missing command name' stderr], [0], [ignore])
-
-dnl Unknown command
-AT_CHECK([ovn-nbctl foo], [1], [], [stderr])
-AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- foo], [1], [], [stderr])
-AT_CHECK([grep 'unknown command' stderr], [0], [ignore])
-
-dnl Unknown option
-AT_CHECK([ovn-nbctl --foo list Logical_Switch], [1], [], [stderr])
-AT_CHECK([grep 'unrecognized option' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- --foo list Logical_Switch], [1], [], [stderr])
-AT_CHECK([grep 'command has no .* option' stderr], [0], [ignore])
-
-dnl Missing option argument
-AT_CHECK([ovn-nbctl --columns], [1], [], [stderr])
-AT_CHECK([grep 'option .* requires an argument' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- --columns list Logical_Switch], [1], [], [stderr])
-AT_CHECK([grep 'missing argument to .* option' stderr], [0], [ignore])
-
-dnl Unexpected option argument
-AT_CHECK([ovn-nbctl --if-exists=foo list Logical_Switch], [1], [], [stderr])
-AT_CHECK([egrep 'option .* doesn'\''t allow an argument|option .* requires an argument' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- --if-exists=foo list Logical_Switch], [1], [], [stderr])
-AT_CHECK([grep 'option on .* does not accept an argument' stderr], [0], [ignore])
-
-dnl Not enough arguments
-AT_CHECK([ovn-nbctl list], [1], [], [stderr])
-AT_CHECK([grep 'command requires at least .* arguments' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- list], [1], [], [stderr])
-AT_CHECK([grep 'command requires at least .* arguments' stderr], [0], [ignore])
-
-dnl Too many arguments
-AT_CHECK([ovn-nbctl show foo bar], [1], [], [stderr])
-AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- show foo bar], [1], [], [stderr])
-AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl show foo --bar], [1], [], [stderr])
-AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore])
-
-AT_CHECK([ovn-nbctl -- show foo --bar], [1], [], [stderr])
-AT_CHECK([grep 'command takes at most .* arguments' stderr], [0], [ignore])])
-
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_port_groups], [port groups], [
-dnl Check that port group can be looked up by name
-AT_CHECK([ovn-nbctl create Port_Group name=pg0], [0], [ignore])
-AT_CHECK([ovn-nbctl get Port_Group pg0 name], [0], [dnl
-pg0
-])])
-
-OVN_NBCTL_TEST([ovn_nbctl_extra_newlines], [extra newlines], [
-dnl This test addresses a specific issue seen when running ovn-nbctl in
-dnl daemon mode. All we have to do is ensure that each time we list database
-dnl information, there is not an extra newline at the beginning of the output.
-AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
-AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
-name                : sw1
-])
-AT_CHECK([ovn-nbctl --columns=name list logical_switch sw1], [0], [dnl
-name                : sw1
-])])
-
-OVN_NBCTL_TEST([ovn_nbctl_table_formatting], [table formatting], [
-dnl This test addresses a specific issue seen when running ovn-nbctl in
-dnl daemon mode. We need to ensure that table formatting options are honored
-dnl when listing database information.
-AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
-AT_CHECK([ovn-nbctl --bare --columns=name list logical_switch sw1], [0], [dnl
-sw1
-])])
-dnl ---------------------------------------------------------------------
-
-OVN_NBCTL_TEST([ovn_nbctl_port_group_commands], [port group commands], [
-AT_CHECK([ovn-nbctl pg-add pg1], [0], [ignore])
-AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],
-[pg1
-])
-
-AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
-AT_CHECK([ovn-nbctl list port_group], [0], [])
-
-AT_CHECK([ovn-nbctl ls-add sw1], [0], [ignore])
-AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p1], [0], [ignore])
-SW1P1=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port sw1-p1)
-AT_CHECK([ovn-nbctl lsp-add sw1 sw1-p2], [0], [ignore])
-SW1P2=$(ovn-nbctl --bare --columns=_uuid list logical_switch_port sw1-p2)
-
-AT_CHECK([ovn-nbctl pg-add pg1 sw1-p1], [0], [ignore])
-AT_CHECK([ovn-nbctl --bare --columns=name list port_group pg1], [0],[dnl
-pg1
-])
-AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1], [0], [dnl
-$SW1P1
-])
-
-AT_CHECK([ovn-nbctl pg-set-ports pg1 sw1-p2], [0], [ignore])
-AT_CHECK_UNQUOTED([ovn-nbctl --bare --columns=ports list port_group pg1], [0], [dnl
-$SW1P2
-])
-
-AT_CHECK([ovn-nbctl pg-del pg1], [0], [ignore])
-AT_CHECK([ovn-nbctl list port_group], [0], [])
-])
-
-AT_SETUP([ovn-nbctl - daemon retry connection])
-OVN_NBCTL_TEST_START daemon
-AT_CHECK([kill `cat ovsdb-server.pid`])
-AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db], [0], [], [stderr])
-AT_CHECK([ovn-nbctl show], [0], [ignore])
-OVN_NBCTL_TEST_STOP /Terminated/d
-AT_CLEANUP
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
deleted file mode 100644
index 62e58fd..0000000
--- a/tests/ovn-northd.at
+++ /dev/null
@@ -1,900 +0,0 @@ 
-AT_BANNER([OVN northd])
-AT_SETUP([ovn -- check   from NBDB to SBDB])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl create Logical_Router name=R1
-ovn-sbctl chassis-add gw1 geneve 127.0.0.1
-ovn-sbctl chassis-add gw2 geneve 1.2.4.8
-
-# Connect alice to R1 as distributed router gateway port on hv2
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
-
-ovn-nbctl --wait=sb \
-    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
-                                     chassis_name=gw1 \
-                                     priority=20 -- \
-    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
-                                     chassis_name=gw2 \
-                                     priority=10 -- \
-    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
-
-nb_gwc1_uuid=`ovn-nbctl --bare --columns _uuid find Gateway_Chassis name="alice_gw1"`
-
-# With the new ha_chassis_group table added, there should be no rows in
-# gateway_chassis table in SB DB.
-AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
-])
-
-# There should be one ha_chassis_group with the name "alice"
-ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
-ha_chassis_group name="alice"`
-
-AT_CHECK([test $ha_chassi_grp_name = alice])
-
-ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group name=alice`
-
-AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
-logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
-])
-
-# There should be one ha_chassis_group with the name "alice"
-ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
-ha_chassis_group name="alice"`
-
-AT_CHECK([test $ha_chassi_grp_name = alice])
-
-ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group name=alice`
-
-AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
-logical_port="cr-alice" | grep $ha_chgrp_uuid | wc -l], [0], [1
-])
-
-ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
-# Trim the spaces.
-ha_ch=`echo $ha_ch | sed 's/ //g'`
-
-ha_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list="$ha_ch_list $i"
-done
-
-# Trim the spaces.
-ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
-
-AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
-
-# Delete chassis - gw2 in SB DB.
-# ovn-northd should not recreate ha_chassis rows
-# repeatedly when gw2 is deleted.
-ovn-sbctl chassis-del gw2
-
-ha_ch_list_1=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list_1="$ha_ch_list_1 $i"
-done
-
-# Trim the spaces.
-ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
-
-ha_ch_list_2=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list_2="$ha_ch_list_2 $i"
-done
-
-# Trim the spaces.
-ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
-
-AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
-
-# Add back the gw2 chassis
-ovn-sbctl chassis-add gw2 geneve 1.2.4.8
-
-# delete the 2nd Gateway_Chassis on NBDB for alice port
-gw_ch=`ovn-sbctl --bare --columns gateway_chassis find port_binding \
-logical_port="cr-alice"`
-AT_CHECK([test "$gw_ch" = ""])
-
-ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
-ha_ch=`echo $ha_ch | sed 's/ //g'`
-# Trim the spaces.
-echo "ha ch in grp = $ha_ch"
-
-ha_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list="$ha_ch_list $i"
-done
-
-# Trim the spaces.
-ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
-
-AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
-
-# delete the 2nd Gateway_Chassis on NBDB for alice port
-ovn-nbctl --wait=sb set Logical_Router_Port alice gateway_chassis=${nb_gwc1_uuid}
-
-# There should be only 1 row in ha_chassis SB DB table.
-AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0], [1
-])
-
-AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
-])
-
-# There should be only 1 row in ha_chassis SB DB table.
-AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0], [1
-])
-
-# delete all the gateway_chassis on NBDB for alice port
-
-ovn-nbctl --wait=sb clear Logical_Router_Port alice gateway_chassis
-
-# expect that the ha_chassis doesn't exist anymore
-AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
-])
-
-AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
-])
-
-AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
-])
-
-# expect that the ha_chassis doesn't exist anymore
-AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
-])
-AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check Gateway_Chassis propagation from NBDB to SBDB backwards compatibility])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl create Logical_Router name=R1
-ovn-sbctl chassis-add gw1 geneve 127.0.0.1
-ovn-sbctl chassis-add gw2 geneve 1.2.4.8
-
-ovn-nbctl --wait=sb lrp-add R1 bob 00:00:02:01:02:03 172.16.1.1/24 \
-    -- set Logical_Router_Port bob options:redirect-chassis="gw1"
-
-
-# It should be converted to ha_chassis_group entries in SBDB, and
-# still redirect-chassis is kept for backwards compatibility
-
-AT_CHECK([ovn-sbctl list gateway_chassis | wc -l], [0], [0
-])
-
-AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis | wc -l], [0], [1
-])
-
-AT_CHECK([ovn-sbctl --bare --columns _uuid list ha_chassis_group | wc -l], [0], [1
-])
-
-# There should be one ha_chassis_group with the name "bob_gw1"
-ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
-ha_chassis_group name="bob_gw1"`
-
-AT_CHECK([test $ha_chassi_grp_name = bob_gw1])
-
-ha_chgrp_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group name=bob_gw1`
-
-AT_CHECK([ovn-sbctl --bare --columns ha_chassis_group find port_binding \
-logical_port="cr-bob" | grep $ha_chgrp_uuid | wc -l], [0], [1
-])
-
-ovn-nbctl --wait=sb remove Logical_Router_Port bob options redirect-chassis
-
-# expect that the ha_chassis/ha_chassis_group doesn't exist anymore
-
-AT_CHECK([ovn-sbctl find Gateway_Chassis name=bob_gw1], [0], [])
-AT_CHECK([ovn-sbctl list ha_chassis | wc -l], [0], [0
-])
-
-AT_CHECK([ovn-sbctl list ha_chassis_group | wc -l], [0], [0
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check up state of VIF LSP])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add S1
-ovn-nbctl --wait=sb lsp-add S1 S1-vm1
-AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xdown])
-
-ovn-sbctl chassis-add hv1 geneve 127.0.0.1
-ovn-sbctl lsp-bind S1-vm1 hv1
-AT_CHECK([test x`ovn-nbctl lsp-get-up S1-vm1` = xup])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check up state of router LSP linked to a distributed LR])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl lr-add R1
-ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
-
-ovn-nbctl ls-add S1
-ovn-nbctl lsp-add S1 S1-R1
-ovn-nbctl lsp-set-type S1-R1 router
-ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
-ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
-AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check up state of router LSP linked to a gateway LR])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-sbctl chassis-add gw1 geneve 127.0.0.1
-
-ovn-nbctl create Logical_Router name=R1 options:chassis=gw1
-ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
-
-ovn-nbctl ls-add S1
-ovn-nbctl lsp-add S1 S1-R1
-ovn-nbctl lsp-set-type S1-R1 router
-ovn-nbctl lsp-set-addresses S1-R1 02:ac:10:01:00:01
-ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
-
-ovn-sbctl lsp-bind S1-R1 gw1
-AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check up state of router LSP linked to an LRP with set Gateway Chassis])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-sbctl chassis-add gw1 geneve 127.0.0.1
-
-ovn-nbctl lr-add R1
-ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24
-ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1
-
-ovn-nbctl ls-add S1
-ovn-nbctl lsp-add S1 S1-R1
-ovn-nbctl lsp-set-type S1-R1 router
-ovn-nbctl lsp-set-addresses S1-R1 router
-ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
-AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check IPv6 RA config propagation to SBDB])
-ovn_start
-
-ovn-nbctl lr-add ro
-ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
-ovn-nbctl ls-add sw
-ovn-nbctl lsp-add sw sw-ro
-ovn-nbctl lsp-set-type sw-ro router
-ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
-ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
-ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:mtu=1280
-
-uuid=$(ovn-sbctl --columns=_uuid --bare find Port_Binding logical_port=ro-sw)
-
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_send_periodic],
-[0], ["true"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_address_mode],
-[0], [slaac
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[0], ["600"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[0], ["200"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
-[0], ["1280"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_eth],
-[0], ["00:00:00:00:00:01"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_addr],
-[0], ["fe80::200:ff:fe00:1"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_prefixes],
-[0], ["aef0::/64"
-])
-
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=300
-ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=600
-
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[0], ["300"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[0], ["225"
-])
-
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=300
-ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=250
-
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[0], ["300"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[0], ["225"
-])
-
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=0
-ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=0
-
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[0], ["4"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[0], ["3"
-])
-
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=3600
-ovn-nbctl --wait=sb set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=2400
-
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[0], ["1800"
-])
-AT_CHECK([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[0], ["1350"
-])
-
-ovn-nbctl --wait=sb set Logical_Router_port ro-sw ipv6_ra_configs:send_periodic=false
-
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_send_periodic],
-[1], [], [ovn-sbctl: no key "ipv6_ra_send_periodic" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_max_interval],
-[1], [], [ovn-sbctl: no key "ipv6_ra_max_interval" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_min_interval],
-[1], [], [ovn-sbctl: no key "ipv6_ra_min_interval" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_mtu],
-[1], [], [ovn-sbctl: no key "ipv6_ra_mtu" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_address_mode],
-[1], [], [ovn-sbctl: no key "ipv6_ra_address_mode" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_eth],
-[1], [], [ovn-sbctl: no key "ipv6_ra_src_eth" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_src_addr],
-[1], [], [ovn-sbctl: no key "ipv6_ra_src_addr" in Port_Binding record "${uuid}" column options
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get Port_Binding ${uuid} options:ipv6_ra_prefixes],
-[1], [], [ovn-sbctl: no key "ipv6_ra_prefixes" in Port_Binding record "${uuid}" column options
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- test unixctl])
-ovn_init_db ovn-sb; ovn-sbctl init
-ovn_init_db ovn-nb; ovn-nbctl init
-
-# test unixctl option
-mkdir "$ovs_base"/northd
-as northd start_daemon ovn-northd --unixctl="$ovs_base"/northd/ovn-northd.ctl --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-ovn-nbctl ls-add sw
-ovn-nbctl --wait=sb lsp-add sw p1
-# northd created with unixctl option successfully created port_binding entry
-AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding logical_port="p1" | wc -l], [0], [1
-])
-AT_CHECK([ovn-nbctl --wait=sb lsp-del p1])
-
-# ovs-appctl exit with unixctl option
-OVS_APP_EXIT_AND_WAIT_BY_TARGET(["$ovs_base"/northd/ovn-northd.ctl], ["$ovs_base"/northd/ovn-northd.pid])
-
-# Check no port_binding entry for new port as ovn-northd is not running
-ovn-nbctl lsp-add sw p2
-ovn-nbctl --timeout=10 --wait=sb sync
-AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding logical_port="p2" | wc -l], [0], [0
-])
-
-# test default unixctl path
-as northd start_daemon ovn-northd --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-ovn-nbctl --wait=sb lsp-add sw p3
-# northd created with default unixctl path successfully created port_binding entry
-AT_CHECK([ovn-sbctl --bare --columns datapath find port_binding logical_port="p3" | wc -l], [0], [1
-])
-
-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])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- check HA_Chassis_Group propagation from NBDB to SBDB])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
-
-# ovn-northd should not create HA chassis group and HA chassis rows
-# unless the HA chassis group in OVN NB DB is associated to
-# a logical router port or logical port of type external.
-AT_CHECK([ovn-sbctl --bare --columns name find ha_chassis_group name="hagrp1" \
-| wc -l], [0], [0
-])
-
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
-
-# There should be no HA_Chassis rows in SB DB.
-AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
-| grep -v '-' | wc -l ], [0], [0
-])
-
-# Add chassis ch1.
-ovn-sbctl chassis-add ch1 geneve 127.0.0.2
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list chassis | grep ch1 | wc -l`])
-
-# There should be no HA_Chassis rows
-AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
-| grep -v '-' | wc -l ], [0], [0
-])
-
-# Create a logical router port and attach ha chassis group.
-ovn-nbctl lr-add lr0
-ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
-
-hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1`
-ovn-nbctl set logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Make sure that ovn-northd doesn't recreate the ha_chassis
-# records if the chassis record is missing in SB DB.
-
-ha_ch_list_1=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list_1="$ha_ch_list_1 $i"
-done
-
-# Trim the spaces.
-ha_ch_list_1=`echo $ha_ch_list_1 | sed 's/ //g'`
-
-ha_ch_list_2=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list_2="$ha_ch_list_2 $i"
-done
-
-# Trim the spaces.
-ha_ch_list_2=`echo $ha_ch_list_2 | sed 's/ //g'`
-
-AT_CHECK([test "$ha_ch_list_1" = "$ha_ch_list_2"])
-
-# 2 HA chassis should be created with 'chassis' column empty because
-# we have not added hv1 and hv2 chassis to the SB DB.
-AT_CHECK([test 2 = `ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
-| grep -v '-' | wc -l`])
-
-# We should have 1 ha chassis with 'chassis' column set for hv1
-AT_CHECK([test 1 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | awk '{print $3}' \
-| grep '-' | wc -l`])
-
-# Create another logical router port and associate to the same ha_chasis_group
-ovn-nbctl lr-add lr1
-ovn-nbctl lrp-add lr1 lr1-public 00:00:20:20:12:14 182.168.0.100/24
-
-ovn-nbctl set logical_router_port lr1-public ha_chassis_group=$hagrp1_uuid
-
-# We should still have 1 HA chassis group and 3 HA chassis in SB DB.
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Change the priority of ch1 - ha chassis in NB DB. It should get
-# reflected in SB DB.
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 100
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns priority find \
-ha_chassis | grep 100 | wc -l`])
-
-# Delete ch1 HA chassis in NB DB.
-ovn-nbctl --wait=sb ha-chassis-group-remove-chassis hagrp1 ch1
-
-OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Add back the ha chassis
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 40
-OVS_WAIT_UNTIL([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Delete lr0-public. We should still have 1 HA chassis group and
-# 3 HA chassis in SB DB.
-ovn-nbctl --wait=sb lrp-del lr0-public
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Delete lr1-public. There should be no HA chassis group in SB DB.
-ovn-nbctl --wait=sb lrp-del lr1-public
-
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc -l`])
-
-# Add lr0-public again
-ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
-ovn-nbctl set logical_router_port lr0-public ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Create a Gateway chassis. ovn-northd should ignore this.
-ovn-nbctl lrp-set-gateway-chassis lr0-public ch-1 20
-
-# There should be only 1 HA chassis group in SB DB with the
-# name hagrp1.
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group | wc -l`])
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Now delete HA chassis group. ovn-northd should create HA chassis group
-# with the Gateway chassis name
-ovn-nbctl clear logical_router_port lr0-public ha_chassis_group
-ovn-nbctl ha-chassis-group-del hagrp1
-
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="lr0-public" | wc -l`])
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
-find ha_chassis | wc -l`])
-
-ovn-nbctl lrp-set-gateway-chassis lr0-public ch2 10
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="lr0-public" | wc -l`])
-
-ovn-sbctl --bare --columns _uuid find ha_chassis
-OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Test if 'ref_chassis' column is properly set or not in
-# SB DB ha_chassis_group.
-ovn-nbctl ls-add sw0
-ovn-nbctl lsp-add sw0 sw0-p1
-
-ovn-sbctl chassis-add ch2 geneve 127.0.0.3
-ovn-sbctl chassis-add ch3 geneve 127.0.0.4
-ovn-sbctl chassis-add comp1 geneve 127.0.0.5
-ovn-sbctl chassis-add comp2 geneve 127.0.0.6
-
-ovn-nbctl lrp-add lr0 lr0-sw0 00:00:20:20:12:14 10.0.0.1/24
-ovn-nbctl lsp-add sw0 sw0-lr0
-ovn-nbctl lsp-set-type sw0-lr0 router
-ovn-nbctl lsp-set-addresses sw0-lr0 router
-ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
-
-ovn-sbctl lsp-bind sw0-p1 comp1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xup])
-
-comp1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp1"`
-comp2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp2"`
-ch2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="comp1"`
-
-echo "comp1_ch_uuid = $comp1_ch_uuid"
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp1_ch_uuid" = "$ref_ch_list"])
-
-# unbind sw0-p1
-ovn-sbctl lsp-unbind sw0-p1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p1` = xdown])
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "" = "$ref_ch_list"])
-
-# Bind sw0-p1 in comp2
-ovn-sbctl lsp-bind sw0-p1 comp2
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp2_ch_uuid" = "$ref_ch_list"])
-
-ovn-nbctl ls-add sw1
-ovn-nbctl lsp-add sw1 sw1-p1
-ovn-nbctl lr-add lr1
-ovn-nbctl lrp-add lr1 lr1-sw1 00:00:20:20:12:15 20.0.0.1/24
-ovn-nbctl lsp-add sw1 sw1-lr1
-ovn-nbctl lsp-set-type sw1-lr1 router
-ovn-nbctl lsp-set-addresses sw1-lr1 router
-ovn-nbctl lsp-set-options sw1-lr1 router-port=lr1-sw1
-
-# Bind sw1-p1 in comp1.
-ovn-sbctl lsp-bind sw1-p1 comp1
-# Wait until sw1-p1 is up
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xup])
-
-# sw1-p1 is not connected to lr0. So comp1 should not be in 'ref_chassis'
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp2_ch_uuid" = "$ref_ch_list"])
-
-# Now attach sw0 to lr1
-ovn-nbctl lrp-add lr1 lr1-sw0 00:00:20:20:12:16 10.0.0.10/24
-ovn-nbctl lsp-add sw0 sw0-lr1
-ovn-nbctl lsp-set-type sw0-lr1 router
-ovn-nbctl lsp-set-addresses sw0-lr1 router
-ovn-nbctl lsp-set-options sw0-lr1 router-port=lr1-sw0
-
-# Both comp1 and comp2 should be in 'ref_chassis' as sw1 is indirectly
-# connected to lr0
-exp_ref_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
-do
-    if test $i = $comp1_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    elif test $i = $comp2_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    fi
-done
-
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# Unind sw1-p1. comp2 should not be in the ref_chassis.
-ovn-sbctl lsp-unbind sw1-p1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1-p1` = xdown])
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp2_ch_uuid" = "$ref_ch_list"])
-
-# Create sw2 and attach it to lr2
-ovn-nbctl ls-add sw2
-ovn-nbctl lsp-add sw2 sw2-p1
-ovn-nbctl lr-add lr2
-ovn-nbctl lrp-add lr2 lr2-sw2 00:00:20:20:12:17 30.0.0.1/24
-ovn-nbctl lsp-add sw2 sw2-lr2
-ovn-nbctl lsp-set-type sw2-lr2 router
-ovn-nbctl lsp-set-addresses sw2-lr2 router
-ovn-nbctl lsp-set-options sw2-lr2 router-port=lr2-sw2
-
-# Bind sw2-p1 to comp1
-ovn-sbctl lsp-bind sw2-p1 comp1
-# Wait until sw2-p1 is up
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw2-p1` = xup])
-
-# sw2-p1 is not connected to lr0. So comp1 should not be in 'ref_chassis'
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp2_ch_uuid" = "$ref_ch_list"])
-
-# Now attach sw1 to lr2. With this sw2-p1 is indirectly connected to lr0.
-ovn-nbctl lrp-add lr2 lr2-sw1 00:00:20:20:12:18 20.0.0.10/24
-ovn-nbctl lsp-add sw1 sw1-lr2
-ovn-nbctl lsp-set-type sw1-lr2 router
-ovn-nbctl lsp-set-addresses sw1-lr2 router
-ovn-nbctl lsp-set-options sw1-lr2 router-port=lr2-sw1
-
-# sw2-p1 is indirectly connected to lr0. So comp1 (and comp2) should be in
-# 'ref_chassis'
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# Create sw0-p2 and bind it to comp1
-ovn-nbctl lsp-add sw0 sw0-p2
-ovn-sbctl lsp-bind sw0-p2 comp1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xup])
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# unbind sw0-p2
-ovn-sbctl lsp-unbind sw0-p2
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0-p2` = xdown])
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# Delete lr1-sw0. comp1 should be deleted from ref_chassis as there is no link
-# from sw1 and sw2 to lr0.
-ovn-nbctl lrp-del lr1-sw0
-
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$comp2_ch_uuid" = "$ref_ch_list"])
-
-# Set redirect-chassis option to lr0-public. It should be ignored.
-ovn-nbctl set logical_router_port lr0-public options:redirect-chassis=ch1
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group | wc -l`])
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="lr0-public" | wc -l`])
-
-ovn-sbctl --bare --columns _uuid find ha_chassis
-OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Delete the gateway chassis. HA chassis group should be created in SB DB
-# for the redirect-chassis option.
-ovn-nbctl clear logical_router_port lr0-public gateway_chassis
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group | wc -l`])
-
-ovn-sbctl list ha_chassis_group
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="lr0-public_ch1" | wc -l`])
-
-ovn-sbctl --bare --columns _uuid find ha_chassis
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl list ha_chassis | grep chassis |
-grep -v chassis-name | wc -l`])
-
-# Clear the redirect-chassis option.
-ovn-nbctl clear logical_router_port lr0-public options
-
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
-AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
-
-# Delete old sw0.
-ovn-nbctl ls-del sw0
-
-# Create external logical ports and associate ha_chassis_group
-ovn-nbctl ls-add sw0
-ovn-nbctl lsp-add sw0 sw0-pext1
-ovn-nbctl lsp-add sw0 sw0-pext2
-ovn-nbctl lsp-add sw0 sw0-p1
-
-ovn-nbctl lsp-set-addresses sw0-pext1 "00:00:00:00:00:03 10.0.0.3"
-ovn-nbctl lsp-set-addresses sw0-pext2 "00:00:00:00:00:03 10.0.0.4"
-ovn-nbctl lsp-set-addresses sw0-p1 "00:00:00:00:00:03 10.0.0.5"
-
-ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
-
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch1 30
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 20
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch3 10
-
-# ovn-northd should not create HA chassis group and HA chassis rows
-# unless the HA chassis group in OVN NB DB is associated to
-# a logical router port or logical port of type external.
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
-AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
-
-hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group \
-name=hagrp1`
-
-# The type of the lsp - sw0-pext1 is still not set to external.
-# So ha_chassis_group should be ignored.
-ovn-nbctl set logical_switch_port sw0-pext1 ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | grep chassis | wc -l`])
-
-# Set the type of sw0-pext1 to external
-ovn-nbctl lsp-set-type sw0-pext1 external
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group \
-name=hagrp1`
-
-AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
-ha_chassis_group find port_binding logical_port=sw0-pext1`])
-
-# Set the type of sw0-pext2 to external and associate ha_chassis_group
-ovn-nbctl lsp-set-type sw0-pext2 external
-ovn-nbctl set logical_switch_port sw0-pext2 ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis |
-grep -v chassis-name | wc -l`])
-AT_CHECK([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
-ha_chassis_group find port_binding logical_port=sw0-pext1`])
-
-OVS_WAIT_UNTIL([test "$sb_hagrp1_uuid" = `ovn-sbctl --bare --columns \
-ha_chassis_group find port_binding logical_port=sw0-pext2`])
-
-# sw0-p1 is a normal port. So ha_chassis_group should not be set
-# in port_binding.
-ovn-nbctl --wait=sb set logical_switch_port sw0-p1 \
-ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=sw0-p1) = x], [0], [])
-
-# Clear ha_chassis_group for sw0-pext1
-ovn-nbctl --wait=sb clear logical_switch_port sw0-pext1 ha_chassis_group
-
-OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=sw0-pext1) = x], [0], [])
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns name find \
-ha_chassis_group name="hagrp1" | wc -l`])
-
-AT_CHECK([test 3 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-# Clear ha_chassis_group for sw0-pext2
-ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2 ha_chassis_group
-
-OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=sw0-pext2) = x], [0], [])
-
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group |  wc -l`])
-AT_CHECK([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
-
-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])
-
-AT_CLEANUP
diff --git a/tests/ovn-performance.at b/tests/ovn-performance.at
deleted file mode 100644
index a8a15f8..0000000
--- a/tests/ovn-performance.at
+++ /dev/null
@@ -1,424 +0,0 @@ 
-#
-# Tests targeting performance of OVN components.
-#
-
-m4_divert_push([PREPARE_TESTS])
-
-# vec_cmp VALUE_VEC OP-VALUE_VEC
-#
-# Compares each value from VALUE_VEC to the operator-value pair from the
-# OP-VALUE_VEC.
-#
-# VALUE_VEC must be a list of values separated by a character from $IFS.
-# OP-VALUE_VEC must be a list of operator-value expressions separated by a
-# character from $IFS.  Operator-value expressions cannot contain any characters
-# from $IFS like spaces. '=' is treated as an equality operator ('==') for
-# conciseness.
-#
-# Returns the result of each comparison as a list of boolean values (0 or 1)
-# separated by a new-line character.
-vec_cmp() {
-    local a b i j
-
-    i=0
-    for a in $1; do
-        j=0
-        for b in $2; do
-            if test $i -eq $j; then
-                # Replace assignment '=' with equality comparison '=='
-                case "$b" in
-                =[[0-9]]*) b="=$b" ;;
-                esac
-
-                echo $(($a $b))
-                break
-            fi
-            j=$((j + 1))
-        done
-        i=$((i + 1))
-    done
-}
-
-# vec_sub VEC_A VEC_B
-#
-# Subtracts two vectors:
-#
-#     VEC_A = [a1, a2, ...]
-#     VEC_B = [b1, b2, ...]
-#     OUT = [(a1 - b1), (a2 - b2), ...]
-#
-# VEC_A and VEC_B must be lists of values separated by a character from $IFS.
-vec_sub() {
-    local a b i j
-
-    i=0
-    for a in $1; do
-        j=0
-        for b in $2; do
-            if test $i -eq $j; then
-                echo $((a - b))
-                break
-            fi
-            j=$((j + 1))
-        done
-        i=$((i + 1))
-    done
-}
-
-# vec_fold VEC OP
-#
-# Reduces a vector to a single value by applying the binary operator OP (i.e.,
-# one that requires two arguments) cumulatively to all vector elements from left
-# to right:
-#
-#     VEC = [e1, e2, e3 ...]
-#     OUT = (...((e1 OP e2) OP e3) OP ...)
-#
-# VEC must be a list of values separated by a character from $IFS.
-vec_fold() {
-    local first op prod
-
-    first=1
-    op=$2
-    for a in $1; do
-        if test $first -eq 1; then
-            prod=$a
-            first=0
-        else
-            prod=$((prod $op a))
-        fi
-    done
-    echo $prod
-}
-
-# read_counters SANDBOXES TARGET COUNTER
-#
-# Prints out the coverage COUNTER for the TARGET in each of the SANDBOXES.
-#
-# SANDBOXES must be a list of strings separated by a character from $IFS.
-read_counters() {
-    local sims="$1" target="$2" counter="$3"
-
-    for sim in $sims; do
-        as $sim ovs-appctl -t "$target" coverage/read-counter "$counter" || return 1
-    done
-}
-
-# counter_delta_ SANDBOXES TARGET COUNTER COMMAND
-#
-# Runs the COMMAND and reports the COUNTER change registered during the command
-# run for the given TARGET in each of the SANDBOXES.
-counter_delta_() {
-    local sims="$1" target="$2" counter="$3" cmd="$4"
-    local before after
-
-    before=$(read_counters "$sims" "$target" "$counter") || return 1
-    eval "$cmd" >/dev/null || return 1
-    after=$(read_counters "$sims" "$target" "$counter") || return 1
-
-    vec_sub "$after" "$before"
-}
-
-# counter_delta SANDBOXES TARGET COUNTER COMMAND
-#
-# Same as counter_delta_ but also prints the COUNTER values together with the
-# COMMAND to standard error.
-counter_delta() {
-    local cmd="$4"
-    local v
-
-    v=$(counter_delta_ "$@") || return 1
-
-    # Dump the counters and the command for troubleshooting
-    echo "$v" | tr '\n' '\t' >&2
-    echo "$cmd" >&2
-
-    echo "$v"
-}
-
-# vec_cmp_counter_delta SANDBOXES TARGET COUNTER CONDS COMMAND
-#
-# Check if COUNTER change in the TARGET app in each of the SANDBOXES after
-# running the COMMAND meets the conditions listed as operator-value pairs in
-# CONDS.
-vec_cmp_counter_delta() {
-    local v
-
-    v=$(counter_delta "$1" "$2" "$3" "$5") || return 1
-    v=$(vec_cmp "$v" "$4") || return 1
-    v=$(vec_fold "$v" "&&") || return 1
-
-    echo "$v"
-}
-
-# cmp_counter_delta SANDBOXES TARGET COUNTER COND COMMAND
-#
-# Check if COUNTER change in the TARGET app in each of the SANDBOXES after
-# running the COMMAND meets the COND condition given as a operator-value pair.
-cmp_counter_delta() {
-    local conds=""
-
-    # Use the same condition for each sandbox
-    for _ in $1; do
-        conds="$conds $4"
-    done
-
-    vec_cmp_counter_delta "$1" "$2" "$3" "$conds" "$5"
-}
-
-m4_divert_pop([PREPARE_TESTS])
-
-# CHECK_COUNTER_DELTA_IS_ZERO SANDBOXES TARGET COUNTER COMMAND
-#
-# Runs the COMMAND and checks if the COUNTER value for the TARGET in all of
-# the SANDBOXES did not change.
-m4_define([CHECK_COUNTER_DELTA_IS_ZERO],[
-    rv=$(cmp_counter_delta "$1" "$2" "$3" "=0" "$4")
-    rc=$?
-    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
-])
-
-# CHECK_COUNTER_DELTA_IS_NOT_ZERO SANDBOXES TARGET COUNTER COMMAND
-#
-# Runs the COMMAND and checks if the COUNTER value for the TARGET in
-# all of the SANDBOXES has changed.
-m4_define([CHECK_COUNTER_DELTA_IS_NOT_ZERO],[
-    rv=$(cmp_counter_delta "$1" "$2" "$3" ">0" "$4")
-    rc=$?
-    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
-])
-
-# CHECK_COUNTER_DELTA_COND SANDBOXES TARGET COUNTER CONDS COMMAND
-#
-# Runs the COMMAND and checks if the COUNTER value for the TARGET in all of the
-# SANDBOXES satisfies the conditions listed in CONDS.
-m4_define([CHECK_COUNTER_DELTA_COND],[
-    rv=$(vec_cmp_counter_delta "$1" "$2" "$3" "$4" "$5")
-    rc=$?
-    AT_CHECK([test $rc -eq 0 -a $rv -eq 1])
-])
-
-# OVN_CONTROLLER_EXPECT_HIT SANDBOXES COUNTER COMMAND
-#
-# Checks if the COUNTER value has changed for any of the ovn-controller
-# processes in the SANDBOXES when the COMMAND was run.
-m4_define([OVN_CONTROLLER_EXPECT_HIT],[
-    CHECK_COUNTER_DELTA_IS_NOT_ZERO([$1], [ovn-controller], [$2], [$3])
-])
-
-# OVN_CONTROLLER_EXPECT_NO_HIT SANDBOXES COUNTER COMMAND
-#
-# Checks if the COUNTER value has not changed for any of the ovn-controller
-# processes in the SANDBOXES when the COMMAND was run.
-m4_define([OVN_CONTROLLER_EXPECT_NO_HIT],[
-    CHECK_COUNTER_DELTA_IS_ZERO([$1], [ovn-controller], [$2], [$3])
-])
-
-# OVN_CONTROLLER_EXPECT_HIT_COND SANDBOXES COUNTER CONDS COMMAND
-#
-# Checks if the change of the COUNTER value, when the COMMAND was run, of the
-# ovn-controller process in each of the SANDBOXES meets the conditions in
-# CONDS. CONDS must be a list of operator-value pairs, for example "[>0 =0]",
-# following the same order as SANDBOXES.
-m4_define([OVN_CONTROLLER_EXPECT_HIT_COND],[
-    CHECK_COUNTER_DELTA_COND([$1], [ovn-controller], [$2], [$3], [$4])
-])
-
-AT_SETUP([ovn -- ovn-controller incremental processing])
-# Check which operations the trigger full logical flow processing.
-#
-# Create and destroy logical routers, switches, ports, address sets and ACLs
-# while counting calls to lflow_run() in ovn-controller.
-
-ovn_start
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-done
-
-# Add router lr1
-OVN_CONTROLLER_EXPECT_HIT(
-    [hv1 hv2], [lflow_run],
-    [ovn-nbctl --wait=hv lr-add lr1]
-)
-
-for i in 1 2; do
-    ls=ls$i
-    lsp=$ls-lr1
-    lrp=lr1-$ls
-
-    # Add switch $ls
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv ls-add $ls]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv add Logical_Switch $ls other_config subnet=10.0.$i.0/24]
-    )
-
-    # Add router port to $ls
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lrp-add lr1 $lrp 02:00:00:00:0$i:01 10.0.$i.1/24]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-add $ls $lsp]
-    )
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-set-type $lsp router]
-    )
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-set-options $lsp router-port=$lrp]
-    )
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-set-addresses $lsp router]
-    )
-done
-
-get_lsp_uuid () {
-    ovn-nbctl lsp-list ls${1#lp} | grep $1 | awk '{ print $1 }'
-}
-
-pg_ports=
-
-for i in 1 2; do
-    j=$((i%2 + 1))
-    as=as$i
-    ls=ls$i
-    lp=lp$i
-    vif=vif$i
-
-    # Add port $lp
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-add $ls $lp]
-    )
-
-    pg_ports="$pg_port `get_lsp_uuid $lp`"
-
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv lsp-set-addresses $lp "dynamic"]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl wait-until Logical_Switch_Port $lp dynamic_addresses!=[[]] &&
-         ovn-nbctl --wait=hv sync]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl get Logical_Switch_Port $lp dynamic_addresses &&
-         ovn-nbctl --wait=hv sync]
-    )
-
-    # Add address set $as
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv create Address_Set name="$as"]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv add Address_Set "$as" addresses "10.0.$i.10"]
-    )
-
-    # Add ACLs for port $lp
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv acl-add $ls to-lport 1001 'outport == \"$lp\" && ip4.src == \$$as' allow]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv acl-add $ls to-lport 1000 'outport == \"$lp\"' drop]
-    )
-
-    # Bind port $lp and wait for it to come up
-    OVN_CONTROLLER_EXPECT_HIT_COND(
-        [hv$i hv$j], [lflow_run], [>0 =0],
-        [as hv$i ovs-vsctl add-port br-int $vif -- set Interface $vif external-ids:iface-id=$lp &&
-         ovn-nbctl wait-until Logical_Switch_Port $lp 'up=true' &&
-         ovn-nbctl --wait=hv sync]
-    )
-done
-
-for i in 1 2; do
-    j=$((i%2 + 1))
-    as=as$i
-    ls=ls$i
-    lp=lp$i
-
-    # Delete ACLs for port $lp
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv acl-del $ls to-lport 1001 'outport == \"$lp\" && ip4.src == \$$as']
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv acl-del $ls to-lport 1000 'outport == \"$lp\"']
-    )
-
-    # Delete address set $as
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv remove Address_Set "$as" addresses "10.0.$i.10"]
-    )
-    OVN_CONTROLLER_EXPECT_NO_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv destroy Address_Set "$as"]
-    )
-done
-
-OVN_CONTROLLER_EXPECT_NO_HIT(
-    [hv1 hv2], [lflow_run],
-    [ovn-nbctl --wait=hv create Port_Group name=pg1 ports=\"$pg_ports\"]
-)
-
-# Add ACLs for port group pg1
-OVN_CONTROLLER_EXPECT_NO_HIT(
-    [hv1 hv2], [lflow_run],
-    [ovn-nbctl --wait=hv acl-add pg1 to-lport 1001 'outport == @pg1 && ip4.src == $pg1_ip4' allow]
-)
-
-for i in 1 2; do
-    j=$((i%2 + 1))
-    lp=lp$i
-
-    # Delete port $lp
-    OVN_CONTROLLER_EXPECT_HIT_COND(
-        [hv$i hv$j], [lflow_run], [>0 =0],
-        [ovn-nbctl --wait=hv lsp-del $lp]
-    )
-done
-
-# Delete port group pg1
-OVN_CONTROLLER_EXPECT_NO_HIT(
-    [hv1 hv2], [lflow_run],
-    [ovn-nbctl --wait=hv destroy Port_Group pg1]
-)
-
-for i in 1 2; do
-    ls=ls$i
-
-    # Delete switch $ls
-    OVN_CONTROLLER_EXPECT_HIT(
-        [hv1 hv2], [lflow_run],
-        [ovn-nbctl --wait=hv ls-del $ls]
-    )
-done
-
-# Delete router lr1
-OVN_CONTROLLER_EXPECT_HIT(
-    [hv1 hv2], [lflow_run],
-    [ovn-nbctl --wait=hv lr-del lr1]
-)
-
-OVN_CLEANUP([hv1], [hv2])
-
-AT_CLEANUP
diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at
deleted file mode 100644
index 650e357..0000000
--- a/tests/ovn-sbctl.at
+++ /dev/null
@@ -1,150 +0,0 @@ 
-AT_BANNER([ovn-sbctl])
-
-# OVN_SBCTL_TEST_START
-m4_define([OVN_SBCTL_TEST_START],
-  [dnl Create databases (ovn-nb, ovn-sb).
-   AT_KEYWORDS([ovn])
-   for daemon in ovn-nb ovn-sb; do
-      AT_CHECK([ovsdb-tool create $daemon.db $abs_top_srcdir/${daemon%%-*}/${daemon}.ovsschema])
-   done
-
-   dnl Start ovsdb-servers.
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovnnb_db.pid --unixctl=$OVS_RUNDIR/ovnnb_db.ctl --log-file=ovsdb_nb.log --remote=punix:$OVS_RUNDIR/ovnnb_db.sock ovn-nb.db ], [0], [], [stderr])
-   AT_CHECK([ovsdb-server --detach --no-chdir --pidfile=ovnsb_db.pid --unixctl=$OVS_RUNDIR/ovnsb_db.ctl --log-file=ovsdb_sb.log --remote=punix:$OVS_RUNDIR/ovnsb_db.sock ovn-sb.db], [0], [], [stderr])
-   on_exit "kill `cat ovnnb_db.pid` `cat ovnsb_db.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d
-/ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']])
-   AT_CAPTURE_FILE([ovsdb-server.log])
-
-   dnl Start ovn-northd.
-   AT_CHECK([ovn-northd --detach --no-chdir --pidfile --log-file --ovnnb-db=unix:$OVS_RUNDIR/ovnnb_db.sock --ovnsb-db=unix:$OVS_RUNDIR/ovnsb_db.sock], [0], [], [stderr])
-   on_exit "kill `cat ovn-northd.pid`"
-   AT_CHECK([[sed < stderr '
-/vlog|INFO|opened log file/d']])
-   AT_CAPTURE_FILE([ovn-northd.log])
-])
-
-# OVN_SBCTL_TEST_STOP
-m4_define([OVN_SBCTL_TEST_STOP],
-  [AT_CHECK([check_logs "$1"])
-   OVS_APP_EXIT_AND_WAIT([ovn-northd])
-   OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnnb_db.ctl], [$OVS_RUNDIR/ovnnb_db.pid])
-   OVS_APP_EXIT_AND_WAIT_BY_TARGET([$OVS_RUNDIR/ovnsb_db.ctl], [$OVS_RUNDIR/ovnsb_db.pid])])
-
-dnl ---------------------------------------------------------------------
-
-AT_SETUP([ovn-sbctl - chassis commands])
-OVN_SBCTL_TEST_START
-ovn_init_db ovn-sb
-
-AT_CHECK([ovn-sbctl chassis-add ch0 geneve 1.2.3.4])
-AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list encap | sort],
-         [0], [dnl
-1.2.3.4,geneve
-])
-
-AT_CHECK([ovn-sbctl chassis-add ch1 stt,geneve,vxlan 1.2.3.5])
-AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list encap | sort],
-         [0], [dnl
-1.2.3.4,geneve
-1.2.3.5,geneve
-1.2.3.5,stt
-1.2.3.5,vxlan
-])
-
-AT_CHECK([ovn-sbctl chassis-del ch0])
-AT_CHECK([ovn-sbctl -f csv -d bare --no-headings --columns ip,type list encap | sort],
-         [0], [dnl
-1.2.3.5,geneve
-1.2.3.5,stt
-1.2.3.5,vxlan
-])
-
-OVN_SBCTL_TEST_STOP
-as ovn-sb
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-AT_CLEANUP
-
-dnl ---------------------------------------------------------------------
-
-AT_SETUP([ovn-sbctl])
-OVN_SBCTL_TEST_START
-
-AT_CHECK([ovn-nbctl ls-add br-test])
-AT_CHECK([ovn-nbctl lsp-add br-test vif0])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif0 f0:ab:cd:ef:01:02])
-AT_CHECK([ovn-sbctl chassis-add ch0 stt 1.2.3.5])
-AT_CHECK([ovn-nbctl --wait=sb sync])
-AT_CHECK([ovn-sbctl lsp-bind vif0 ch0])
-
-AT_CHECK([ovn-sbctl show], [0], [dnl
-Chassis ch0
-    Encap stt
-        ip: "1.2.3.5"
-        options: {csum="true"}
-    Port_Binding vif0
-])
-
-# adds another 'vif1'
-AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses vif1 f0:ab:cd:ef:01:03])
-AT_CHECK([ovn-sbctl lsp-bind vif1 ch0])
-
-AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl
-Chassis ch0
-    Encap stt
-        ip: "1.2.3.5"
-        options: {csum="true"}
-    Port_Binding vif
-    Port_Binding vif
-])
-
-# deletes 'vif1'
-AT_CHECK([ovn-nbctl lsp-del vif1])
-AT_CHECK([ovn-nbctl --wait=sb sync])
-
-AT_CHECK([ovn-sbctl show], [0], [dnl
-Chassis ch0
-    Encap stt
-        ip: "1.2.3.5"
-        options: {csum="true"}
-    Port_Binding vif0
-])
-
-uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':' -f2 | tr -d ' ')
-AT_CHECK_UNQUOTED([ovn-sbctl --columns=logical_port,mac,chassis list Port_Binding], [0], [dnl
-logical_port        : vif0
-mac                 : [["f0:ab:cd:ef:01:02"]]
-chassis             : ${uuid}
-])
-
-# test the passing down of logical port type and options.
-AT_CHECK([ovn-nbctl --wait=sb lsp-add br-test vtep0])
-AT_CHECK([ovn-nbctl lsp-set-type vtep0 vtep])
-AT_CHECK([ovn-nbctl lsp-set-options vtep0 vtep_physical_switch=p0 vtep_logical_switch=l0])
-
-AT_CHECK([ovn-sbctl --timeout=10 wait-until Port_Binding vtep0 options!={}])
-AT_CHECK([ovn-sbctl --columns=logical_port,mac,type,options list Port_Binding vtep0], [0], [dnl
-logical_port        : vtep0
-mac                 : [[]]
-type                : vtep
-options             : {vtep_logical_switch=l0, vtep_physical_switch=p0}
-])
-
-OVN_SBCTL_TEST_STOP
-AT_CLEANUP
-
-dnl ---------------------------------------------------------------------
-
-AT_SETUP([ovn-sbctl - connection])
-OVN_SBCTL_TEST_START
-
-AT_CHECK([ovn-sbctl --inactivity-probe=30000 set-connection ptcp:6641:127.0.0.1 punix:$OVS_RUNDIR/ovnsb_db.sock])
-AT_CHECK([ovn-sbctl list connection | grep inactivity_probe], [0], [dnl
-inactivity_probe    : 30000
-inactivity_probe    : 30000
-])
-
-OVN_SBCTL_TEST_STOP
-AT_CLEANUP
diff --git a/tests/ovn.at b/tests/ovn.at
deleted file mode 100644
index cb380d2..0000000
--- a/tests/ovn.at
+++ /dev/null
@@ -1,14702 +0,0 @@ 
-# OVN_CHECK_PACKETS([PCAP], [EXPECTED])
-#
-# This compares packets read from PCAP, in pcap format, to those read
-# from EXPECTED, which is a text file containing packets as hex
-# strings, one per line.  If PCAP contains fewer packets than
-# EXPECTED, it waits up to 10 seconds for more packets to appear.
-#
-# The implementation is an m4 macro that is mostly implemented in
-# terms of a shell function.  This reduces the size of the generated
-# testsuite file since the shell function is only emitted once even
-# when this macro is invoked many times.
-m4_divert_text([PREPARE_TESTS],
-  [ovn_check_packets__ () {
-     echo
-     echo "checking packets in $1 against $2:"
-     rcv_pcap=$1
-     rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
-     exp_text=$2
-     exp_n=`wc -l < "$exp_text"`
-     OVS_WAIT_UNTIL(
-       [$PYTHON "$top_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
-        rcv_n=`wc -l < "$rcv_text"`
-        echo "rcv_n=$rcv_n exp_n=$exp_n"
-        test $rcv_n -ge $exp_n])
-     sort $exp_text > expout
-   }
-])
-m4_define([OVN_CHECK_PACKETS],
-  [ovn_check_packets__ "$1" "$2"
-   AT_CHECK([sort $rcv_text], [0], [expout])])
-
-AT_BANNER([OVN components])
-
-AT_SETUP([ovn -- lexer])
-dnl For lines without =>, input and expected output are identical.
-dnl For lines with =>, input precedes => and expected output follows =>.
-AT_DATA([test-cases.txt], [dnl
-foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456
-"abc\u0020def" => "abc def"
-" => error("Input ends inside quoted string.")dnl "
-
-$foo $bar $baz $quuxquuxquux $_abcd_ $a.b.c.d $a123_.456
-$1 => error("`$' must be followed by a valid identifier.") 1
-
-a/*b*/c => a c
-a//b c => a
-a/**/b => a b
-a/*/b => a error("`/*' without matching `*/'.")
-a/*/**/b => a b
-a/b => a error("`/' is only valid as part of `//' or `/*'.") b
-
-0 1 12345 18446744073709551615
-18446744073709551616 => error("Decimal constants must be less than 2**64.")
-9999999999999999999999 => error("Decimal constants must be less than 2**64.")
-01 => error("Decimal constants must not have leading zeros.")
-
-0/0
-0/1
-1/0 => error("Value contains unmasked 1-bits.")
-1/1
-128/384
-1/3
-1/ => error("Integer constant expected.")
-
-1/0x123 => error("Value and mask have incompatible formats.")
-
-0x1234
-0x01234 => 0x1234
-0x0 => 0
-0x000 => 0
-0xfedcba9876543210
-0XFEDCBA9876543210 => 0xfedcba9876543210
-0xfedcba9876543210fedcba9876543210
-0x0000fedcba9876543210fedcba9876543210 => 0xfedcba9876543210fedcba9876543210
-0x => error("Hex digits expected following 0x.")
-0X => error("Hex digits expected following 0X.")
-0x0/0x0 => 0/0
-0x0/0x1 => 0/0x1
-0x1/0x0 => error("Value contains unmasked 1-bits.")
-0xffff/0x1ffff
-0x. => error("Invalid syntax in hexadecimal constant.")
-
-192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0
-256.1.2.3 => error("Invalid numeric constant.")
-192.168.0.0/16
-192.168.0.0/255.255.0.0 => 192.168.0.0/16
-192.168.0.0/255.255.255.0 => 192.168.0.0/24
-192.168.0.0/255.255.0.255
-192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.")
-192.168.0.0/32
-192.168.0.0/255.255.255.255 => 192.168.0.0/32
-1.2.3.4:5 => 1.2.3.4 : 5
-
-::
-::1
-ff00::1234 => ff00::1234
-2001:db8:85a3::8a2e:370:7334
-2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334
-2001:0db8:85a3:0000:0000:8a2e:0370:7334 => 2001:db8:85a3::8a2e:370:7334
-::ffff:192.0.2.128
-::ffff:c000:0280 => ::ffff:192.0.2.128
-::1/::1
-::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128
-::1/128
-ff00::/8
-ff00::/ff00:: => ff00::/8
-
-01:23:45:67:ab:cd
-01:23:45:67:AB:CD => 01:23:45:67:ab:cd
-fe:dc:ba:98:76:54
-FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54
-01:00:00:00:00:00/01:00:00:00:00:00
-ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
-fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff
-ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked 1-bits.")
-fe:x => error("Invalid numeric constant.")
-00:01:02:03:04:x => error("Invalid numeric constant.")
-
-# Test that operators are tokenized as expected, even without white space.
-(){}[[]]==!=<<=>>=!&&||..,;=<->--: => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <-> -- :
-& => error("`&' is only valid as part of `&&'.")
-| => error("`|' is only valid as part of `||'.")
-- => error("`-' is only valid as part of `--'.")
-
-^ => error("Invalid character `^' in input.")
-])
-AT_CAPTURE_FILE([input.txt])
-sed 's/ =>.*//' test-cases.txt > input.txt
-sed 's/.* => //' test-cases.txt > expout
-AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout])
-AT_CLEANUP
-
-dnl The OVN expression parser needs to know what fields overlap with one
-dnl another.  This test therefore verifies that all the smaller registers
-dnl are defined as terms of subfields of the larger ones.
-dnl
-dnl When we add or remove registers this test needs to be updated, of course.
-AT_SETUP([ovn -- registers])
-AT_CHECK([ovstest test-ovn dump-symtab | grep reg | sort], [0],
-[[reg0 = xxreg0[96..127]
-reg1 = xxreg0[64..95]
-reg2 = xxreg0[32..63]
-reg3 = xxreg0[0..31]
-reg4 = xxreg1[96..127]
-reg5 = xxreg1[64..95]
-reg6 = xxreg1[32..63]
-reg7 = xxreg1[0..31]
-reg8 = xreg4[32..63]
-reg9 = xreg4[0..31]
-xreg0 = xxreg0[64..127]
-xreg1 = xxreg0[0..63]
-xreg2 = xxreg1[64..127]
-xreg3 = xxreg1[0..63]
-xreg4 = OXM_OF_PKT_REG4
-xxreg0 = NXM_NX_XXREG0
-xxreg1 = NXM_NX_XXREG1
-]])
-AT_CLEANUP
-
-dnl Check that the OVN conntrack field definitions are correct.
-AT_SETUP([ovn -- conntrack fields])
-AT_CHECK([ovstest test-ovn dump-symtab | grep ^ct | sort], [0],
-[[ct.dnat = ct_state[7]
-ct.est = ct_state[1]
-ct.inv = ct_state[4]
-ct.new = ct_state[0]
-ct.rel = ct_state[2]
-ct.rpl = ct_state[3]
-ct.snat = ct_state[6]
-ct.trk = ct_state[5]
-ct_label = NXM_NX_CT_LABEL
-ct_label.blocked = ct_label[0]
-ct_mark = NXM_NX_CT_MARK
-ct_state = NXM_NX_CT_STATE
-]])
-AT_CLEANUP
-
-AT_SETUP([ovn -- composition])
-AT_CHECK([ovstest test-ovn composition 2], [0], [ignore])
-AT_CLEANUP
-
-AT_SETUP([ovn -- expression parser])
-dnl For lines without =>, input and expected output are identical.
-dnl For lines with =>, input precedes => and expected output follows =>.
-AT_DATA([test-cases.txt], [[
-eth.type == 0x800
-eth.type==0x800 => eth.type == 0x800
-eth.type[0..15] == 0x800 => eth.type == 0x800
-
-vlan.present
-vlan.present == 1 => vlan.present
-!(vlan.present == 0) => vlan.present
-!(vlan.present != 1) => vlan.present
-!vlan.present
-vlan.present == 0 => !vlan.present
-vlan.present != 1 => !vlan.present
-!(vlan.present == 1) => !vlan.present
-!(vlan.present != 0) => !vlan.present
-
-eth.dst[0]
-eth.dst[0] == 1 => eth.dst[0]
-eth.dst[0] != 0 => eth.dst[0]
-!(eth.dst[0] == 0) => eth.dst[0]
-!(eth.dst[0] != 1) => eth.dst[0]
-
-!eth.dst[0]
-eth.dst[0] == 0 => !eth.dst[0]
-eth.dst[0] != 1 => !eth.dst[0]
-!(eth.dst[0] == 1) => !eth.dst[0]
-!(eth.dst[0] != 0) => !eth.dst[0]
-
-vlan.tci[12..15] == 0x3
-vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3
-vlan.tci[12..15] != 0x3
-vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3
-
-!vlan.pcp => vlan.pcp == 0
-!(vlan.pcp) => vlan.pcp == 0
-vlan.pcp == 0x4
-vlan.pcp != 0x4
-vlan.pcp > 0x4
-vlan.pcp >= 0x4
-vlan.pcp < 0x4
-vlan.pcp <= 0x4
-!(vlan.pcp != 0x4) => vlan.pcp == 0x4
-!(vlan.pcp == 0x4) => vlan.pcp != 0x4
-!(vlan.pcp <= 0x4) => vlan.pcp > 0x4
-!(vlan.pcp < 0x4) => vlan.pcp >= 0x4
-!(vlan.pcp >= 0x4) => vlan.pcp < 0x4
-!(vlan.pcp > 0x4) => vlan.pcp <= 0x4
-0x4 == vlan.pcp => vlan.pcp == 0x4
-0x4 != vlan.pcp => vlan.pcp != 0x4
-0x4 < vlan.pcp => vlan.pcp > 0x4
-0x4 <= vlan.pcp => vlan.pcp >= 0x4
-0x4 > vlan.pcp => vlan.pcp < 0x4
-0x4 >= vlan.pcp => vlan.pcp <= 0x4
-!(0x4 != vlan.pcp) => vlan.pcp == 0x4
-!(0x4 == vlan.pcp) => vlan.pcp != 0x4
-!(0x4 >= vlan.pcp) => vlan.pcp > 0x4
-!(0x4 > vlan.pcp) => vlan.pcp >= 0x4
-!(0x4 <= vlan.pcp) => vlan.pcp < 0x4
-!(0x4 < vlan.pcp) => vlan.pcp <= 0x4
-
-1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4
-1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
-1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4
-1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4
-1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4
-4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1
-4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1
-4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1
-4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1
-!(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4
-!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
-!(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4
-!(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4
-!(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4
-!(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1
-!(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1
-!(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1
-!(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1
-
-vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
-vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp == 4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4
-
-vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 && vlan.pcp != 0x3 && vlan.pcp != 0x4
-vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 && vlan.pcp == 0x4
-
-vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 || vlan.pcp != 0x4)
-vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3) && vlan.pcp == 0x4
-vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3) || vlan.pcp != 0x4)
-
-ip4.src == {10.0.0.0/8, 192.168.0.0/16, 172.16.20.0/24, 8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 || ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808
-ip6.src == ::1 => ip6.src == 0x1
-
-ip4.src == 1.2.3.4 => ip4.src == 0x1020304
-ip4.src == ::1.2.3.4/::ffff:ffff => ip4.src == 0x1020304
-ip6.src == ::1 => ip6.src == 0x1
-
-1
-0
-!1 => 0
-!0 => 1
-
-inport == "eth0"
-!(inport != "eth0") => inport == "eth0"
-
-(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => 0
-
-ip4.src == "eth0" => Integer field ip4.src is not compatible with string constant.
-inport == 1 => String field inport is not compatible with integer constant.
-ip4.src = 1.2.3.4 => Syntax error at `=' expecting relational operator.
-
-ip4.src > {1, 2, 3} => Only == and != operators may be used with value sets.
-eth.type > 0x800 => Only == and != operators may be used with nominal field eth.type.
-vlan.present > 0 => Only == and != operators may be used with Boolean field vlan.present.
-
-inport != "eth0" => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
-!(inport == "eth0") => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account).
-eth.type != 0x800 => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
-!(eth.type == 0x800) => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account).
-inport = "eth0" => Syntax error at `=' expecting relational operator.
-
-123 == 123 => Syntax error at `123' expecting field name.
-
-$name => Syntax error at `$name' expecting address set name.
-@name => Syntax error at `@name' expecting port group name.
-
-123 == xyzzy => Syntax error at `xyzzy' expecting field name.
-xyzzy == 1 => Syntax error at `xyzzy' expecting field name.
-
-inport[1] == 1 => Cannot select subfield of string field inport.
-
-eth.type[] == 1 => Syntax error at `@:>@' expecting small integer.
-eth.type[::1] == 1 => Syntax error at `::1' expecting small integer.
-eth.type[18446744073709551615] == 1 => Syntax error at `18446744073709551615' expecting small integer.
-
-eth.type[5!] => Syntax error at `!' expecting `@:>@'.
-
-eth.type[5..1] => Invalid bit range 5 to 1.
-
-eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field eth.type.
-
-eth.type[10] == 1 => Cannot select subfield of nominal field eth.type.
-
-eth.type => Explicit `!= 0' is required for inequality test of multibit field against 0.
-
-!(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test of multibit field against 0.
-
-123 => Syntax error at end of input expecting relational operator.
-
-123 x => Syntax error at `x' expecting relational operator.
-
-{1, "eth0"} => Syntax error at `"eth0"' expecting integer.
-
-eth.type == xyzzy => Syntax error at `xyzzy' expecting constant.
-
-(1 x) => Syntax error at `x' expecting `)'.
-
-!0x800 != eth.type => Missing parentheses around operand of !.
-
-eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => && and || must be parenthesized when used together.
-
-eth.dst == {} => Syntax error at `}' expecting constant.
-
-eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators may be used with masked constants.  Consider using subfields instead (e.g. eth.src[0..15] > 0x1111 in place of eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff).
-
-ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src.
-
-1 == eth.type == 2 => Range expressions must have the form `x < field < y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by `>=').
-
-eth.dst[40] x => Syntax error at `x' expecting end of input.
-
-ip4.src == {1.2.3.4, $set1, $unknownset} => Syntax error at `$unknownset' expecting address set name.
-eth.src == {$set3, badmac, 00:00:00:00:00:01} => Syntax error at `badmac' expecting constant.
-
-((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) => Parentheses nested too deeply.
-
-ct_label > $set4 => Only == and != operators may be used to compare a field against an empty value set.
-]])
-sed 's/ =>.*//' test-cases.txt > input.txt
-sed 's/.* => //' test-cases.txt > expout
-AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout])
-AT_CLEANUP
-
-AT_SETUP([ovn -- expression annotation])
-dnl Input precedes =>, expected output follows =>.
-dnl Empty lines and lines starting with # are ignored.
-AT_DATA([test-cases.txt], [[
-ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800
-ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800
-ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd)
-ip.proto == {123, 234} => (ip.proto == 0x7b || ip.proto == 0xea) && (eth.type == 0x800 || eth.type == 0x86dd)
-ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304 && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800
-
-# Nested expressions over a single symbol should be annotated with symbol's
-# prerequisites only once, at the top level.
-tcp.dst == 1 || (tcp.dst >= 2 && tcp.dst <= 3) => (tcp.dst == 0x1 || (tcp.dst >= 0x2 && tcp.dst <= 0x3)) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-
-ip => eth.type == 0x800 || eth.type == 0x86dd
-ip == 1 => eth.type == 0x800 || eth.type == 0x86dd
-ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd
-ip > 0 => Only == and != operators may be used with nominal field ip.
-!ip => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
-ip == 0 => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'.
-
-vlan.present => vlan.tci[12]
-!vlan.present => !vlan.tci[12]
-
-!vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12]
-vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 && vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12]
-!reg0 && !reg1 && !reg2 && !reg3 => xxreg0[96..127] == 0 && xxreg0[64..95] == 0 && xxreg0[32..63] == 0 && xxreg0[0..31] == 0
-
-ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type == 0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd))
-!ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd))
-ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd)
-
-bad_prereq != 0 => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
-self_recurse != 0 => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
-mutual_recurse_1 != 0 => Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_1'.
-mutual_recurse_2 != 0 => Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_2'.
-]])
-sed 's/ =>.*//' test-cases.txt > input.txt
-sed 's/.* => //' test-cases.txt > expout
-AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 1-term expression conversion])
-AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
-  [Tested converting all 1-terminal expressions with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2-term expression conversion])
-AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
-  [Tested converting 578 expressions of 2 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 3-term expression conversion])
-AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3], [0],
-  [Tested converting 67410 expressions of 3 terminals with 2 numeric vars (each 2 bits) in terms of operators == != < <= > >= and 2 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 3-term numeric expression simplification])
-AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=2 --svars=0 3], [0],
-  [Tested simplifying 490770 expressions of 3 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >=.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term string expression simplification])
-AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=0 --svars=4 4], [0],
-  [Tested simplifying 21978 expressions of 4 terminals with 4 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 3-term mixed expression simplification])
-AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=1 --svars=1 3], [0],
-  [Tested simplifying 127890 expressions of 3 terminals with 1 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 1 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- simplification special cases])
-simplify() {
-    echo "$1" | ovstest test-ovn simplify-expr
-}
-AT_CHECK([simplify 'eth.dst == 0/0'], [0], [1
-])
-AT_CHECK([simplify 'eth.dst != 0/0'], [0], [0
-])
-AT_CHECK([simplify 'tcp.dst >= 0'], [0],
-    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-])
-AT_CHECK([simplify 'tcp.dst <= 65535'], [0],
-    [ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-])
-AT_CHECK([simplify 'tcp.dst > 0'], [0],
-    [[(tcp.dst[0] || tcp.dst[1] || tcp.dst[2] || tcp.dst[3] || tcp.dst[4] || tcp.dst[5] || tcp.dst[6] || tcp.dst[7] || tcp.dst[8] || tcp.dst[9] || tcp.dst[10] || tcp.dst[11] || tcp.dst[12] || tcp.dst[13] || tcp.dst[14] || tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-]])
-AT_CHECK([simplify 'tcp.dst < 65535'], [0],
-    [[(!tcp.dst[0] || !tcp.dst[1] || !tcp.dst[2] || !tcp.dst[3] || !tcp.dst[4] || !tcp.dst[5] || !tcp.dst[6] || !tcp.dst[7] || !tcp.dst[8] || !tcp.dst[9] || !tcp.dst[10] || !tcp.dst[11] || !tcp.dst[12] || !tcp.dst[13] || !tcp.dst[14] || !tcp.dst[15]) && ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-]])
-AT_CLEANUP
-
-AT_SETUP([ovn -- is_chassis_resident simplification])
-simplify() {
-    echo "$1" | ovstest test-ovn simplify-expr
-}
-AT_CHECK([simplify 'is_chassis_resident("eth1")'], [0], [1
-])
-AT_CHECK([simplify 'is_chassis_resident("eth2")'], [0], [0
-])
-AT_CHECK([simplify '!is_chassis_resident("eth1")'], [0], [0
-])
-AT_CHECK([simplify '!is_chassis_resident("eth2")'], [0], [1
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term numeric expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 4], [0],
-  [Tested normalizing 1874026 expressions of 4 terminals with 3 numeric vars (each 1 bits) in terms of operators == != < <= > >=.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term string expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 4], [0],
-  [Tested normalizing 11242 expressions of 4 terminals with 3 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term mixed expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --bits=1 --svars=2 4], [0],
-  [Tested normalizing 175978 expressions of 4 terminals with 1 numeric vars (each 1 bits) in terms of operators == != < <= > >= and 2 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 5-term numeric expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
-  [Tested normalizing 1317600 expressions of 5 terminals with 3 numeric vars (each 1 bits) in terms of operators ==.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 5-term string expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
-  [Tested normalizing 368550 expressions of 5 terminals with 3 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 5-term mixed expression normalization])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
-  [Tested normalizing 216000 expressions of 5 terminals with 1 numeric vars (each 1 bits) in terms of operators == and 1 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term numeric expressions to flows])
-AT_KEYWORDS([expression])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2 --svars=0 --bits=2 --relops='==' 4], [0],
-  [Tested converting to flows 175978 expressions of 4 terminals with 2 numeric vars (each 2 bits) in terms of operators ==.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term string expressions to flows])
-AT_KEYWORDS([expression])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0 --svars=4 4], [0],
-  [Tested converting to flows 21978 expressions of 4 terminals with 4 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4-term mixed expressions to flows])
-AT_KEYWORDS([expression])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1 --bits=2 --svars=1 --relops='==' 4], [0],
-  [Tested converting to flows 48312 expressions of 4 terminals with 1 numeric vars (each 2 bits) in terms of operators == and 1 string vars.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 3-term numeric expressions to flows])
-AT_KEYWORDS([expression])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3 --svars=0 --bits=3 --relops='==' 3], [0],
-  [Tested converting to flows 41328 expressions of 3 terminals with 3 numeric vars (each 3 bits) in terms of operators ==.
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- converting expressions to flows -- string fields])
-AT_KEYWORDS([expression])
-expr_to_flow () {
-    echo "$1" | ovstest test-ovn expr-to-flows | sort
-}
-AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg14=0x5
-])
-AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg14=0x6
-])
-AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows)
-])
-AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl
-ip,reg14=0x5
-ipv6,reg14=0x5
-])
-AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl
-ip,reg14=0x6
-ipv6,reg14=0x6
-])
-AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows)
-])
-AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2", "LOCAL"}'], [0],
-[reg14=0x5
-reg14=0x6
-reg14=0xfffe
-])
-AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} && ip'], [0], [dnl
-ip,reg14=0x5
-ip,reg14=0x6
-ipv6,reg14=0x5
-ipv6,reg14=0x6
-])
-AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'], [0], [dnl
-(no flows)
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- converting expressions to flows -- address sets])
-AT_KEYWORDS([expression])
-expr_to_flow () {
-    echo "$1" | ovstest test-ovn expr-to-flows | sort
-}
-AT_CHECK([expr_to_flow 'ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3}'], [0], [dnl
-ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
-])
-AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
-ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
-])
-AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
-ip,nw_src=1.2.3.4
-ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
-])
-AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20, 5.5.5.0/24, $set1}'], [0], [dnl
-ip,nw_src=1.2.0.0/20
-ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
-ip,nw_src=5.5.5.0/24
-])
-AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
-ipv6,ipv6_src=::1
-ipv6,ipv6_src=::2
-ipv6,ipv6_src=::3
-])
-AT_CHECK([expr_to_flow 'ip6.src == {::1, $set2, ::4}'], [0], [dnl
-ipv6,ipv6_src=::1
-ipv6,ipv6_src=::2
-ipv6,ipv6_src=::3
-ipv6,ipv6_src=::4
-])
-AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, 00:00:00:00:00:02, 00:00:00:00:00:03}'], [0], [dnl
-dl_src=00:00:00:00:00:01
-dl_src=00:00:00:00:00:02
-dl_src=00:00:00:00:00:03
-])
-AT_CHECK([expr_to_flow 'eth.src == {$set3}'], [0], [dnl
-dl_src=00:00:00:00:00:01
-dl_src=00:00:00:00:00:02
-dl_src=00:00:00:00:00:03
-])
-AT_CHECK([expr_to_flow 'eth.src == {00:00:00:00:00:01, $set3, ba:be:be:ef:de:ad, $set3}'], [0], [dnl
-dl_src=00:00:00:00:00:01
-dl_src=00:00:00:00:00:02
-dl_src=00:00:00:00:00:03
-dl_src=ba:be:be:ef:de:ad
-])
-AT_CHECK([expr_to_flow 'ip4.src == {$set4}'], [0], [dnl
-(no flows)
-])
-AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set4}'], [0], [dnl
-ip,nw_src=1.2.3.4
-])
-AT_CHECK([expr_to_flow 'ip4.src == 1.2.3.4 || ip4.src == {$set4}'], [0], [dnl
-ip,nw_src=1.2.3.4
-])
-AT_CHECK([expr_to_flow 'ip4.src != {$set4}'], [0], [dnl
-
-])
-AT_CHECK([expr_to_flow 'ip4.src != {1.0.0.0/8, $set4}'], [0], [dnl
-ip,nw_src=0.0.0.0/1.0.0.0
-ip,nw_src=128.0.0.0/1
-ip,nw_src=16.0.0.0/16.0.0.0
-ip,nw_src=2.0.0.0/2.0.0.0
-ip,nw_src=32.0.0.0/32.0.0.0
-ip,nw_src=4.0.0.0/4.0.0.0
-ip,nw_src=64.0.0.0/64.0.0.0
-ip,nw_src=8.0.0.0/8.0.0.0
-])
-AT_CHECK([expr_to_flow 'ip4.src != 1.0.0.0/8 && ip4.src != {$set4}'], [0], [dnl
-ip,nw_src=0.0.0.0/1.0.0.0
-ip,nw_src=128.0.0.0/1
-ip,nw_src=16.0.0.0/16.0.0.0
-ip,nw_src=2.0.0.0/2.0.0.0
-ip,nw_src=32.0.0.0/32.0.0.0
-ip,nw_src=4.0.0.0/4.0.0.0
-ip,nw_src=64.0.0.0/64.0.0.0
-ip,nw_src=8.0.0.0/8.0.0.0
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- converting expressions to flows -- port groups])
-AT_KEYWORDS([expression])
-expr_to_flow () {
-    echo "$1" | ovstest test-ovn expr-to-flows | sort
-}
-AT_CHECK([expr_to_flow 'outport == @pg1'], [0], [dnl
-reg15=0x11
-reg15=0x12
-reg15=0x13
-])
-AT_CHECK([expr_to_flow 'outport == {@pg_empty}'], [0], [dnl
-(no flows)
-])
-AT_CHECK([expr_to_flow 'outport == {"lsp1", @pg_empty}'], [0], [dnl
-reg15=0x11
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- converting expressions to flows -- conjunction])
-AT_KEYWORDS([conjunction])
-expr_to_flow () {
-    echo "$1" | ovstest test-ovn expr-to-flows | sort
-}
-
-lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
-ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3}"
-AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
-conj_id=1,ip
-ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
-ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
-ip,nw_dst=20.0.0.3: conjunction(1, 0/2)
-ip,nw_src=10.0.0.1: conjunction(1, 1/2)
-ip,nw_src=10.0.0.2: conjunction(1, 1/2)
-ip,nw_src=10.0.0.3: conjunction(1, 1/2)
-])
-
-lflow="ip && (!ct.est || (ct.est && ct_label.blocked == 1))"
-AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
-ct_state=+est+trk,ct_label=0x1/0x1,ip
-ct_state=+est+trk,ct_label=0x1/0x1,ipv6
-ct_state=-est+trk,ip
-ct_state=-est+trk,ipv6
-])
-
-lflow="ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
-ip4.dst == {20.0.0.1, 20.0.0.2}"
-AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
-conj_id=1,ip
-ip,nw_dst=20.0.0.1: conjunction(1, 0/2)
-ip,nw_dst=20.0.0.2: conjunction(1, 0/2)
-ip,nw_src=10.0.0.1: conjunction(1, 1/2)
-ip,nw_src=10.0.0.2: conjunction(1, 1/2)
-ip,nw_src=10.0.0.3: conjunction(1, 1/2)
-])
-
-lflow="ip4 && ip4.src == {10.0.0.1, 10.0.0.2, 10.0.0.3} && \
-ip4.dst == {20.0.0.1, 20.0.0.2, 20.0.0.3} && \
-tcp.dst >= 1000 && tcp.dst <= 1010"
-
-AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
-conj_id=1,tcp
-tcp,nw_dst=20.0.0.1: conjunction(1, 0/3)
-tcp,nw_dst=20.0.0.2: conjunction(1, 0/3)
-tcp,nw_dst=20.0.0.3: conjunction(1, 0/3)
-tcp,nw_src=10.0.0.1: conjunction(1, 1/3)
-tcp,nw_src=10.0.0.2: conjunction(1, 1/3)
-tcp,nw_src=10.0.0.3: conjunction(1, 1/3)
-tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/3)
-tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/3)
-tcp,tp_dst=0x3f0/0xfffe: conjunction(1, 2/3)
-tcp,tp_dst=1000: conjunction(1, 2/3)
-tcp,tp_dst=1001: conjunction(1, 2/3)
-tcp,tp_dst=1010: conjunction(1, 2/3)
-])
-
-lflow="ip4 && ip4.src == {10.0.0.4, 10.0.0.5, 10.0.0.6} && \
-((ip4.dst == {20.0.0.4, 20.0.0.7, 20.0.0.8} && tcp.dst >= 1000 && \
-tcp.dst <= 2000 && tcp.src >=1000 && tcp.src <= 2000) \
-|| ip4.dst == 20.0.0.5 || ip4.dst == 20.0.0.6)"
-
-AT_CHECK([expr_to_flow "$lflow"], [0], [dnl
-conj_id=1,tcp
-ip,nw_src=10.0.0.4,nw_dst=20.0.0.5
-ip,nw_src=10.0.0.4,nw_dst=20.0.0.6
-ip,nw_src=10.0.0.5,nw_dst=20.0.0.5
-ip,nw_src=10.0.0.5,nw_dst=20.0.0.6
-ip,nw_src=10.0.0.6,nw_dst=20.0.0.5
-ip,nw_src=10.0.0.6,nw_dst=20.0.0.6
-tcp,nw_dst=20.0.0.4: conjunction(1, 0/4)
-tcp,nw_dst=20.0.0.7: conjunction(1, 0/4)
-tcp,nw_dst=20.0.0.8: conjunction(1, 0/4)
-tcp,nw_src=10.0.0.4: conjunction(1, 1/4)
-tcp,nw_src=10.0.0.5: conjunction(1, 1/4)
-tcp,nw_src=10.0.0.6: conjunction(1, 1/4)
-tcp,tp_dst=0x3ea/0xfffe: conjunction(1, 2/4)
-tcp,tp_dst=0x3ec/0xfffc: conjunction(1, 2/4)
-tcp,tp_dst=0x3f0/0xfff0: conjunction(1, 2/4)
-tcp,tp_dst=0x400/0xfe00: conjunction(1, 2/4)
-tcp,tp_dst=0x600/0xff00: conjunction(1, 2/4)
-tcp,tp_dst=0x700/0xff80: conjunction(1, 2/4)
-tcp,tp_dst=0x780/0xffc0: conjunction(1, 2/4)
-tcp,tp_dst=0x7c0/0xfff0: conjunction(1, 2/4)
-tcp,tp_dst=1000: conjunction(1, 2/4)
-tcp,tp_dst=1001: conjunction(1, 2/4)
-tcp,tp_dst=2000: conjunction(1, 2/4)
-tcp,tp_src=0x3ea/0xfffe: conjunction(1, 3/4)
-tcp,tp_src=0x3ec/0xfffc: conjunction(1, 3/4)
-tcp,tp_src=0x3f0/0xfff0: conjunction(1, 3/4)
-tcp,tp_src=0x400/0xfe00: conjunction(1, 3/4)
-tcp,tp_src=0x600/0xff00: conjunction(1, 3/4)
-tcp,tp_src=0x700/0xff80: conjunction(1, 3/4)
-tcp,tp_src=0x780/0xffc0: conjunction(1, 3/4)
-tcp,tp_src=0x7c0/0xfff0: conjunction(1, 3/4)
-tcp,tp_src=1000: conjunction(1, 3/4)
-tcp,tp_src=1001: conjunction(1, 3/4)
-tcp,tp_src=2000: conjunction(1, 3/4)
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- action parsing])
-dnl Unindented text is input (a set of OVN logical actions).
-dnl Indented text is expected output.
-AT_DATA([test-cases.txt],
-[[# drop
-drop;
-    encodes as drop
-drop; next;
-    Syntax error at `next' expecting end of input.
-next; drop;
-    Syntax error at `drop' expecting action.
-
-# output
-output;
-    encodes as resubmit(,64)
-
-# next
-next;
-    encodes as resubmit(,19)
-next(11);
-    formats as next;
-    encodes as resubmit(,19)
-next(0);
-    encodes as resubmit(,8)
-next(23);
-    encodes as resubmit(,31)
-
-next();
-    Syntax error at `)' expecting "pipeline" or "table".
-next(10;
-    Syntax error at `;' expecting `)'.
-next(24);
-    "next" action cannot advance beyond table 23.
-
-next(table=11);
-    formats as next;
-    encodes as resubmit(,19)
-next(pipeline=ingress);
-    formats as next;
-    encodes as resubmit(,19)
-next(table=11, pipeline=ingress);
-    formats as next;
-    encodes as resubmit(,19)
-next(pipeline=ingress, table=11);
-    formats as next;
-    encodes as resubmit(,19)
-
-next(pipeline=egress);
-    "next" action cannot advance from ingress to egress pipeline (use "output" action instead)
-
-next(table=10);
-    formats as next(10);
-    encodes as resubmit(,18)
-
-# Loading a constant value.
-tcp.dst=80;
-    formats as tcp.dst = 80;
-    encodes as set_field:80->tcp_dst
-    has prereqs ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd)
-eth.dst[40] = 1;
-    encodes as set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst
-vlan.pcp = 2;
-    encodes as set_field:0x4000/0xe000->vlan_tci
-    has prereqs vlan.tci[12]
-vlan.tci[13..15] = 2;
-    encodes as set_field:0x4000/0xe000->vlan_tci
-inport = "";
-    encodes as set_field:0->reg14
-ip.ttl=4;
-    formats as ip.ttl = 4;
-    encodes as set_field:4->nw_ttl
-    has prereqs eth.type == 0x800 || eth.type == 0x86dd
-outport="eth0"; next; outport="LOCAL"; next;
-    formats as outport = "eth0"; next; outport = "LOCAL"; next;
-    encodes as set_field:0x5->reg15,resubmit(,19),set_field:0xfffe->reg15,resubmit(,19)
-
-inport[1] = 1;
-    Cannot select subfield of string field inport.
-ip.proto[1] = 1;
-    Cannot select subfield of nominal field ip.proto.
-eth.dst[40] == 1;
-    Syntax error at `==' expecting `=' or `<->'.
-ip = 1;
-    Predicate symbol ip used where lvalue required.
-ip.proto = 6;
-    Field ip.proto is not modifiable.
-inport = {"a", "b"};
-    Syntax error at `{' expecting constant.
-inport = {};
-    Syntax error at `{' expecting constant.
-bad_prereq = 123;
-    Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
-self_recurse = 123;
-    Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
-vlan.present = 0;
-    Predicate symbol vlan.present used where lvalue required.
-
-# Moving one field into another.
-reg0=reg1;
-    formats as reg0 = reg1;
-    encodes as move:NXM_NX_XXREG0[64..95]->NXM_NX_XXREG0[96..127]
-vlan.pcp = reg0[0..2];
-    encodes as move:NXM_NX_XXREG0[96..98]->NXM_OF_VLAN_TCI[13..15]
-    has prereqs vlan.tci[12]
-reg0[10] = vlan.pcp[1];
-    encodes as move:NXM_OF_VLAN_TCI[14]->NXM_NX_XXREG0[106]
-    has prereqs vlan.tci[12]
-outport = inport;
-    encodes as move:NXM_NX_REG14[]->NXM_NX_REG15[]
-
-reg0[0] = vlan.present;
-    Predicate symbol vlan.present used where lvalue required.
-reg0 = reg1[0..10];
-    Can't assign 11-bit value to 32-bit destination.
-inport = reg0;
-    Can't assign integer field (reg0) to string field (inport).
-inport = big_string;
-    String fields inport and big_string are incompatible for assignment.
-ip.proto = reg0[0..7];
-    Field ip.proto is not modifiable.
-
-# Exchanging fields.
-reg0 <-> reg1;
-    encodes as push:NXM_NX_XXREG0[64..95],push:NXM_NX_XXREG0[96..127],pop:NXM_NX_XXREG0[64..95],pop:NXM_NX_XXREG0[96..127]
-vlan.pcp <-> reg0[0..2];
-    encodes as push:NXM_NX_XXREG0[96..98],push:NXM_OF_VLAN_TCI[13..15],pop:NXM_NX_XXREG0[96..98],pop:NXM_OF_VLAN_TCI[13..15]
-    has prereqs vlan.tci[12]
-reg0[10] <-> vlan.pcp[1];
-    encodes as push:NXM_OF_VLAN_TCI[14],push:NXM_NX_XXREG0[106],pop:NXM_OF_VLAN_TCI[14],pop:NXM_NX_XXREG0[106]
-    has prereqs vlan.tci[12]
-outport <-> inport;
-    encodes as push:NXM_NX_REG14[],push:NXM_NX_REG15[],pop:NXM_NX_REG14[],pop:NXM_NX_REG15[]
-
-reg0[0] <-> vlan.present;
-    Predicate symbol vlan.present used where lvalue required.
-reg0 <-> reg1[0..10];
-    Can't exchange 32-bit field with 11-bit field.
-inport <-> reg0;
-    Can't exchange string field (inport) with integer field (reg0).
-inport <-> big_string;
-    String fields inport and big_string are incompatible for exchange.
-ip.proto <-> reg0[0..7];
-    Field ip.proto is not modifiable.
-reg0[0..7] <-> ip.proto;
-    Field ip.proto is not modifiable.
-
-# TTL decrement.
-ip.ttl--;
-    encodes as dec_ttl
-    has prereqs ip
-ip.ttl
-    Syntax error at end of input expecting `--'.
-
-# load balancing.
-ct_lb;
-    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
-    has prereqs ip
-ct_lb();
-    formats as ct_lb;
-    encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat)
-    has prereqs ip
-ct_lb(192.168.1.2:80, 192.168.1.3:80);
-    encodes as group:1
-    has prereqs ip
-ct_lb(192.168.1.2, 192.168.1.3, );
-    formats as ct_lb(192.168.1.2, 192.168.1.3);
-    encodes as group:2
-    has prereqs ip
-ct_lb(fd0f::2, fd0f::3, );
-    formats as ct_lb(fd0f::2, fd0f::3);
-    encodes as group:3
-    has prereqs ip
-
-ct_lb(192.168.1.2:);
-    Syntax error at `)' expecting port number.
-ct_lb(192.168.1.2:123456);
-    Syntax error at `123456' expecting port number.
-ct_lb(foo);
-    Syntax error at `foo' expecting IP address.
-ct_lb([192.168.1.2]);
-    Syntax error at `192.168.1.2' expecting IPv6 address.
-
-# ct_next
-ct_next;
-    encodes as ct(table=19,zone=NXM_NX_REG13[0..15])
-    has prereqs ip
-
-# ct_commit
-ct_commit;
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
-    has prereqs ip
-ct_commit();
-    formats as ct_commit;
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15])
-    has prereqs ip
-ct_commit(ct_mark=1);
-    formats as ct_commit(ct_mark=0x1);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark))
-    has prereqs ip
-ct_commit(ct_mark=1/1);
-    formats as ct_commit(ct_mark=0x1/0x1);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_mark))
-    has prereqs ip
-ct_commit(ct_label=1);
-    formats as ct_commit(ct_label=0x1);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_label))
-    has prereqs ip
-ct_commit(ct_label=1/1);
-    formats as ct_commit(ct_label=0x1/0x1);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1/0x1->ct_label))
-    has prereqs ip
-ct_commit(ct_mark=1, ct_label=2);
-    formats as ct_commit(ct_mark=0x1, ct_label=0x2);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1->ct_mark,set_field:0x2->ct_label))
-    has prereqs ip
-
-ct_commit(ct_label=0x01020304050607080910111213141516);
-    formats as ct_commit(ct_label=0x1020304050607080910111213141516);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1020304050607080910111213141516->ct_label))
-    has prereqs ip
-ct_commit(ct_label=0x181716151413121110090807060504030201);
-    formats as ct_commit(ct_label=0x16151413121110090807060504030201);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x16151413121110090807060504030201->ct_label))
-    has prereqs ip
-ct_commit(ct_label=0x1000000000000000000000000000000/0x1000000000000000000000000000000);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0x1000000000000000000000000000000/0x1000000000000000000000000000000->ct_label))
-    has prereqs ip
-ct_commit(ct_label=18446744073709551615);
-    formats as ct_commit(ct_label=0xffffffffffffffff);
-    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(set_field:0xffffffffffffffff->ct_label))
-    has prereqs ip
-ct_commit(ct_label=18446744073709551616);
-    Decimal constants must be less than 2**64.
-
-# ct_dnat
-ct_dnat;
-    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
-    has prereqs ip
-ct_dnat(192.168.1.2);
-    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
-    has prereqs ip
-
-ct_dnat(192.168.1.2, 192.168.1.3);
-    Syntax error at `,' expecting `)'.
-ct_dnat(foo);
-    Syntax error at `foo' expecting IPv4 address.
-ct_dnat(foo, bar);
-    Syntax error at `foo' expecting IPv4 address.
-ct_dnat();
-    Syntax error at `)' expecting IPv4 address.
-
-# ct_snat
-ct_snat;
-    encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
-    has prereqs ip
-ct_snat(192.168.1.2);
-    encodes as ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2))
-    has prereqs ip
-
-ct_snat(192.168.1.2, 192.168.1.3);
-    Syntax error at `,' expecting `)'.
-ct_snat(foo);
-    Syntax error at `foo' expecting IPv4 address.
-ct_snat(foo, bar);
-    Syntax error at `foo' expecting IPv4 address.
-ct_snat();
-    Syntax error at `)' expecting IPv4 address.
-
-# ct_clear
-ct_clear;
-    encodes as ct_clear
-
-# clone
-clone { ip4.dst = 255.255.255.255; output; }; next;
-    encodes as clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,19)
-    has prereqs eth.type == 0x800
-
-# arp
-arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
-    encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip4
-arp { };
-    formats as arp { drop; };
-    encodes as controller(userdata=00.00.00.00.00.00.00.00)
-    has prereqs ip4
-
-# get_arp
-get_arp(outport, ip4.dst);
-    encodes as push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[]
-    has prereqs eth.type == 0x800
-get_arp(inport, reg0);
-    encodes as push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_NX_XXREG0[96..127],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG0[],pop:NXM_NX_REG15[]
-
-get_arp;
-    Syntax error at `;' expecting `('.
-get_arp();
-    Syntax error at `)' expecting field name.
-get_arp(inport);
-    Syntax error at `)' expecting `,'.
-get_arp(inport ip4.dst);
-    Syntax error at `ip4.dst' expecting `,'.
-get_arp(inport, ip4.dst;
-    Syntax error at `;' expecting `)'.
-get_arp(inport, eth.dst);
-    Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required.
-get_arp(inport, outport);
-    Cannot use string field outport where numeric field is required.
-get_arp(reg0, ip4.dst);
-    Cannot use numeric field reg0 where string field is required.
-
-# put_arp
-put_arp(inport, arp.spa, arp.sha);
-    encodes as push:NXM_NX_REG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ARP_SHA[],push:NXM_OF_ARP_SPA[],pop:NXM_NX_REG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.01.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_REG0[]
-    has prereqs eth.type == 0x806 && eth.type == 0x806
-
-# put_dhcp_opts
-reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
-reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot");
-    formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name = "ovn.org", wpad = "https://example.org", bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix = "/tftpboot");
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause)
-reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5});
-    formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server_address = {10.0.0.4, 10.0.0.5});
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05,pause)
-
-reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
-    Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
-reg1[0] = put_dhcp_opts();
-    put_dhcp_opts requires offerip to be specified.
-reg1[0] = put_dhcp_opts(x = 1.2.3.4, router = 10.0.0.1);
-    Syntax error at `x' expecting DHCPv4 option name.
-reg1[0] = put_dhcp_opts(router = 10.0.0.1);
-    put_dhcp_opts requires offerip to be specified.
-reg1[0] = put_dhcp_opts(offerip=1.2.3.4, "hi");
-    Syntax error at `"hi"'.
-reg1[0] = put_dhcp_opts(offerip=1.2.3.4, xyzzy);
-    Syntax error at `xyzzy' expecting DHCPv4 option name.
-reg1[0] = put_dhcp_opts(offerip="xyzzy");
-    DHCPv4 option offerip requires numeric value.
-reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
-    DHCPv4 option domain_name requires string value.
-
-# nd_ns
-nd_ns { nd.target = xxreg0; output; };
-    encodes as controller(userdata=00.00.00.09.00.00.00.00.ff.ff.00.18.00.00.23.20.00.06.00.80.00.00.00.00.00.01.de.10.00.01.2e.10.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
-    has prereqs ip6
-
-nd_ns { };
-    formats as nd_ns { drop; };
-    encodes as controller(userdata=00.00.00.09.00.00.00.00)
-    has prereqs ip6
-
-# nd_na
-nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; };
-    formats as nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
-    encodes as controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
-    has prereqs nd_ns
-# nd_na_router
-nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; };
-    formats as nd_na_router { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; output; };
-    encodes as controller(userdata=00.00.00.0c.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00)
-    has prereqs nd_ns
-
-# get_nd
-get_nd(outport, ip6.dst);
-    encodes as push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],pop:NXM_NX_XXREG0[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_XXREG0[]
-    has prereqs eth.type == 0x86dd
-get_nd(inport, xxreg0);
-    encodes as push:NXM_NX_REG15[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],set_field:00:00:00:00:00:00->eth_dst,resubmit(,65),pop:NXM_NX_REG15[]
-get_nd;
-    Syntax error at `;' expecting `('.
-get_nd();
-    Syntax error at `)' expecting field name.
-get_nd(inport);
-    Syntax error at `)' expecting `,'.
-get_nd(inport ip6.dst);
-    Syntax error at `ip6.dst' expecting `,'.
-get_nd(inport, ip6.dst;
-    Syntax error at `;' expecting `)'.
-get_nd(inport, eth.dst);
-    Cannot use 48-bit field eth.dst[0..47] where 128-bit field is required.
-get_nd(inport, outport);
-    Cannot use string field outport where numeric field is required.
-get_nd(xxreg0, ip6.dst);
-    Cannot use numeric field xxreg0 where string field is required.
-
-# put_nd
-put_nd(inport, nd.target, nd.sll);
-    encodes as push:NXM_NX_XXREG0[],push:NXM_OF_ETH_SRC[],push:NXM_NX_ND_SLL[],push:NXM_NX_ND_TARGET[],pop:NXM_NX_XXREG0[],pop:NXM_OF_ETH_SRC[],controller(userdata=00.00.00.04.00.00.00.00),pop:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[]
-    has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.type == 0x87 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd)
-
-# put_dhcpv6_opts
-reg1[0] = put_dhcpv6_opts(ia_addr = ae70::4, server_id = 00:00:00:00:10:02);
-    encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
-reg1[0] = put_dhcpv6_opts();
-    encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
-reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
-    formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1, ae70::2});
-    encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
-reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc, dns_server={ae70::1,ae89::2});
-    formats as reg1[0] = put_dhcpv6_opts(server_id = 12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
-    encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.02.00.06.12.34.56.78.9a.bc.00.17.00.20.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
-reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org");
-    encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.18.00.07.6f.76.6e.2e.6f.72.67,pause)
-reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
-    Syntax error at `x' expecting DHCPv6 option name.
-reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, "hi");
-    Syntax error at `"hi"'.
-reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, xyzzy);
-    Syntax error at `xyzzy' expecting DHCPv6 option name.
-reg1[0] = put_dhcpv6_opts(ia_addr="ae70::4");
-    DHCPv6 option ia_addr requires numeric value.
-reg1[0] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
-    DHCPv6 option domain_search requires string value.
-
-# set_queue
-set_queue(0);
-    encodes as set_queue:0
-set_queue(61440);
-    encodes as set_queue:61440
-set_queue(65535);
-    Queue ID 65535 for set_queue is not in valid range 0 to 61440.
-
-# dns_lookup
-reg1[0] = dns_lookup();
-    encodes as controller(userdata=00.00.00.06.00.00.00.00.00.01.de.10.00.00.00.40,pause)
-    has prereqs udp
-reg1[0] = dns_lookup("foo");
-    dns_lookup doesn't take any parameters
-
-# set_meter
-set_meter(0);
-    Rate 0 for set_meter is not in valid.
-set_meter(1);
-    encodes as meter:1
-set_meter(100, 1000);
-    encodes as meter:2
-set_meter(100, 1000, );
-    Syntax error at `,' expecting `)'.
-set_meter(4294967295, 4294967295);
-    encodes as meter:3
-
-# log
-log(verdict=allow, severity=warning);
-    encodes as controller(userdata=00.00.00.07.00.00.00.00.00.04)
-log(name="test1", verdict=drop, severity=info);
-    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31)
-log(verdict=drop, severity=info, meter="meter1");
-    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06,meter_id=4)
-log(name="test1", verdict=drop, severity=info, meter="meter1");
-    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06.74.65.73.74.31,meter_id=4)
-log(verdict=drop);
-    formats as log(verdict=drop, severity=info);
-    encodes as controller(userdata=00.00.00.07.00.00.00.00.01.06)
-log(verdict=bad_verdict, severity=info);
-    Syntax error at `bad_verdict' unknown verdict.
-log(verdict=drop, severity=bad_severity);
-    Syntax error at `bad_severity' unknown severity.
-log(severity=notice);
-    Syntax error at `;' expecting verdict.
-
-# put_nd_ra_opts
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64, slla = ae:01:02:03:04:05);
-    encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
-    has prereqs ip6
-reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla = ae:01:02:03:04:10, mtu = 1450);
-    encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause)
-    has prereqs ip6
-reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:06, prefix = aef0::/64);
-    encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
-    has prereqs ip6
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64);
-    slla option not present
-reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
-    encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
-    has prereqs ip6
-reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
-    encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.aa.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.03.04.40.80.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.be.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10,pause)
-    has prereqs ip6
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", slla = ae:01:02:03:04:10);
-    prefix option needs to be set when address mode is slaac/dhcpv6_stateless.
-reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:10);
-    prefix option needs to be set when address mode is slaac/dhcpv6_stateless.
-reg1[0] = put_nd_ra_opts(addr_mode = dhcpv6_stateless, prefix = aef0::/64, slla = ae:01:02:03:04:10);
-    Syntax error at `dhcpv6_stateless' expecting constant.
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::, slla = ae:01:02:03:04:10);
-    Invalid value for "prefix" option
-reg1[0] = put_nd_ra_opts(addr_mode = "foo", mtu = 1500, slla = ae:01:02:03:04:10);
-    Invalid value for "addr_mode" option
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla = ae:01:02:03:04:10);
-    IPv6 ND RA option mtu requires numeric value.
-reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4, slla = ae:01:02:03:04:10);
-    Invalid value for "mtu" option
-
-# icmp4
-icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
-    encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip4
-
-icmp4 { };
-    formats as icmp4 { drop; };
-    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
-    has prereqs ip4
-
-# icmp4 with icmp4.frag_mtu
-icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output; }; output;
-    encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip4
-
-# icmp4_error
-icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
-    encodes as controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip4
-
-icmp4_error { };
-    formats as icmp4_error { drop; };
-    encodes as controller(userdata=00.00.00.0e.00.00.00.00)
-    has prereqs ip4
-
-# icmp4_error with icmp4.frag_mtu
-icmp4_error { eth.dst = ff:ff:ff:ff:ff:ff; icmp4.frag_mtu = 1500; output; }; output;
-    encodes as controller(userdata=00.00.00.0e.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.28.00.00.23.20.00.25.00.00.00.00.00.00.00.03.00.0e.00.00.00.0d.00.00.00.00.05.dc.00.00.00.04.00.04.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip4
-
-icmp4.frag_mtu = 1500;
-    encodes as controller(userdata=00.00.00.0d.00.00.00.00.05.dc,pause)
-
-# icmp6
-icmp6 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
-    encodes as controller(userdata=00.00.00.0a.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs ip6
-
-icmp6 { };
-    formats as icmp6 { drop; };
-    encodes as controller(userdata=00.00.00.0a.00.00.00.00)
-    has prereqs ip6
-
-# tcp_reset
-tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
-    encodes as controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-    has prereqs tcp
-
-tcp_reset { };
-    formats as tcp_reset { drop; };
-    encodes as controller(userdata=00.00.00.0b.00.00.00.00)
-    has prereqs tcp
-
-# trigger_event
-trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
-    encodes as controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
-
-# Testing invalid vip results in extra error messages from socket-util.c
-trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "sctp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
-    Load balancer protocol 'sctp' is not 'tcp' or 'udp'
-trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "bacon");
-    Load balancer 'bacon' is not a UUID
-
-# IGMP
-igmp;
-    encodes as controller(userdata=00.00.00.10.00.00.00.00)
-
-# Contradictionary prerequisites (allowed but not useful):
-ip4.src = ip6.src[0..31];
-    encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
-    has prereqs eth.type == 0x800 && eth.type == 0x86dd
-ip4.src <-> ip6.src[0..31];
-    encodes as push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
-    has prereqs eth.type == 0x800 && eth.type == 0x86dd
-
-# check_pkt_larger
-reg0[0] = check_pkt_larger(1500);
-    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
-
-reg0 = check_pkt_larger(1500);
-    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
-
-reg0 = check_pkt_larger(foo);
-    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
-
-reg0[0] = check_pkt_larger(foo);
-    Syntax error at `foo' expecting `;'.
-
-# Miscellaneous negative tests.
-;
-    Syntax error at `;'.
-xyzzy;
-    Syntax error at `xyzzy' expecting action.
-next; 123;
-    Syntax error at `123'.
-next; xyzzy;
-    Syntax error at `xyzzy' expecting action.
-next
-    Syntax error at end of input expecting `;'.
-]])
-sed '/^[[ 	]]/d' test-cases.txt > input.txt
-cp test-cases.txt expout
-AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout])
-AT_CLEANUP
-
-AT_BANNER([OVN end-to-end tests])
-
-# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
-AT_SETUP([ovn -- 3 HVs, 1 LS, 3 lports/HV])
-AT_KEYWORDS([ovnarp])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Create hypervisors hv[123].
-# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
-# Add all of the vifs to a single logical switch lsw0.
-# Turn on port security on all the vifs except vif[123]1.
-# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
-# Add some ACLs for Ethertypes 1234, 1235, 1236.
-ovn-nbctl ls-add lsw0
-net_add n1
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2 3; do
-        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
-        ovn-nbctl lsp-add lsw0 lp$i$j
-        if test $j = 1; then
-            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
-        else
-            if test $j = 3; then
-                ip_addrs="192.168.0.$i$j fe80::ea2a:eaff:fe28:$i$j/64 192.169.0.$i$j"
-            else
-                ip_addrs="192.168.0.$i$j"
-            fi
-            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j $ip_addrs"
-            ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
-        fi
-    done
-done
-ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
-ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == "lp11"' drop
-ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp33"' drop
-ovn-nbctl create Address_Set name=set1 addresses=\"f0:00:00:00:00:11\",\"f0:00:00:00:00:21\",\"f0:00:00:00:00:31\"
-ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 && outport == "lp33"' drop
-
-get_lsp_uuid () {
-    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
-}
-
-ovn-nbctl create Port_Group name=pg1 ports=`get_lsp_uuid lp22`,`get_lsp_uuid lp33`
-ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1238 && outport == @pg1' drop
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Make sure there is no attempt to adding duplicated flows by ovn-controller
-AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
-AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
-AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv${1%?}
-}
-
-# test_packet INPORT DST SRC ETHTYPE OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        : > $i$j.expected
-    done
-done
-test_packet() {
-    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-# test_arp INPORT SHA SPA TPA [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
-    local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-    hv=`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
-
-    if test X$reply_ha = X; then
-        # Expect to receive the broadcast ARP on the other logical switch ports
-        # if no reply is expected.
-        local i j
-        for i in 1 2 3; do
-            for j in 1 2 3; do
-                if test $i$j != $inport; then
-                    echo $request >> $i$j.expected
-                fi
-            done
-        done
-    else
-        # Expect to receive the reply, if any.
-        local reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
-        echo $reply >> $inport.expected
-    fi
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send packets between all pairs of source and destination ports:
-#
-# 1. Unicast packets are delivered to exactly one logical switch port
-#    (except that packets destined to their input ports are dropped).
-#
-# 2. Broadcast and multicast are delivered to all logical switch ports
-#    except the input port.
-#
-# 3. When port security is turned on, the switch drops packets from the wrong
-#    MAC address.
-#
-# 4. The switch drops all packets with a VLAN tag.
-#
-# 5. The switch drops all packets with a multicast source address.  (This only
-#    affects behavior when port security is turned off, since otherwise port
-#    security would drop the packet anyway.)
-#
-# 6. The switch delivers packets with an unknown destination to logical
-#    switch ports with "unknown" among their MAC addresses (and port
-#    security disabled).
-#
-# 7. The switch drops unicast packets that violate an ACL.
-#
-# 8. The switch drops multicast and broadcast packets that violate an ACL.
-#
-# 9. OVN generates responses to ARP requests for known IPs, except for
-#    requests from a port for the port's own IP.
-#
-# 10. No response to ARP requests for unknown IPs.
-
-for is in 1 2 3; do
-    for js in 1 2 3; do
-        s=$is$js
-        bcast=
-        unknown=
-        bacl2=
-        bacl3=
-        for id in 1 2 3; do
-            for jd in 1 2 3; do
-                d=$id$jd
-
-                if test $d != $s; then unicast=$d; else unicast=; fi
-                test_packet $s f000000000$d f000000000$s $s$d $unicast     #1
-
-                if test $d != $s && test $js = 1; then
-                    impersonate=$d
-                else
-                    impersonate=
-                fi
-                test_packet $s f000000000$d f00000000055 55$d $impersonate #3
-
-                if test $d != $s && test $s != 11; then acl2=$d; else acl2=; fi
-                if test $d != $s && test $d != 33; then acl3=$d; else acl3=; fi
-                if test $d = $s || (test $js = 1 && test $d = 33); then
-                    # Source of 11, 21, or 31 and dest of 33 should be dropped
-                    # due to the 4th ACL that uses address_set(set1).
-                    acl4=
-                else
-                    acl4=$d
-                fi
-                if test $d = $s || test $d = 22 || test $d = 33; then
-                    # dest of 22 and 33 should be dropped
-                    # due to the 5th ACL that uses port_group(pg1).
-                    acl5=
-                else
-                    acl5=$d
-                fi
-                test_packet $s f000000000$d f000000000$s 1234        #7, acl1
-                test_packet $s f000000000$d f000000000$s 1235 $acl2  #7, acl2
-                test_packet $s f000000000$d f000000000$s 1236 $acl3  #7, acl3
-                test_packet $s f000000000$d f000000000$s 1237 $acl4  #7, acl4
-                test_packet $s f000000000$d f000000000$s 1238 $acl5  #7, acl5
-
-                test_packet $s f000000000$d f00000000055 810000091234      #4
-                test_packet $s f000000000$d 0100000000$s $s$d              #5
-
-                if test $d != $s && test $jd = 1; then
-                    unknown="$unknown $d"
-                fi
-                bcast="$bcast $unicast"
-                bacl2="$bacl2 $acl2"
-                bacl3="$bacl3 $acl3"
-
-                sip=`ip_to_hex 192 168 0 $is$js`
-                tip=`ip_to_hex 192 168 0 $id$jd`
-                tip_unknown=`ip_to_hex 11 11 11 11`
-                if test $d != $s; then
-                    reply_ha=f000000000$d
-                else
-                    reply_ha=
-                fi
-                test_arp $s f000000000$s $sip $tip $reply_ha               #9
-                test_arp $s f000000000$s $sip $tip_unknown                 #10
-
-                if test $jd = 3; then
-                    # lsp[123]3 has an additional ip 192.169.0.[123]3.
-                    tip=`ip_to_hex 192 169 0 $id$jd`
-                    test_arp $s f000000000$s $sip $tip $reply_ha           #9
-                fi
-            done
-        done
-
-        # Broadcast and multicast.
-        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast             #2
-        test_packet $s 010000000000 f000000000$s ${s}ff $bcast             #2
-        if test $js = 1; then
-            bcast_impersonate=$bcast
-        else
-            bcast_impersonate=
-        fi
-        test_packet $s 010000000000 f00000000044 44ff $bcast_impersonate   #3
-
-        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown           #6
-
-        test_packet $s ffffffffffff f000000000$s 1234                #8, acl1
-        test_packet $s ffffffffffff f000000000$s 1235 $bacl2         #8, acl2
-        test_packet $s ffffffffffff f000000000$s 1236 $bacl3         #8, acl3
-        test_packet $s 010000000000 f000000000$s 1234                #8, acl1
-        test_packet $s 010000000000 f000000000$s 1235 $bacl2         #8, acl2
-        test_packet $s 010000000000 f000000000$s 1236 $bacl3         #8, acl3
-    done
-done
-
-# set address for lp13 with invalid characters.
-# lp13 should be configured with only 192.168.0.13.
-ovn-nbctl lsp-set-addresses lp13 "f0:00:00:00:00:13 192.168.0.13 invalid 192.169.0.13"
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-sip=`ip_to_hex 192 168 0 11`
-tip=`ip_to_hex 192 168 0 13`
-test_arp 11 f00000000011  $sip $tip f00000000013
-
-tip=`ip_to_hex 192 169 0 13`
-#arp request for 192.169.0.13 should be flooded
-test_arp 11 f00000000011  $sip $tip
-
-# dump information and flows with counters
-ovn-sbctl dump-flows -- list multicast_group
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv3 dump ------"
-as hv3 ovs-vsctl show
-as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
-    done
-done
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-# 2 hypervisors, one logical switch, 2 logical ports per hypervisor
-# logical ports bound to chassis encap-ip.
-AT_SETUP([ovn -- 2 HVs, 1 LS, 2 lports/HV])
-AT_KEYWORDS([ovnarp])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Create hypervisors hv[12].
-# Add vif1[12] to hv1, vif2[12] to hv2
-ovn-nbctl ls-add lsw0
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2; do
-        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
-        ovn-nbctl lsp-add lsw0 lp$i$j
-        ip_addrs="192.168.0.$i$j"
-        ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j $ip_addrs"
-        ovn-nbctl --wait=hv lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
-    done
-done
-
-get_lsp_uuid () {
-    ovn-nbctl lsp-list lsw0 | grep $1 | awk '{ print $1 }'
-}
-
-# XXX-Check how to pass lp$i1 in AT_CHECK_UNQUOTED, for now just do it
-# explictly
-
-# For Chassis hv1
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp11], [0], [dnl
-encap               : [[]]
-])
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp12], [0], [dnl
-encap               : [[]]
-])
-
-# For Chassis hv2
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp21], [0], [dnl
-encap               : [[]]
-])
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp22], [0], [dnl
-encap               : [[]]
-])
-
-# Bind the ports to the encap-ip
-for i in 1 2; do
-    for j in 1 2; do
-        as hv$i
-        ovs-vsctl set Interface vif$i$j external-ids:encap-ip=192.168.0.$i
-    done
-done
-
-sleep 1
-
-# dump port bindings; since we have vxlan and geneve tunnels, we expect the
-# ports to be bound to geneve tunnels.
-
-# For Chassis 1
-encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap chassis_name=hv1 type=geneve ip=192.168.0.1`
-
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp11], [0], [dnl
-encap               : ${encap_rec}
-])
-
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp12], [0], [dnl
-encap               : ${encap_rec}
-])
-
-# For Chassis 2
-encap_rec=`ovn-sbctl --data=bare --no-heading --column _uuid find encap chassis_name=hv2 type=geneve ip=192.168.0.2`
-
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp21], [0], [dnl
-encap               : ${encap_rec}
-])
-
-AT_CHECK_UNQUOTED([ovn-sbctl  --column encap list port_binding lp22], [0], [dnl
-encap               : ${encap_rec}
-])
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Make sure there is no attempt to adding duplicated flows by ovn-controller
-AT_FAIL_IF([test -n "`grep duplicate hv1/ovn-controller.log`"])
-AT_FAIL_IF([test -n "`grep duplicate hv2/ovn-controller.log`"])
-AT_FAIL_IF([test -n "`grep duplicate hv3/ovn-controller.log`"])
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv${1%?}
-}
-
-# test_packet INPORT DST SRC ETHTYPE OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
-for i in 1 2; do
-    for j in 1 2; do
-        : > $i$j.expected
-    done
-done
-test_packet() {
-    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send packets between all pairs of source and destination ports:
-#
-# 1. Unicast packets are delivered to exactly one logical switch port
-#    (except that packets destined to their input ports are dropped).
-
-for is in 1 2; do
-    for js in 1 2; do
-        s=$is$js
-        bcast=
-        unknown=
-        bacl2=
-        bacl3=
-        for id in 1 2 3; do
-            for jd in 1 2 3; do
-                d=$id$jd
-
-                if test $d != $s; then unicast=$d; else unicast=; fi
-                test_packet $s f000000000$d f000000000$s $s$d $unicast     #1
-            done
-        done
-
-    done
-done
-
-# dump information and flows with counters
-ovn-sbctl dump-flows -- list multicast_group
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv3 dump ------"
-as hv3 ovs-vsctl show
-as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2; do
-    for j in 1 2; do
-        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
-    done
-done
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- trace 1 LS, 3 LSPs])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Create a logical switch and some logical ports.
-# Turn on port security on all lports except ls1.
-# Make ls1 a destination for unknown MACs.
-# Add some ACLs for Ethertypes 1234, 1235, 1236.
-ovn-nbctl ls-add lsw0
-ovn-sbctl chassis-add hv0 geneve 127.0.0.1
-for i in 1 2 3; do
-    ovn-nbctl lsp-add lsw0 lp$i
-done
-ovn-nbctl --wait=sb sync
-for i in 1 2 3; do
-    ovn-sbctl lsp-bind lp$i hv0
-    if test $i = 1; then
-        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.0.$i" unknown
-    else
-        if test $i = 3; then
-           ip_addrs="192.168.0.$i fe80::ea2a:eaff:fe28:$i/64 192.169.0.$i"
-        else
-           ip_addrs="192.168.0.$i"
-        fi
-        ovn-nbctl lsp-set-addresses lp$i "f0:00:00:00:00:0$i $ip_addrs"
-        ovn-nbctl lsp-set-port-security lp$i f0:00:00:00:00:0$i
-    fi
-done
-ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
-ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == "lp1"' drop
-ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp3"' drop
-ovn-nbctl create Address_Set name=set1 addresses=\"f0:00:00:00:00:01\",\"f0:00:00:00:00:02\"
-ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1237 && eth.src == $set1 && outport == "lp3"' drop
-
-ovn-nbctl --wait=sb sync
-on_exit 'kill `cat ovn-trace.pid`'
-ovn-trace --detach --pidfile --no-chdir
-
-# test_packet INPORT DST SRC [-vlan] [-eth TYPE] OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 11 for vif11.
-test_packet() {
-    local inport=$1 eth_dst=$2 eth_src=$3; shift; shift; shift
-    uflow="inport==\"lp$inport\" && eth.dst==$eth_dst && eth.src==$eth_src"
-    while :; do
-        case $1 in # (
-            -vlan) uflow="$uflow && vlan.vid == 1234"; shift ;; # (
-            -eth) uflow="$uflow && eth.type == 0x$2"; shift; shift ;; # (
-            *) break ;;
-        esac
-    done
-    for outport; do
-        echo "output(\"lp$outport\");"
-    done > expout
-
-    AT_CAPTURE_FILE([trace])
-    AT_CHECK([ovs-appctl -t ovn-trace trace --all lsw0 "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
-}
-
-# test_arp INPORT SHA SPA TPA [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
-
-    local request="inport == \"lp$inport\"
-                   && eth.dst == ff:ff:ff:ff:ff:ff && eth.src == $sha
-                   && arp.op == 1 && arp.sha == $sha && arp.spa == $spa
-                   && arp.tha == ff:ff:ff:ff:ff:ff && arp.tpa == $tpa"
-
-    if test -z "$reply_ha"; then
-        reply=
-        local i
-        for i in 1 2 3; do
-            if test $i != $inport; then
-                reply="${reply}output(\"lp$i\");
-"
-            fi
-        done
-    else
-        reply="\
-eth.dst = $sha;
-eth.src = $reply_ha;
-arp.op = 2;
-arp.tha = $sha;
-arp.sha = $reply_ha;
-arp.tpa = $spa;
-arp.spa = $tpa;
-output(\"lp$inport\");
-"
-    fi
-
-    AT_CAPTURE_FILE([trace])
-    AT_CHECK_UNQUOTED([ovs-appctl -t ovn-trace trace --all lsw0 "$request" | tee trace | sed '1,/Minimal trace/d'], [0], [$reply])
-}
-
-# Send packets between all pairs of source and destination ports:
-#
-# 1. Unicast packets are delivered to exactly one logical switch port
-#    (except that packets destined to their input ports are dropped).
-#
-# 2. Broadcast and multicast are delivered to all logical switch ports
-#    except the input port.
-#
-# 3. When port security is turned on, the switch drops packets from the wrong
-#    MAC address.
-#
-# 4. The switch drops all packets with a VLAN tag.
-#
-# 5. The switch drops all packets with a multicast source address.  (This only
-#    affects behavior when port security is turned off, since otherwise port
-#    security would drop the packet anyway.)
-#
-# 6. The switch delivers packets with an unknown destination to logical
-#    switch ports with "unknown" among their MAC addresses (and port
-#    security disabled).
-#
-# 7. The switch drops unicast packets that violate an ACL.
-#
-# 8. The switch drops multicast and broadcast packets that violate an ACL.
-#
-# 9. OVN generates responses to ARP requests for known IPs, except for
-#    requests from a port for the port's own IP.
-#
-# 10. No response to ARP requests for unknown IPs.
-
-for s in 1 2 3; do
-    bcast=
-    unknown=
-    bacl2=
-    bacl3=
-    for d in 1 2 3; do
-        echo
-        echo "lp$s -> lp$d"
-        if test $d != $s; then unicast=$d; else unicast=; fi
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s $unicast      #1
-
-        if test $d != $s && test $s = 1; then
-            impersonate=$d
-        else
-            impersonate=
-        fi
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 $impersonate   #3
-
-        if test $d != $s && test $s != 1; then acl2=$d; else acl2=; fi
-        if test $d != $s && test $d != 3; then acl3=$d; else acl3=; fi
-        if test $d = $s || ( (test $s = 1 || test $s = 2) && test $d = 3); then
-            # Source of 1 or 2 and dest of 3 should be dropped
-            # due to the 4th ACL that uses address_set(set1).
-            acl4=
-        else
-            acl4=$d
-        fi
-
-        #7, acl1 to acl4:
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1234
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1235 $acl2
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1236 $acl3
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:0$s -eth 1237 $acl4
-
-        test_packet $s f0:00:00:00:00:0$d f0:00:00:00:00:55 -vlan          #4
-        test_packet $s f0:00:00:00:00:0$d 01:00:00:00:00:0$s               #5
-
-        if test $d != $s && test $d = 1; then
-            unknown="$unknown $d"
-        fi
-        bcast="$bcast $unicast"
-        bacl2="$bacl2 $acl2"
-        bacl3="$bacl3 $acl3"
-
-        sip=192.168.0.$s
-        tip=192.168.0.$d
-        tip_unknown=11.11.11.11
-        if test $d != $s; then reply_ha=f0:00:00:00:00:0$d; else reply_ha=; fi
-        test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha                 #9
-        test_arp $s f0:00:00:00:00:0$s $sip $tip_unknown                   #10
-
-        if test $d = 3; then
-            # lp3 has an additional ip 192.169.0.[123]3.
-            tip=192.169.0.$d
-            test_arp $s f0:00:00:00:00:0$s $sip $tip $reply_ha             #9
-        fi
-    done
-
-    # Broadcast and multicast.
-    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s $bcast             #2
-    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s $bcast             #2
-    if test $s = 1; then
-       bcast_impersonate=$bcast
-    else
-       bcast_impersonate=
-    fi
-    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:44 $bcast_impersonate  #3
-
-    test_packet $s f0:00:00:00:ff:ff f0:00:00:00:00:0$s $unknown           #6
-
-    #8, acl1 to acl3:
-    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1234
-    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1235 $bacl2
-    test_packet $s ff:ff:ff:ff:ff:ff f0:00:00:00:00:0$s -eth 1236 $bacl3
-
-    #8, acl1 to acl3:
-    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1234
-    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1235 $bacl2
-    test_packet $s 01:00:00:00:00:00 f0:00:00:00:00:0$s -eth 1236 $bacl3
-done
-
-AT_CLEANUP
-
-# 2 hypervisors, 4 logical ports per HV
-# 2 locally attached networks (one flat, one vlan tagged over same device)
-# 2 ports per HV on each network
-AT_SETUP([ovn -- 2 HVs, 4 lports/HV, localnet ports])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# In this test cases we create 3 switches, all connected to same
-# physical network (through br-phys on each HV). Each switch has
-# VIF ports across 2 HVs. Each HV has 5 VIF ports. The first digit
-# of VIF port name indicates the hypervisor it is bound to, e.g.
-# lp23 means VIF 3 on hv2.
-#
-# Each switch's VLAN tag and their logical switch ports are:
-#   - ls1:
-#       - untagged
-#       - ports: lp11, lp12, lp21, lp22
-#
-#   - ls2:
-#       - tagged with VLAN 101
-#       - ports: lp13, lp14, lp23, lp24
-#   - ls3:
-#       - untagged
-#       - ports: lp15, lp25
-#
-# Note: a localnet port is created for each switch to connect to
-# physical network.
-
-for i in 1 2 3; do
-    ls_name=ls$i
-    ovn-nbctl ls-add $ls_name
-    ln_port_name=ln$i
-    if test $i -eq 2; then
-        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
-    else
-        ovn-nbctl lsp-add $ls_name $ln_port_name
-    fi
-    ovn-nbctl lsp-set-addresses $ln_port_name unknown
-    ovn-nbctl lsp-set-type $ln_port_name localnet
-    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
-done
-
-# lsp_to_ls LSP
-#
-# Prints the name of the logical switch that contains LSP.
-lsp_to_ls () {
-    case $1 in dnl (
-        lp?[[12]]) echo ls1 ;; dnl (
-        lp?[[34]]) echo ls2 ;; dnl (
-        lp?5) echo ls3 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2 3 4 5; do
-        ovs-vsctl add-port br-int vif$i$j -- \
-            set Interface vif$i$j external-ids:iface-id=lp$i$j \
-                                  options:tx_pcap=hv$i/vif$i$j-tx.pcap \
-                                  options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
-                                  ofport-request=$i$j
-
-        lsp_name=lp$i$j
-        ls_name=$(lsp_to_ls $lsp_name)
-
-        ovn-nbctl lsp-add $ls_name $lsp_name
-        ovn-nbctl lsp-set-addresses $lsp_name f0:00:00:00:00:$i$j
-        ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$j
-
-        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
-    done
-done
-ovn-nbctl --wait=sb sync
-ovn-sbctl dump-flows
-
-OVN_POPULATE_ARP
-
-# XXX This is now the 3rd copy of these functions in this file ...
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv${1%?}
-}
-#
-# test_packet INPORT DST SRC ETHTYPE EOUT LOUT
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is specified as
-# logical switch port numbers, e.g. 11 for vif11.
-#
-# EOUT is the end-to-end output port, that is, where the packet will end up
-# after possibly bouncing through one or more localnet ports.  LOUT is the
-# logical output port, which might be a localnet port, as seen by ovn-trace
-# (which doesn't know what localnet ports are connected to and therefore can't
-# figure out the end-to-end answer).
-for i in 1 2; do
-    for j in 1 2 3 4 5; do
-        : > $i$j.expected
-    done
-done
-test_packet() {
-    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6
-    echo "$@"
-
-    # First try tracing the packet.
-    uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src && eth.type==0x$eth"
-    if test $lout != drop; then
-        echo "output(\"$lout\");"
-    fi > expout
-    AT_CAPTURE_FILE([trace])
-    AT_CHECK([ovn-trace --all $(lsp_to_ls lp$inport) "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
-
-    # Then actually send a packet, for an end-to-end test.
-    local packet=$(echo $dst$src | sed 's/://g')${eth}
-    hv=`vif_to_hv $inport`
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    if test $eout != drop; then
-        echo $packet >> ${eout#lp}.expected
-    fi
-}
-
-# lp11 and lp21 are on the same network (phys, untagged)
-# and on different hypervisors
-test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
-test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
-
-# lp11 and lp12 are on the same network (phys, untagged)
-# and on the same hypervisor
-test_packet 11 f0:00:00:00:00:12 f0:00:00:00:00:11 1112 lp12 lp12
-test_packet 12 f0:00:00:00:00:11 f0:00:00:00:00:12 1211 lp11 lp11
-
-# lp13 and lp23 are on the same network (phys, VLAN 101)
-# and on different hypervisors
-test_packet 13 f0:00:00:00:00:23 f0:00:00:00:00:13 1323 lp23 lp23
-test_packet 23 f0:00:00:00:00:13 f0:00:00:00:00:23 2313 lp13 lp13
-
-# lp13 and lp14 are on the same network (phys, VLAN 101)
-# and on the same hypervisor
-test_packet 13 f0:00:00:00:00:14 f0:00:00:00:00:13 1314 lp14 lp14
-test_packet 14 f0:00:00:00:00:13 f0:00:00:00:00:14 1413 lp13 lp13
-
-# lp11 and lp15 are on the same network (phys, untagged),
-# same hypervisor, and on different switches
-test_packet 11 f0:00:00:00:00:15 f0:00:00:00:00:11 1115 lp15 ln1
-test_packet 15 f0:00:00:00:00:11 f0:00:00:00:00:15 1511 lp11 ln3
-
-# lp11 and lp25 are on the same network (phys, untagged),
-# different hypervisors, and on different switches
-test_packet 11 f0:00:00:00:00:25 f0:00:00:00:00:11 1125 lp25 ln1
-test_packet 25 f0:00:00:00:00:11 f0:00:00:00:00:25 2511 lp11 ln3
-
-# Ports that should not be able to communicate
-test_packet 11 f0:00:00:00:00:13 f0:00:00:00:00:11 1113 drop ln1
-test_packet 11 f0:00:00:00:00:23 f0:00:00:00:00:11 1123 drop ln1
-test_packet 21 f0:00:00:00:00:13 f0:00:00:00:00:21 2113 drop ln1
-test_packet 21 f0:00:00:00:00:23 f0:00:00:00:00:21 2123 drop ln1
-test_packet 13 f0:00:00:00:00:11 f0:00:00:00:00:13 1311 drop ln2
-test_packet 13 f0:00:00:00:00:21 f0:00:00:00:00:13 1321 drop ln2
-test_packet 23 f0:00:00:00:00:11 f0:00:00:00:00:23 2311 drop ln2
-test_packet 23 f0:00:00:00:00:21 f0:00:00:00:00:23 2321 drop ln2
-
-# Dump a bunch of info helpful for debugging if there's a failure.
-
-echo "------ OVN dump ------"
-ovn-nbctl show
-ovn-sbctl show
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2; do
-    for j in 1 2 3 4 5; do
-        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
-    done
-done
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- vtep: 3 HVs, 1 VIFs/HV, 1 GW, 1 LS])
-AT_KEYWORDS([vtep])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Configure the Northbound database
-ovn-nbctl ls-add lsw0
-
-ovn-nbctl lsp-add lsw0 lp1
-ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
-
-ovn-nbctl lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
-
-ovn-nbctl lsp-add lsw0 lp-vtep
-ovn-nbctl lsp-set-type lp-vtep vtep
-ovn-nbctl lsp-set-options lp-vtep vtep-physical-switch=br-vtep vtep-logical-switch=lsw0
-ovn-nbctl lsp-set-addresses lp-vtep unknown
-
-# lpr, lr and lrp1 are used for the ARP request handling test only.
-ovn-nbctl lsp-add lsw0 lpr
-ovn-nbctl lr-add lr
-ovn-nbctl lrp-add lr lrp1 f0:00:00:00:00:f1 192.168.1.1/24
-ovn-nbctl set Logical_Switch_Port lpr type=router \
-                             options:router-port=lrp1 \
-    addresses='"f0:00:00:00:00:f1 192.168.1.1"'
-
-
-net_add n1               # Network to connect hv1, hv2, and vtep
-net_add n2               # Network to connect vtep and hv3
-
-# Create hypervisor hv1 connected to n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
-
-# Create hypervisor hv2 connected to n1
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
-
-
-# Start the vtep emulator with a leg in both networks
-sim_add vtep
-as vtep
-
-ovsdb-tool create "$ovs_base"/vtep/vtep.db "$abs_top_srcdir"/vtep/vtep.ovsschema || return 1
-ovs-appctl -t ovsdb-server ovsdb-server/add-db "$ovs_base"/vtep/vtep.db
-
-ovs-vsctl add-br br-phys
-net_attach n1 br-phys
-
-mac=`ovs-vsctl get Interface br-phys mac_in_use | sed s/\"//g`
-arp_table="$arp_table $sandbox,br-phys,192.168.0.3,$mac"
-ovs-appctl netdev-dummy/ip4addr br-phys 192.168.0.3/24 >/dev/null || return 1
-ovs-appctl ovs/route/add 192.168.0.3/24 br-phys >/dev/null || return 1
-
-ovs-vsctl add-br br-vtep
-net_attach n2 br-vtep
-
-vtep-ctl add-ps br-vtep
-vtep-ctl set Physical_Switch br-vtep tunnel_ips=192.168.0.3
-vtep-ctl add-ls lsw0
-
-start_daemon ovs-vtep br-vtep
-start_daemon ovn-controller-vtep --vtep-db=unix:"$ovs_base"/vtep/db.sock --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-
-OVS_WAIT_UNTIL([vtep-ctl bind-ls br-vtep br-vtep_n2 0 lsw0])
-
-OVS_WAIT_UNTIL([test -n "`as vtep vtep-ctl get-replication-mode lsw0 |
-               grep -- source`"])
-# It takes more time for the update to be processed by ovs-vtep.
-sleep 1
-
-# Add hv3 on the other side of the vtep
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-net_attach n2 br-phys
-
-ovs-vsctl add-port br-phys vif3 -- set Interface vif3 options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap ofport-request=1
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# test_packet INPORT DST SRC ETHTYPE OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 1 for vif1.
-for i in 1 2 3; do
-    : > $i.expected
-done
-test_packet() {
-    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
-    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
-    hv=hv$inport
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-# Send packets between all pairs of source and destination ports:
-#
-# 1. Unicast packets are delivered to exactly one logical switch port
-#    (except that packets destined to their input ports are dropped).
-#
-# 2. Broadcast and multicast are delivered to all logical switch ports
-#    except the input port.
-#
-# 3. The switch delivers packets with an unknown destination to logical
-#    switch ports with "unknown" among their MAC addresses (and port
-#    security disabled).
-for s in 1 2 3; do
-    bcast=
-    unknown=
-    for d in 1 2 3; do
-        if test $d != $s; then unicast=$d; else unicast=; fi
-        test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast       #1
-
-        # The vtep (vif3) is the only one configured for "unknown"
-        if test $d != $s && test $d = 3; then
-            unknown="$unknown $d"
-        fi
-        bcast="$bcast $unicast"
-    done
-
-    # Broadcast and multicast.
-    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast             #2
-    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast             #2
-
-    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown           #3
-done
-
-# ARP request should not be responded to by logical switch router
-# type arp responder on HV1 and HV2 and should reach directly to
-# vif1 and vif2
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-sha=f00000000003
-spa=`ip_to_hex 192 168 1 2`
-tpa=`ip_to_hex 192 168 1 1`
-request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-as hv3 ovs-appctl netdev-dummy/receive vif3 $request
-echo $request >> 1.expected
-echo $request >> 2.expected
-
-# dump information with counters
-echo "------ OVN dump ------"
-ovn-nbctl show
-ovn-sbctl show
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 show br-int
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-ofctl -O OpenFlow13 show br-int
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv3 dump ------"
-as hv3 ovs-vsctl show
-# note: hv3 has no logical port bind, thus it should not have br-int
-AT_CHECK([as hv3 ovs-ofctl -O OpenFlow13 show br-int], [1], [],
-[ovs-ofctl: br-int is not a bridge or a socket
-])
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
-done
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1],[hv2],[vtep])
-OVN_CLEANUP_VSWITCH([hv3])
-
-AT_CLEANUP
-
-# Similar test to "hardware GW"
-AT_SETUP([ovn -- 3 HVs, 1 VIFs/HV, 1 software GW, 1 LS])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Configure the Northbound database
-ovn-nbctl ls-add lsw0
-
-ovn-nbctl lsp-add lsw0 lp1
-ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
-
-ovn-nbctl lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
-
-ovn-nbctl lsp-add lsw0 lp-gw
-ovn-nbctl lsp-set-type lp-gw l2gateway
-ovn-nbctl lsp-set-options lp-gw network_name=physnet1 l2gateway-chassis=hv_gw
-ovn-nbctl lsp-set-addresses lp-gw unknown
-
-net_add n1               # Network to connect hv1, hv2, and gw
-net_add n2               # Network to connect gw and hv3
-
-# Create hypervisor hv1 connected to n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
-
-# Create hypervisor hv2 connected to n1
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv2/vif2-tx.pcap options:rxq_pcap=hv2/vif2-rx.pcap ofport-request=1
-
-# Create hypervisor hv_gw connected to n1 and n2
-# connect br-phys bridge to n1; connect hv-gw bridge to n2
-sim_add hv_gw
-as hv_gw
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl add-br br-phys2
-net_attach n2 br-phys2
-ovs-vsctl set open . external_ids:ovn-bridge-mappings="physnet1:br-phys2"
-
-# Add hv3 on the other side of the GW
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-net_attach n2 br-phys
-ovs-vsctl add-port br-phys vif3 -- set Interface vif3 options:tx_pcap=hv3/vif3-tx.pcap options:rxq_pcap=hv3/vif3-rx.pcap ofport-request=1
-
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# test_packet INPORT DST SRC ETHTYPE OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as lport numbers, e.g. 1 for vif1.
-for i in 1 2 3; do
-    : > $i.expected
-done
-test_packet() {
-    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
-    #hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
-    hv=hv$inport
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-# Send packets between all pairs of source and destination ports:
-#
-# 1. Unicast packets are delivered to exactly one lport (except that packets
-#    destined to their input ports are dropped).
-#
-# 2. Broadcast and multicast are delivered to all lports except the input port.
-#
-# 3. The lswitch delivers packets with an unknown destination to lports with
-#    "unknown" among their MAC addresses (and port security disabled).
-for s in 1 2 3 ; do
-    bcast=
-    unknown=
-    for d in 1 2 3 ; do
-        if test $d != $s; then unicast=$d; else unicast=; fi
-        test_packet $s f0000000000$d f0000000000$s 00$s$d $unicast       #1
-
-        # The vtep (vif3) is the only one configured for "unknown"
-        if test $d != $s && test $d = 3; then
-            unknown="$unknown $d"
-        fi
-        bcast="$bcast $unicast"
-    done
-
-    test_packet $s ffffffffffff f0000000000$s 0${s}ff $bcast             #2
-    test_packet $s 010000000000 f0000000000$s 0${s}ff $bcast             #3
-    test_packet $s f0000000ffff f0000000000$s 0${s}66 $unknown           #4
-done
-
-echo "------ ovn-nbctl show ------"
-ovn-nbctl show
-echo "------ ovn-sbctl show ------"
-ovn-sbctl show
-
-echo "------ hv1 ------"
-as hv1 ovs-vsctl show
-echo "------ hv1 br-int ------"
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-echo "------ hv1 br-phys ------"
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-phys
-
-echo "------ hv2 ------"
-as hv2 ovs-vsctl show
-echo "------ hv2 br-int ------"
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-echo "------ hv2 br-phys ------"
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-phys
-
-echo "------ hv_gw ------"
-as hv_gw ovs-vsctl show
-echo "------ hv_gw br-phys ------"
-as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys
-echo "------ hv_gw br-phys2 ------"
-as hv_gw ovs-ofctl -O OpenFlow13 dump-flows br-phys2
-
-echo "------ hv3 ------"
-as hv3 ovs-vsctl show
-echo "------ hv3 br-phys ------"
-as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-phys
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    OVN_CHECK_PACKETS([hv$i/vif$i-tx.pcap], [$i.expected])
-done
-AT_CLEANUP
-
-# 3 hypervisors, 3 logical switches with 3 logical ports each, 1 logical router
-AT_SETUP([ovn -- 3 HVs, 3 LS, 3 lports/LS, 1 LR])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-#
-# Three logical switches ls1, ls2, ls3.
-# One logical router lr0 connected to ls[123],
-# with nine subnets, three per logical switch:
-#
-#    lrp11 on ls1 for subnet 192.168.11.0/24
-#    lrp12 on ls1 for subnet 192.168.12.0/24
-#    lrp13 on ls1 for subnet 192.168.13.0/24
-#    ...
-#    lrp33 on ls3 for subnet 192.168.33.0/24
-#
-# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
-# digits are the subnet and the last digit distinguishes the VIF.
-for i in 1 2 3; do
-    ovn-nbctl ls-add ls$i
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            # Add "unknown" to MAC addresses for lp?11, so packets for
-            # MAC-IP bindings discovered via ARP later have somewhere to go.
-            if test $j$k = 11; then unknown=unknown; else unknown=; fi
-
-            ovn-nbctl \
-                -- lsp-add ls$i lp$i$j$k \
-                -- lsp-set-addresses lp$i$j$k \
-                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k" $unknown
-        done
-    done
-done
-
-ovn-nbctl lr-add lr0
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
-        ovn-nbctl \
-            -- lsp-add ls$i lrp$i$j-attachment \
-            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
-                             options:router-port=lrp$i$j \
-                             addresses='"00:00:00:00:ff:'$i$j'"'
-    done
-done
-
-ovn-nbctl set Logical_Switch_Port lrp33-attachment \
-    addresses='"00:00:00:00:ff:33 192.168.33.254"'
-
-# Physical network:
-#
-# Three hypervisors hv[123].
-# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
-# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
-# lp?3[123] all on hv3.
-
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    case $1 in dnl (
-        ?11) echo 1 ;; dnl (
-        ?12 | ?21 | ?22) echo 2 ;; dnl (
-        ?13 | ?23 | ?3?) echo 3 ;;
-    esac
-}
-
-# Given the name of a logical port, prints the name of its logical router
-# port, e.g. "vif_to_lrp 123" yields 12.
-vif_to_lrp() {
-    echo ${1%?}
-}
-
-# Given the name of a logical port, prints the name of its logical
-# switch, e.g. "vif_to_ls 123" yields 1.
-vif_to_ls() {
-    echo ${1%??}
-}
-
-net_add n1
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-done
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            hv=`vif_to_hv $i$j$k`
-                as hv$hv ovs-vsctl \
-                -- add-port br-int vif$i$j$k \
-                -- set Interface vif$i$j$k \
-                    external-ids:iface-id=lp$i$j$k \
-                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
-                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
-                    ofport-request=$i$j$k
-        done
-    done
-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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 123 for vif123.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            : > $i$j$k.expected
-        done
-    done
-done
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    in_ls=`vif_to_ls $inport`
-    in_lrp=`vif_to_lrp $inport`
-    for outport; do
-        out_ls=`vif_to_ls $outport`
-        if test $in_ls = $out_ls; then
-            # Ports on the same logical switch receive exactly the same packet.
-            echo $packet
-        else
-            # Routing decrements TTL and updates source and dest MAC
-            # (and checksum).
-            out_lrp=`vif_to_lrp $outport`
-            echo f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
-        fi >> $outport.expected
-    done
-}
-
-# test_arp INPORT SHA SPA TPA [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
-    local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
-    as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
-
-    # Expect to receive the broadcast ARP on the other logical switch ports if
-    # IP address is not configured to the switch patch port.
-    local i=`vif_to_ls $inport`
-    local j k
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            # 192.168.33.254 is configured to the switch patch port for lrp33,
-            # so no ARP flooding expected for it.
-            if test $i$j$k != $inport && test $tpa != `ip_to_hex 192 168 33 254`; then
-                echo $request >> $i$j$k.expected
-            fi
-        done
-    done
-
-    # Expect to receive the reply, if any.
-    if test X$reply_ha != X; then
-        lrp=`vif_to_lrp $inport`
-        local reply=${sha}00000000ff${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
-        echo $reply >> $inport.expected
-    fi
-}
-
-as hv1 ovs-vsctl --columns=name,ofport list interface
-as hv1 ovn-sbctl list port_binding
-as hv1 ovn-sbctl list datapath_binding
-as hv1 ovn-sbctl dump-flows
-as hv1 ovs-ofctl dump-flows br-int
-
-# Send IP packets between all pairs of source and destination ports:
-#
-# 1. Unicast IP packets are delivered to exactly one logical switch port
-#    (except that packets destined to their input ports are dropped).
-#
-# 2. Broadcast IP packets are delivered to all logical switch ports
-#    except the input port.
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-for is in 1 2 3; do
-  for js in 1 2 3; do
-    for ks in 1 2 3; do
-      bcast=
-      s=$is$js$ks
-      smac=f00000000$s
-      sip=`ip_to_hex 192 168 $is$js $ks`
-      for id in 1 2 3; do
-          for jd in 1 2 3; do
-              for kd in 1 2 3; do
-                d=$id$jd$kd
-                dip=`ip_to_hex 192 168 $id$jd $kd`
-                if test $is = $id; then dmac=f00000000$d; else dmac=00000000ff$is$js; fi
-                if test $d != $s; then unicast=$d; else unicast=; fi
-
-                test_ip $s $smac $dmac $sip $dip $unicast #1
-
-                if test $id = $is && test $d != $s; then bcast="$bcast $d"; fi
-              done
-          done
-        done
-      test_ip $s $smac ffffffffffff $sip ffffffff $bcast #2
-      done
-  done
-done
-
-: > mac_bindings.expected
-
-# 3. Send an IP packet from every logical port to every other subnet,
-#    to an IP address that does not have a static IP-MAC binding.
-#    This should generate a broadcast ARP request for the destination
-#    IP address in the destination subnet.
-#    Moreover generate an ARP reply for each of the IP addresses ARPed
-for is in 1 2 3; do
-  for js in 1 2 3; do
-    for ks in 1 2 3; do
-      s=$is$js$ks
-      smac=f00000000$s
-      sip=`ip_to_hex 192 168 $is$js $ks`
-      for id in 1 2 3; do
-        for jd in 1 2 3; do
-          if test $is$js = $id$jd; then
-            continue
-          fi
-
-          # Send the packet.
-          dmac=00000000ff$is$js
-          # Calculate a 4th octet for the destination that is
-          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
-          # that have static MAC bindings, and fits in the range
-          # 0-255.
-          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
-          dip=`ip_to_hex 192 168 $id$jd $o4`
-          test_ip $s $smac $dmac $sip $dip
-
-          # Every LP on the destination subnet's lswitch should
-          # receive the ARP request.
-          lrmac=00000000ff$id$jd
-          lrip=`ip_to_hex 192 168 $id$jd 254`
-          arp=ffffffffffff${lrmac}08060001080006040001${lrmac}${lrip}000000000000${dip}
-          for jd2 in 1 2 3; do
-            for kd in 1 2 3; do
-              echo $arp >> $id$jd2$kd.expected
-            done
-          done
-
-          hmac=8000000000$o4
-          rmac=00000000ff$id$jd
-          echo ${hmac}${rmac}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 >> ${id}11.expected
-
-          host_mac=8000000000$o4
-          lrmac=00000000ff$id$jd
-
-          arp_reply=${lrmac}${host_mac}08060001080006040002${host_mac}${dip}${lrmac}${lrip}
-
-          hv=hv`vif_to_hv ${id}${jd}1`
-          as $hv ovs-appctl netdev-dummy/receive vif${id}${jd}1 $arp_reply
-
-          host_ip_pretty=192.168.$id$jd.$o4
-          host_mac_pretty=80:00:00:00:00:$o4
-          echo lrp$id$jd,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
-        done
-      done
-    done
-  done
-done
-
-# Test router replies to ARP requests from all source ports:
-#
-# 4. Router replies to query for its MAC address from port's own IP address.
-#
-# 5. Router replies to query for its MAC address from any random IP address
-#    in its subnet.
-#
-# 6. No reply to query for IP address other than router IP.
-#
-# 7. No reply to query from another subnet.
-for i in 1 2 3; do
-  for j in 1 2 3; do
-    for k in 1 2 3; do
-      smac=f00000000$i$j$k               # Source MAC
-      sip=`ip_to_hex 192 168 $i$j $k`    # Source IP
-      rip=`ip_to_hex 192 168 $i$j 254`   # Router IP
-      rmac=00000000ff$i$j                # Router MAC
-      otherip=`ip_to_hex 192 168 $i$j 55` # Some other IP in subnet
-      externalip=`ip_to_hex 1 2 3 4`      # Some other IP not in subnet
-
-      test_arp $i$j$k $smac $sip        $rip        $rmac      #4
-      test_arp $i$j$k $smac $otherip    $rip        $rmac      #5
-      test_arp $i$j$k $smac $sip        $otherip               #6
-
-      # When rip is 192.168.33.254, ARP request from externalip won't be
-      # filtered, because 192.168.33.254 is configured to switch peer port
-      # for lrp33.
-      lrp33_rsp=
-      if test $i = 3 && test $j = 3; then
-        lrp33_rsp=$rmac
-      fi
-      test_arp $i$j$k $smac $externalip $rip        $lrp33_rsp #7
-
-      # MAC binding should be learned from ARP request.
-      host_mac_pretty=f0:00:00:00:0$i:$j$k
-
-      host_ip_pretty=192.168.$i$j.$k
-      echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
-
-      # mac_binding is learned and overwritten so only the last one remains.
-      if test $k = 3; then
-          # lrp33 will not learn from ARP request, because 192.168.33.254 is
-          # configured to switch peer port for lrp33.
-          if test $i != 3 || test $j != 3; then
-              host_ip_pretty=192.168.$i$j.55
-              echo lrp$i$j,$host_ip_pretty,$host_mac_pretty >> mac_bindings.expected
-          fi
-      fi
-
-    done
-  done
-done
-
-
-# Allow some time for packet forwarding.
-# XXX This can be improved.
-sleep 1
-
-# 8. Send an IP packet from every logical port to every other subnet.  These
-#    are the same packets already sent as #3, but now the destinations' IP-MAC
-#    bindings have been discovered via ARP, so instead of provoking an ARP
-#    request, these packets now get routed to their destinations (which don't
-#    have static MAC bindings, so they go to the port we've designated as
-#    accepting "unknown" MACs.)
-for is in 1 2 3; do
-  for js in 1 2 3; do
-    for ks in 1 2 3; do
-      s=$is$js$ks
-      smac=f00000000$s
-      sip=`ip_to_hex 192 168 $is$js $ks`
-      for id in 1 2 3; do
-        for jd in 1 2 3; do
-          if test $is$js = $id$jd; then
-            continue
-          fi
-
-          # Send the packet.
-          dmac=00000000ff$is$js
-          # Calculate a 4th octet for the destination that is
-          # unique per $s, avoids the .1 .2 .3 and .254 IP addresses
-          # that have static MAC bindings, and fits in the range
-          # 0-255.
-          o4=`expr $is '*' 9 + $js '*' 3 + $ks + 10`
-          dip=`ip_to_hex 192 168 $id$jd $o4`
-          test_ip $s $smac $dmac $sip $dip
-
-          # Expect the packet egress.
-          host_mac=8000000000$o4
-          outport=${id}11
-          out_lrp=$id$jd
-          echo ${host_mac}00000000ff${out_lrp}08004500001c00000000"3f1101"00${sip}${dip}0035111100080000 >> $outport.expected
-        done
-      done
-    done
-  done
-done
-
-ovn-sbctl -f csv -d bare --no-heading \
-    -- --columns=logical_port,ip,mac list mac_binding > mac_bindings
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
-                              [$i$j$k.expected])
-        done
-    done
-done
-
-# Check the MAC bindings against those expected.
-AT_CHECK_UNQUOTED([sort < mac_bindings], [0], [`sort < mac_bindings.expected`
-])
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1], [hv2], [hv3])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- IP relocation using GARP request])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-#
-# Two logical switches ls1, ls2.
-# One logical router lr0 connected to ls[12],
-# with 2 subnets, 1 per logical switch:
-#
-#    lrp1 on ls1 for subnet 192.168.1.1/24
-#    lrp2 on ls2 for subnet 192.168.2.1/24
-#
-# 4 VIFs, 2 per LS lp[12][12], first digit being LS.
-# VIFs' fixed IP addresses are 192.168.[12].1[12].
-#
-# There is a secondary IP 192.168.1.100 that is unknown in NB and learned
-# through ARP only, and it can move between lp11 and lp12.
-#
-ovn-nbctl lr-add lr0
-for i in 1 2 ; do
-    ovn-nbctl ls-add ls$i
-    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.1/24
-    ovn-nbctl \
-        -- lsp-add ls$i lrp$i-attachment \
-        -- set Logical_Switch_Port lrp$i-attachment type=router \
-                         options:router-port=lrp$i \
-                         addresses=router
-    for j in 1 2; do
-        ovn-nbctl \
-            -- lsp-add ls$i lp$i$j \
-            -- lsp-set-addresses lp$i$j \
-               "f0:00:00:00:00:$i$j 192.168.$i.1$j"
-    done
-done
-
-# Physical network:
-# 2 hypervisors hv[12], lp?1 on hv1, lp?2 on hv2.
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located, e.g. "vif_to_hv 12" yields 2.
-vif_to_hv() {
-    echo ${1#?}
-}
-
-# Given the name of a logical port, prints the name of its logical router
-# port, e.g. "vif_to_lrp 12" yields 1.
-vif_to_lrp() {
-    echo ${1%?}
-}
-
-# Given the name of a logical port, prints the name of its logical
-# switch, e.g. "vif_to_ls 12" yields 1.
-vif_to_ls() {
-    echo ${1%?}
-}
-
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-done
-for i in 1 2; do
-    for j in 1 2; do
-        hv=`vif_to_hv $i$j`
-            as hv$hv ovs-vsctl \
-                -- add-port br-int vif$i$j \
-                -- set Interface vif$i$j \
-                    external-ids:iface-id=lp$i$j \
-                    options:tx_pcap=hv$hv/vif$i$j-tx.pcap \
-                    options:rxq_pcap=hv$hv/vif$i$j-rx.pcap \
-                    ofport-request=$i$j
-    done
-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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 12 for vif12.
-for i in 1 2; do
-    for j in 1 2; do
-        : > $i$j.expected
-    done
-done
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    in_ls=`vif_to_ls $inport`
-    in_lrp=`vif_to_lrp $inport`
-    for outport; do
-        out_ls=`vif_to_ls $outport`
-        if test $in_ls = $out_ls; then
-            # Ports on the same logical switch receive exactly the same packet.
-            echo $packet
-        else
-            # Routing decrements TTL and updates source and dest MAC
-            # (and checksum).
-            out_lrp=`vif_to_lrp $outport`
-            echo f000000000${outport}00000000ff0${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
-        fi >> $outport.expected
-    done
-}
-
-# test_arp INPORT SHA SPA TPA [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
-    local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
-
-    # Expect to receive the broadcast ARP on the other logical switch ports if
-    # IP address is not configured to the switch patch port.
-    local i=`vif_to_ls $inport`
-    local j
-    for j in 1 2; do
-        if test $i$j != $inport; then
-            echo $request >> $i$j$k.expected
-        fi
-    done
-
-    # Expect to receive the reply, if any.
-    if test X$reply_ha != X; then
-        lrp=`vif_to_lrp $inport`
-        local reply=${sha}00000000ff0${lrp}08060001080006040002${reply_ha}${tpa}${sha}${spa}
-        echo $reply >> $inport.expected
-    fi
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# lp11 send GARP request to announce ownership of 192.168.1.100.
-
-sha=f00000000011
-spa=`ip_to_hex 192 168 1 100`
-tpa=$spa
-test_arp 11 $sha $spa $tpa
-OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="192.168.1.100" | wc -l` -gt 0])
-ovn-nbctl --wait=hv sync
-
-# Send an IP packet from lp21 to 192.168.1.100, which should go to lp11.
-
-smac=f00000000021
-dmac=00000000ff02
-sip=`ip_to_hex 192 168 2 11`
-dip=`ip_to_hex 192 168 1 100`
-test_ip 21 $smac $dmac $sip $dip 11
-
-# lp12 send GARP request to announce ownership of 192.168.1.100.
-
-sha=f00000000012
-test_arp 12 $sha $spa $tpa
-OVS_WAIT_UNTIL([ovn-sbctl find mac_binding ip="192.168.1.100" | grep f0:00:00:00:00:12])
-ovn-nbctl --wait=hv sync
-# give to the hv the time to send queued ip packets
-sleep 1
-
-# Send an IP packet from lp21 to 192.168.1.100, which should go to lp12.
-
-test_ip 21 $smac $dmac $sip $dip 12
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2; do
-    for j in 1 2; do
-        OVN_CHECK_PACKETS([hv`vif_to_hv $i$j`/vif$i$j-tx.pcap],
-                          [$i$j.expected])
-    done
-done
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1], [hv2])
-
-AT_CLEANUP
-
-# 3 hypervisors, one logical switch, 3 logical ports per hypervisor
-AT_SETUP([ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Create hypervisors hv[123].
-# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
-# Add all of the vifs to a single logical switch lsw0.
-# Turn off port security on vifs vif[123]1
-# Turn on l2 port security on vifs vif[123]2
-# Turn of l2 and l3 port security on vifs vif[123]3
-# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
-ovn-nbctl ls-add lsw0
-net_add n1
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2 3; do
-        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
-        ovn-nbctl lsp-add lsw0 lp$i$j
-        if test $j = 1; then
-            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" unknown
-        elif test $j = 2; then
-            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j"
-            ovn-nbctl lsp-set-port-security lp$i$j f0:00:00:00:00:$i$j
-        else
-            extra_addr="f0:00:00:00:0$i:$i$j fe80::ea2a:eaff:fe28:$i$j"
-            ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
-            ovn-nbctl lsp-set-port-security lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr"
-        fi
-    done
-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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv${1%?}
-}
-
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        : > $i$j.expected
-    done
-done
-
-# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-#
-# This shell function causes an ip packet to be received on INPORT.
-# The packet's content has Ethernet destination DST and source SRC
-# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
-# The OUTPORTs (zero or more) list the VIFs on which the packet should
-# be received.  INPORT and the OUTPORTs are specified as logical switch
-# port numbers, e.g. 11 for vif11.
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-# test_arp INPORT SHA SPA TPA DROP [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local inport=$1 smac=$2 sha=$3 spa=$4 tpa=$5 drop=$6 reply_ha=$7
-    local request=ffffffffffff${smac}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-    hv=`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $request
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $request
-    if test $drop != 1; then
-        if test X$reply_ha = X; then
-            # Expect to receive the broadcast ARP on the other logical switch ports
-            # if no reply is expected.
-            local i j
-            for i in 1 2 3; do
-                for j in 1 2 3; do
-                    if test $i$j != $inport; then
-                        echo $request >> $i$j.expected
-                    fi
-                done
-            done
-        else
-            # Expect to receive the reply, if any.
-            local reply=${smac}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
-            echo $reply >> $inport.expected
-        fi
-    fi
-}
-
-# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-# This function is similar to test_ip() except that it sends
-# ipv6 packet
-test_ipv6() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}0000000000000000
-    shift; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-# test_icmpv6 INPORT  SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
-# This function is similar to test_ipv6() except it specifies the ICMPv6 type
-# of the test packet
-test_icmpv6() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
-    local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}${icmp_type}00000000000000
-    shift; shift; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# no port security
-sip=`ip_to_hex 192 168 0 12`
-tip=`ip_to_hex 192 168 0 13`
-# the arp packet should be allowed even if lp[123]1 is
-# not configured with mac f00000000023 and ip 192.168.0.12
-for i in 1 2 3; do
-    test_arp ${i}1 f00000000023 f00000000023 $sip $tip 0 f00000000013
-    for j in 1 2 3; do
-        if test $i != $j; then
-            test_ip ${i}1 f000000000${i}1 f000000000${j}1 $sip $tip ${j}1
-        fi
-    done
-done
-
-# l2 port security
-sip=`ip_to_hex 192 168 0 12`
-tip=`ip_to_hex 192 168 0 13`
-
-# arp packet should be allowed since lp22 is configured with
-# mac f00000000022
-test_arp 22 f00000000022 f00000000022 $sip $tip 0 f00000000013
-
-# arp packet should not be allowed since lp32 is not configured with
-# mac f00000000021
-test_arp 32 f00000000021 f00000000021 $sip $tip 1
-
-# arp packet with sha set to f00000000021 should not be allowed
-# for lp12
-test_arp 12 f00000000012 f00000000021 $sip $tip 1
-
-# ip packets should be allowed and received since lp[123]2 do not
-# have l3 port security
-sip=`ip_to_hex 192 168 0 55`
-tip=`ip_to_hex 192 168 0 66`
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        if test $i != $j; then
-            test_ip ${i}2 f000000000${i}2 f000000000${j}2 $sip $tip ${j}2
-        fi
-    done
-done
-
-# ipv6 packets should be received by lp[123]2
-# lp[123]1 can send ipv6 traffic as there is no port security
-sip=fe800000000000000000000000000000
-tip=ff020000000000000000000000000000
-
-for i in 1 2 3; do
-    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}2 $sip $tip ${i}2
-done
-
-
-# l2 and l3 port security
-sip=`ip_to_hex 192 168 0 13`
-tip=`ip_to_hex 192 168 0 22`
-# arp packet should be allowed since lp13 is configured with
-# f00000000013 and 192.168.0.13
-test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
-
-# the arp packet should be dropped because lp23 is not configured
-# with mac f00000000022
-sip=`ip_to_hex 192 168 0 13`
-tip=`ip_to_hex 192 168 0 22`
-test_arp 23 f00000000022 f00000000022 $sip $tip 1
-
-# the arp packet should be dropped because lp33 is not configured
-# with ip 192.168.0.55
-spa=`ip_to_hex 192 168 0 55`
-tpa=`ip_to_hex 192 168 0 22`
-test_arp 33 f00000000031 f00000000031 $spa $tpa 1
-
-# ip packets should not be received by lp[123]3 since
-# l3 port security is enabled
-sip=`ip_to_hex 192 168 0 55`
-tip=`ip_to_hex 192 168 0 66`
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        test_ip ${i}2 f000000000${i}2 f000000000${j}3 $sip $tip
-    done
-done
-
-# ipv6 packets should be dropped for lp[123]3 since
-# it is configured with only ipv4 address
-sip=fe800000000000000000000000000000
-tip=ff020000000000000000000000000000
-
-for i in 1 2 3; do
-    test_ipv6 ${i}3 f000000000${i}3 f00000000022 $sip $tip
-done
-
-# ipv6 packets should not be received by lp[123]3 with mac f000000000$[123]3
-# lp[123]1 can send ipv6 traffic as there is no port security
-for i in 1 2 3; do
-    test_ipv6 ${i}1 f000000000${i}1 f000000000${i}3 $sip $tip
-done
-
-# lp13 has extra port security with mac f0000000113 and ipv6 addr
-# fe80::ea2a:eaff:fe28:0012
-
-# ipv4 packet should be dropped for lp13 with mac f0000000113
-sip=`ip_to_hex 192 168 0 13`
-tip=`ip_to_hex 192 168 0 23`
-test_ip 13 f00000000113 f00000000023 $sip $tip
-
-# ipv6 packet should be received by lp[123]3 with mac f00000000${i}${i}3
-# and ip6.dst as fe80::ea2a:eaff:fe28:0${i}${i}3.
-# lp11 can send ipv6 traffic as there is no port security
-sip=ee800000000000000000000000000000
-for i in 1 2 3; do
-    tip=fe80000000000000ea2aeafffe2800${i}3
-    test_ipv6 11 f00000000011 f00000000${i}${i}3 $sip $tip ${i}3
-done
-
-
-# ipv6 packet should not be received by lp33 with mac f0000000333
-# and ip6.dst as fe80::ea2a:eaff:fe28:0023 as it is
-# configured with fe80::ea2a:eaff:fe28:0033
-# lp11 can send ipv6 traffic as there is no port security
-
-sip=ee800000000000000000000000000000
-tip=fe80000000000000ea2aeafffe280023
-test_ipv6 11 f00000000011 f00000000333 $sip $tip
-
-# ipv6 packet should be allowed for lp[123]3 with mac f0000000${i}${i}3
-# and ip6.src fe80::ea2a:eaff:fe28:0${i}${i}3 and ip6.src ::.
-# and should be dropped for any other ip6.src
-# lp21 can receive ipv6 traffic as there is no port security
-
-tip=ee800000000000000000000000000000
-for i in 1 2 3; do
-    sip=fe80000000000000ea2aeafffe2800${i}3
-    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 21
-
-    # Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
-    sip=00000000000000000000000000000000
-    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 83 21
-    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 8f 21
-    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff0200000000000000ea2aeafffe2800 87 21
-    # Traffic to non-multicast traffic should be dropped
-    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip 83
-    # Traffic of other ICMPv6 types should be dropped
-    test_icmpv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip ff020000000000000000000000160000 80
-
-    # should be dropped
-    sip=ae80000000000000ea2aeafffe2800aa
-    test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
-done
-
-# configure lsp13 to send and received IPv4 packets with an address range
-ovn-nbctl lsp-set-port-security lp13 "f0:00:00:00:00:13 192.168.0.13 20.0.0.4/24 10.0.0.0/24"
-
-sleep 2
-
-sip=`ip_to_hex 10 0 0 13`
-tip=`ip_to_hex 192 168 0 22`
-# arp packet with inner ip 10.0.0.13 should be allowed for lsp13
-test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
-
-sip=`ip_to_hex 10 0 0 14`
-tip=`ip_to_hex 192 168 0 23`
-# IPv4 packet from lsp13 with src ip 10.0.0.14 destined to lsp23
-# with dst ip 192.168.0.23 should be allowed
-test_ip 13 f00000000013 f00000000023 $sip $tip 23
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 10 0 0 15`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 10.0.0.15 should be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip 13
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 20 0 0 4`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 20.0.0.4 should be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip 13
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 20 0 0 5`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 20.0.0.5 should not be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 20 0 0 255`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 20.0.0.255 should be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip 13
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 192 168 0 255`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 192.168.0.255 should not be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip
-
-sip=`ip_to_hex 192 168 0 33`
-tip=`ip_to_hex 224 0 0 4`
-# IPv4 packet from lsp33 with src ip 192.168.0.33 destined to lsp13
-# with dst ip 224.0.0.4  should be received by lsp13
-test_ip 33 f00000000033 f00000000013 $sip $tip 13
-
-#dump information including flow counters
-ovn-nbctl show
-ovn-sbctl dump-flows -- list multicast_group
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 show br-int
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-ofctl -O OpenFlow13 show br-int
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-echo "------ hv3 dump ------"
-as hv3 ovs-vsctl show
-as hv3 ovs-ofctl -O OpenFlow13 show br-int
-as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
-    done
-done
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24
-# network. R1 has a switchs ls1 (191.168.1.0/24) connected to it.
-# R2 has ls2 (172.16.1.0/24) connected to it.
-
-ls1_lp1_mac="f0:00:00:01:02:03"
-rp_ls1_mac="00:00:00:01:02:03"
-rp_ls2_mac="00:00:00:01:02:04"
-ls2_lp1_mac="f0:00:00:01:02:04"
-
-ls1_lp1_ip="192.168.1.2"
-ls2_lp1_ip="172.16.1.2"
-
-ovn-nbctl lr-add R1
-ovn-nbctl lr-add R2
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 $rp_ls1_mac 192.168.1.1/24
-
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
-  options:router-port=ls1 addresses=\"$rp_ls1_mac\"
-
-# Connect ls2 to R2
-ovn-nbctl lrp-add R2 ls2 $rp_ls2_mac 172.16.1.1/24
-
-ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \
-  options:router-port=ls2 addresses=\"$rp_ls2_mac\"
-
-# Connect R1 to R2
-ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
-ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
-
-ovn-nbctl lr-route-add R1 "0.0.0.0/0" 20.0.0.2
-ovn-nbctl lr-route-add R2 "0.0.0.0/0" 20.0.0.1
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "$ls1_lp1_mac $ls1_lp1_ip"
-
-# Create logical port ls2-lp1 in ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "$ls2_lp1_mac $ls2_lp1_ip"
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Packet to send.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
-        udp && udp.src==53 && udp.dst==4369"
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-
-# Packet to Expect
-# The TTL should be decremented by 2.
-packet="eth.src==$rp_ls2_mac && eth.dst==$ls2_lp1_mac &&
-        ip4 && ip.ttl==62 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
-        udp && udp.src==53 && udp.dst==4369"
-echo $packet | ovstest test-ovn expr-to-packets > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
-grep "reg0 == 172.16.1.2" | wc -l], [0], [1
-])
-
-# Disable the ls2-lp1 port.
-ovn-nbctl --wait=hv set logical_switch_port ls2-lp1 enabled=false
-
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_arp_resolve | \
-grep "reg0 == 172.16.1.2" | wc -l], [0], [0
-])
-
-# Generate the packet destined for ls2-lp1 and it should not be delivered.
-# Packet to send.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_lp1_mac && eth.dst==$rp_ls1_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$ls1_lp1_ip && ip4.dst==$ls2_lp1_ip &&
-        udp && udp.src==53 && udp.dst==4369"
-
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-# The 2nd packet sent shound not be received.
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-
-AT_SETUP([ovn -- 1 HV, 1 LS, 2 lport/LS, 1 LR])
-AT_KEYWORDS([router-admin-state])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR - R1 has switch ls1 with two subnets attached to it (191.168.1.0/24
-# and 172.16.1.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add ls1
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24 172.16.1.1/24
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
-          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
-          -- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port ls1-lp2 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp2 \
-          -- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:04 172.16.1.2"
-
-# Create one hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int vif1 -- \
-    set interface vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif2 -- \
-    set interface vif2 external-ids:iface-id=ls1-lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=1
-
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Send ip packets between the two ports.
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Packet to send.
-src_mac="f00000010203"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
-
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-
-#Disable router R1
-ovn-nbctl set Logical_Router R1 enabled=false
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
-
-# Packet to Expect
-expect_src_mac="000000010203"
-expect_dst_mac="f00000010204"
-echo "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-
-AT_SETUP([ovn -- 1 HV, 2 LSs, 1 lport/LS, 1 LR])
-AT_KEYWORDS([router-admin-state])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
-# and has switch ls2 (172.16.1.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 type=router \
-          options:router-port=ls1 addresses=\"00:00:00:01:02:03\"
-
-# Connect ls2 to R1
-ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:04 172.16.1.1/24
-ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 type=router \
-          options:router-port=ls2 addresses=\"00:00:00:01:02:04\"
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port ls2-lp1 in ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Create one hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int vif1 -- \
-    set interface vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif2 -- \
-    set interface vif2 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=1
-
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Send ip packets between the two ports.
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Packet to send.
-src_mac="f00000010203"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
-
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-#Disable router R1
-ovn-nbctl set Logical_Router R1 enabled=false
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-# Allow some time for the disabling of logical router R1 to propagate.
-# XXX This should be more systematic.
-sleep 1
-
-as hv1 ovs-appctl netdev-dummy/receive vif1 $packet
-
-# Packet to Expect
-expect_src_mac="000000010204"
-expect_dst_mac="f00000010204"
-echo "${expect_dst_mac}${expect_src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 3 LS, 1 lport/LS, 2 peer LRs, static routes])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24
-# network. R1 has switchess foo (192.168.1.0/24)
-# connected to it.
-# R2 has alice (172.16.1.0/24) and bob (172.16.2.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-ovn-nbctl lr-add R2
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add bob
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-          options:router-port=foo addresses=\"00:00:00:01:02:03\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:00:01:02:04 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-          type=router options:router-port=alice addresses=\"00:00:00:01:02:04\"
-
-# Connect bob to R2
-ovn-nbctl lrp-add R2 bob 00:00:00:01:02:05 172.16.2.1/24
-ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob type=router \
-          options:router-port=bob addresses=\"00:00:00:01:02:05\"
-
-# Connect R1 to R2
-ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 peer=R2_R1
-ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 peer=R1_R2
-
-#install static routes
-ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
-ovn-nbctl lr-route-add R2 172.16.2.0/24 20.0.0.2 R1_R2
-ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port alice1 in alice
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Create logical port bob1 in bob
-ovn-nbctl lsp-add bob bob1 \
--- lsp-set-addresses bob1 "f0:00:00:01:02:05 172.16.2.2"
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=bob1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and alice1
-src_mac="f00000010203"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-# Send ip packets between foo1 and bob1
-src_mac="f00000010203"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 2 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump ----------"
-as hv2 ovs-ofctl dump-flows br-int
-
-# Packet to Expect at bob1
-src_mac="000000010205"
-dst_mac="f00000010205"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 2 2`
-echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Packet to Expect at alice1
-src_mac="000000010204"
-dst_mac="f00000010204"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- send gratuitous arp on localnet])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-ovn-nbctl ls-add lsw0
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0
-
-ovn_attach n1 br-phys 192.168.0.1
-
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
-AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv/snoopvif-tx.pcap options:rxq_pcap=hv/snoopvif-rx.pcap])
-
-# Create a vif.
-AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01 192.168.1.2"])
-AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
-
-AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
-
-# Wait for packet to be received.
-echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" > expected
-OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
-
-# Check GARP packet when restart openflow connection.
-as hv
-OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
-
-OVS_WAIT_UNTIL([grep -c "waiting 4 seconds before reconnect" hv/ovn-controller.log])
-
-as hv
-start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl
-
-# Wait for packet to be received.
-echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80102000000000000c0a80102" > expected
-OVN_CHECK_PACKETS([hv/snoopvif-tx.pcap], [expected])
-
-# Delete the localnet ports.
-AT_CHECK([ovs-vsctl del-port localvif1])
-AT_CHECK([ovn-nbctl lsp-del ln_port])
-
-OVN_CLEANUP([hv])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 3 LRs connected via LS, static routes])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
-# connected to it. R2 has alice (172.16.1.0/24) and R3 has bob (10.32.1.0/24)
-# connected to it.
-
-ovn-nbctl lr-add R1
-ovn-nbctl lr-add R2
-ovn-nbctl lr-add R3
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add bob
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-    options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect bob to R3
-ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 10.32.1.1/24
-ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
-    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Connect R3 to join
-ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
-ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
-    type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
-
-#install static routes
-ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
-ovn-nbctl lr-route-add R1 10.32.1.0/24 20.0.0.3
-
-ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1
-ovn-nbctl lr-route-add R2 10.32.1.0/24 20.0.0.3
-
-ovn-nbctl lr-route-add R3 192.168.1.0/24 20.0.0.1
-ovn-nbctl lr-route-add R3 172.16.1.0/24 20.0.0.2
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port alice1 in alice
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Create logical port bob1 in bob
-ovn-nbctl lsp-add bob bob1 \
--- lsp-set-addresses bob1 "f0:00:00:01:02:05 10.32.1.2"
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=bob1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and alice1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
-
-# Send ip packets between foo1 and bob1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 10 32 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-echo "----------------------------"
-
-# Packet to Expect at bob1
-src_mac="000003010203"
-dst_mac="f00000010205"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 10 32 1 2`
-echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Packet to Expect at alice1
-src_mac="000002010203"
-dst_mac="f00000010204"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-echo "${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- dhcpv4 : 1 HV, 2 LS, 2 LSPs/LS])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-ovn-nbctl lsp-add ls1 ls1-lp2 \
--- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
-
-ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
-
-ovn-nbctl ls-add ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
-ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 30.0.0.6 40.0.0.4"
-ovn-nbctl lsp-add ls2 ls2-lp2 \
--- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
-ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
-
-d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
-options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
-\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
-
-ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
-ovn-nbctl lsp-set-dhcpv4-options ls1-lp2 ${d1}
-
-d2="$(ovn-nbctl create DHCP_Options cidr=30.0.0.0/24 \
-options="\"server_id\"=\"30.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:02\" \
-\"lease_time\"=\"3600\"")"
-
-ovn-nbctl lsp-set-dhcpv4-options ls2-lp2 ${d2}
-
-net_add n1
-sim_add hv1
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-ovs-vsctl -- add-port br-int hv1-vif3 -- \
-    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=hv1/vif3-tx.pcap \
-    options:rxq_pcap=hv1/vif3-rx.pcap \
-    ofport-request=3
-
-ovs-vsctl -- add-port br-int hv1-vif4 -- \
-    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
-    options:tx_pcap=hv1/vif4-tx.pcap \
-    options:rxq_pcap=hv1/vif4-rx.pcap \
-    ofport-request=4
-
-OVN_POPULATE_ARP
-
-sleep 2
-
-as hv1 ovs-vsctl show
-
-# This shell function sends a DHCP request packet
-# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP REQUEST_IP ...
-test_dhcp() {
-    local inport=$1 src_mac=$2 dhcp_type=$3 ciaddr=$4 offer_ip=$5 request_ip=$6 use_ip=$7
-    shift; shift; shift; shift; shift; shift; shift;
-    if test $use_ip != 0; then
-        src_ip=$1
-        dst_ip=$2
-        shift; shift;
-    else
-        src_ip=`ip_to_hex 0 0 0 0`
-        dst_ip=`ip_to_hex 255 255 255 255`
-    fi
-    if test $request_ip != 0; then
-        ip_len=0120
-        udp_len=010b
-    else
-        ip_len=011a
-        udp_len=0106
-    fi
-    local request=ffffffffffff${src_mac}08004510${ip_len}0000000080110000${src_ip}${dst_ip}
-    # udp header and dhcp header
-    request=${request}00440043${udp_len}0000
-    request=${request}010106006359aa7600000000${ciaddr}000000000000000000000000${src_mac}
-    # client hardware padding
-    request=${request}00000000000000000000
-    # server hostname
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    # boot file name
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    # dhcp magic cookie
-    request=${request}63825363
-    # dhcp message type
-    request=${request}3501${dhcp_type}
-    # dhcp unknown option
-    request=${request}d70701020304050607
-    # dhcp pad option
-    request=${request}00
-    if test $request_ip != 0; then
-        # dhcp requested ip
-        request=${request}3204${request_ip}
-    fi
-    # dhcp end option
-    request=${request}ff
-
-    for port in $inport "$@"; do
-        : >> $port.expected
-    done
-    if test $offer_ip != 0; then
-        local srv_mac=$1 srv_ip=$2 dhcp_reply_type=$3 expected_dhcp_opts=$4
-        # total IP length will be the IP length of the request packet
-        # (which is 272 in our case) + 8 (padding bytes) + (expected_dhcp_opts / 2)
-        ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
-        udp_len=`expr $ip_len - 20`
-        ip_len=$(printf "%x" $ip_len)
-        udp_len=$(printf "%x" $udp_len)
-        # $ip_len var will be in 3 digits i.e 134. So adding a '0' before $ip_len
-        local reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
-        # udp header and dhcp header.
-        # $udp_len var will be in 3 digits. So adding a '0' before $udp_len
-        reply=${reply}004300440${udp_len}0000020106006359aa7600000000${ciaddr}
-        # your ip address; 0 for NAK
-        if test $dhcp_reply_type = 06; then
-            reply=${reply}00000000
-        else
-            reply=${reply}${offer_ip}
-        fi
-        # next server ip address, relay agent ip address, client mac address
-        reply=${reply}0000000000000000${src_mac}
-        # client hardware padding
-        reply=${reply}00000000000000000000
-        # server hostname
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        # boot file name
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-        # dhcp magic cookie
-        reply=${reply}63825363
-        reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
-        echo $reply >> $inport.expected
-    else
-        for outport; do
-            echo $request >> $outport.expected
-        done
-    fi
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-AT_CAPTURE_FILE([ofctl_monitor0.log])
-as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-# Send DHCPDISCOVER.
-offer_ip=`ip_to_hex 10 0 0 4`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=`ip_to_hex 0 0 0 0`
-request_ip=0
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000001 01 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 1.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
-cat 1.expected | cut -c -48 > expout
-AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 1.expected | cut -c 53- > expout
-AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
-
-# ovs-ofctl also resumes the packets and this causes other ports to receive
-# the DHCP request packet. So reset the pcap files so that its easier to test.
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
-# address in the Requested IP Address option.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=`ip_to_hex 0 0 0 0`
-request_ip=$offer_ip
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 05 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with a mismatched IP in
-# the Requested IP Address option, expect a DHCPNAK.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=`ip_to_hex 0 0 0 0`
-request_ip=`ip_to_hex 10 0 0 7`
-expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 06 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 3.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send Invalid DHCPv4 packet on ls1-lp2. It should be received by ovn-controller
-# but should be resumed without the reply.
-# ls1-lp1 (vif1-tx.pcap) should receive the DHCPv4 request packet twice,
-# one from ovn-controller and the other from "ovs-ofctl resume."
-ciaddr=`ip_to_hex 0 0 0 0`
-offer_ip=0
-request_ip=0
-test_dhcp 2 f00000000002 08 $ciaddr $offer_ip $request_ip 0 1 1
-
-# NXT_RESUMEs should be 4.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-# vif1-tx.pcap should have received the DHCPv4 (invalid) request packet
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPv4 packet on ls2-lp1. It doesn't have any DHCPv4 options defined.
-# ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet once.
-
-ciaddr=`ip_to_hex 0 0 0 0`
-test_dhcp 3 f00000000003 01 $ciaddr 0 0 4 0
-
-# Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not defined for
-# this lport.
-ciaddr=`ip_to_hex 0 0 0 0`
-test_dhcp 4 f00000000004 01 $ciaddr 0 0 3 0
-
-# NXT_RESUMEs should be 4.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
-#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
-
-# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to 10.0.0.6
-# and ip4.dst set to 10.0.0.1.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=$offer_ip
-request_ip=0
-src_ip=$offer_ip
-dst_ip=$server_ip
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 5.
-OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to 10.0.0.6
-# and ip4.dst set to 255.255.255.255.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=$offer_ip
-request_ip=0
-src_ip=$offer_ip
-dst_ip=`ip_to_hex 255 255 255 255`
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 6.
-OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST in the RENEWING/REBINDING state with a mismatched IP in the
-# ciaddr, expect a DHCPNAK.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=`ip_to_hex 10 0 0 7`
-request_ip=0
-src_ip=$offer_ip
-dst_ip=`ip_to_hex 255 255 255 255`
-expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 7.
-OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST in the RENEWING/REBINDING state without a specifyied ciaddr,
-# expect a DHCPNAK.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-ciaddr=`ip_to_hex 0 0 0 0`
-request_ip=0
-src_ip=$offer_ip
-dst_ip=`ip_to_hex 255 255 255 255`
-expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
-
-# NXT_RESUMEs should be 8.
-OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Send DHCPREQUEST with ip4.src set to 10.0.0.6 and ip4.dst set to 10.0.0.4.
-# The packet should not be received by ovn-controller.
-ciaddr=`ip_to_hex 0 0 0 0`
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 4`
-test_dhcp 2 f00000000002 03 $ciaddr 0 0 1 $src_ip $dst_ip 1
-
-# NXT_RESUMEs should be 8.
-OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-# vif1-tx.pcap should have received the DHCPv4 request packet
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [1.expected])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
-
-ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
-
-ovn-nbctl lsp-add ls1 ls1-lp2 \
--- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 ae70::5"
-
-ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
-
-ovn-nbctl lsp-add ls1 ls1-lp3 \
--- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
-
-ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
-
-d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
-options="\"server_id\"=\"00:00:00:10:00:01\"")"
-
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
-
-d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
-options="\"dhcpv6_stateless\"=\"true\" \"server_id\"=\"00:00:00:10:00:01\"")"
-
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp3 ${d2}
-
-ovn-nbctl ls-add ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
-ovn-nbctl lsp-set-port-security ls2-lp1 "f0:00:00:00:00:03 be70::3"
-ovn-nbctl lsp-add ls2 ls2-lp2 \
--- lsp-set-addresses ls2-lp2 "f0:00:00:00:00:04 be70::4"
-ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 be70::4"
-
-net_add n1
-sim_add hv1
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-ovs-vsctl -- add-port br-int hv1-vif3 -- \
-    set interface hv1-vif3 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=hv1/vif3-tx.pcap \
-    options:rxq_pcap=hv1/vif3-rx.pcap \
-    ofport-request=3
-
-ovs-vsctl -- add-port br-int hv1-vif4 -- \
-    set interface hv1-vif4 external-ids:iface-id=ls2-lp2 \
-    options:tx_pcap=hv1/vif4-tx.pcap \
-    options:rxq_pcap=hv1/vif4-rx.pcap \
-    ofport-request=4
-
-ovs-vsctl -- add-port br-int hv1-vif5 -- \
-    set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
-    options:tx_pcap=hv1/vif5-tx.pcap \
-    options:rxq_pcap=hv1/vif5-rx.pcap \
-    ofport-request=5
-
-OVN_POPULATE_ARP
-
-sleep 2
-
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-# This shell function sends a DHCPv6 request packet
-# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
-# The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
-# packet should be received twice (one from ovn-controller and the other
-# from the "ovs-ofctl monitor br-int resume"
-test_dhcpv6() {
-    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
-    if test $msg_code != 0b; then
-        req_len=2a
-    else
-        req_len=1a
-    fi
-    local request=ffffffffffff${src_mac}86dd0000000000${req_len}1101${src_lla}
-    # dst ip ff02::1:2
-    request=${request}ff020000000000000000000000010002
-    # udp header and dhcpv6 header
-    request=${request}0222022300${req_len}ffff${msg_code}010203
-    # Client identifier
-    request=${request}0001000a00030001${src_mac}
-    # Add IA-NA (Identity Association for Non Temporary Address) if msg_code
-    # is not 11 (information request packet)
-    if test $msg_code != 0b; then
-        request=${request}0003000c0102030400000e1000001518
-    fi
-    shift; shift; shift; shift; shift;
-    if test $offer_ip != 0; then
-        local server_mac=000000100001
-        local server_lla=fe80000000000000020000fffe100001
-        local reply_code=07
-        if test $msg_code = 01; then
-            reply_code=02
-        fi
-        local msg_len=54
-        if test $offer_ip = 1; then
-            msg_len=28
-        fi
-        local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla}
-        # udp header and dhcpv6 header
-        reply=${reply}0223022200${msg_len}ffff${reply_code}010203
-        # Client identifier
-        reply=${reply}0001000a00030001${src_mac}
-        # IA-NA
-        if test $offer_ip != 1; then
-            reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
-        fi
-        # Server identifier
-        reply=${reply}0002000a00030001${server_mac}
-        echo $reply | trim_zeros >> $inport.expected
-    else
-        for outport; do
-            echo $request | trim_zeros >> $outport.expected
-        done
-    fi
-
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-AT_CAPTURE_FILE([ofctl_monitor0.log])
-as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-src_mac=f00000000001
-src_lla=fe80000000000000f20000fffe000001
-offer_ip=ae700000000000000000000000000004
-test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
-
-# NXT_RESUMEs should be 1.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap | trim_zeros > 1.packets
-# cat 1.expected | trim_zeros > expout
-cat 1.expected | cut -c -120 > expout
-AT_CHECK([cat 1.packets | cut -c -120], [0], [expout])
-# Skipping the UDP checksum
-cat 1.expected | cut -c 125- > expout
-AT_CHECK([cat 1.packets | cut -c 125-], [0], [expout])
-
-rm  1.expected
-
-# Send invalid packet on ls1-lp2. ovn-controller should resume the packet
-# without any modifications and the packet should be received by ls1-lp1.
-# ls1-lp1 will receive the packet twice, one from the ovn-controller after the
-# resume and the other from ovs-ofctl monitor resume.
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-
-src_mac=f00000000002
-src_lla=fe80000000000000f20000fffe000002
-offer_ip=ae700000000000000000000000000005
-# Set invalid msg_type
-
-test_dhcpv6 2 $src_mac $src_lla 10 0 1 1
-
-# NXT_RESUMEs should be 2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-# vif2-tx.pcap should not have received the DHCPv6 reply packet
-rm 2.packets
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap | trim_zeros > 2.packets
-AT_CHECK([cat 2.packets], [0], [])
-
-# vif1-tx.pcap should have received the DHCPv6 (invalid) request packet
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap | trim_zeros > 1.packets
-cat 1.expected > expout
-AT_CHECK([cat 1.packets], [0], [expout])
-
-# Send DHCPv6 packet on ls2-lp1. native DHCPv6 is disabled on this port.
-# There should be no DHCPv6 reply from ovn-controller and the request packet
-# should be received by ls2-lp2.
-
-src_mac=f00000000003
-src_lla=fe80000000000000f20000fffe000003
-test_dhcpv6 3 $src_mac $src_lla 01 0 4
-
-# NXT_RESUMEs should be 2 only.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-# vif3-tx.pcap should not have received the DHCPv6 reply packet
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap | trim_zeros > 3.packets
-AT_CHECK([cat 3.packets], [0], [])
-
-# vif4-tx.pcap should have received the DHCPv6 request packet
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif4-tx.pcap | trim_zeros > 4.packets
-cat 4.expected > expout
-AT_CHECK([cat 4.packets], [0], [expout])
-
-# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless mode for this port.
-# The DHCPv6 reply shouldn't contain offer_ip.
-src_mac=f00000000022
-src_lla=fe80000000000000f20000fffe000022
-reset_pcap_file hv1-vif5 hv1/vif5
-test_dhcpv6 5 $src_mac $src_lla 01 1 5
-
-# NXT_RESUMEs should be 3.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap | trim_zeros > 5.packets
-# Skipping the UDP checksum
-cat 5.expected | cut -c 1-120,125- > expout
-AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
-
-# Send DHCPv6 information request (code 11) on ls1-lp3. The DHCPv6 reply
-# shouldn't contain offer_ip
-src_mac=f00000000022
-src_lla=fe80000000000000f20000fffe000022
-reset_pcap_file hv1-vif5 hv1/vif5
-rm -f 5.expected
-test_dhcpv6 5 $src_mac $src_lla 0b 1 5
-
-# NXT_RESUMEs should be 4.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap |
-trim_zeros > 5.packets
-# Skipping the UDP checksum
-cat 5.expected | cut -c 1-120,125- > expout
-AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 2 LRs connected via LS, gateway router])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24)
-# connected to it. R2 has alice (172.16.1.0/24) connected to it.
-# R2 is a gateway router.
-
-
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-# 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
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-
-#install static routes
-ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
-ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \
-R1 static_routes @lrt
-
-ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
-ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
-R2 static_routes @lrt
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port alice1 in alice
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and alice1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-ovn-sbctl list chassis
-ovn-sbctl list encap
-echo "---------------------"
-
-# Packet to Expect at alice1
-src_mac="000002010203"
-dst_mac="f00000010204"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
-
-
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
-
-echo "------ hv1 dump after packet 1 ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump after packet 1 ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-echo "----------------------------"
-
-echo $expected > expected
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Delete the router and re-create it. Things should work as before.
-ovn-nbctl  lr-del R2
-ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-
-ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
-ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \
-R2 static_routes @lrt
-
-# Wait for ovn-controller to catch up.
-sleep 1
-
-# Send the packet again.
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-echo "------ hv1 dump after packet 2 ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump after packet 2 ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-echo "----------------------------"
-
-echo $expected >> expected
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- icmp_reply: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
-AT_KEYWORDS([router-icmp-reply])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
-# and has switch ls2 (172.16.1.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
-    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
-
-# Connect ls2 to R1
-ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
-ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
-    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
-
-# Create logical port ls2-lp1 in ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
-
-# Create one hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int vif1 -- \
-    set interface vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif2 -- \
-    set interface vif2 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=1
-
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-for i in 1 2; do
-    : > vif$i.expected
-done
-# test_ipv4_icmp_request INPORT ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM ICMP_CHKSUM [EXP_IP_CHKSUM EXP_ICMP_CHKSUM]
-#
-# Causes a packet to be received on INPORT.  The packet is an ICMPv4
-# request with ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHSUM and
-# ICMP_CHKSUM as specified.  If EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are
-# provided, then it should be the ip and icmp checksums of the packet
-# responded; otherwise, no reply is expected.
-# In the absence of an ip checksum calculation helpers, this relies
-# on the caller to provide the checksums for the ip and icmp headers.
-# XXX This should be more systematic.
-#
-# INPORT is an lport number, e.g. 11 for vif11.
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC and IPV4_DST are each 8 hex digits.
-# IP_CHSUM and ICMP_CHKSUM are each 4 hex digits.
-# EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits.
-test_ipv4_icmp_request() {
-    local inport=$1 eth_src=$2 eth_dst=$3 ipv4_src=$4 ipv4_dst=$5 ip_chksum=$6 icmp_chksum=$7
-    local exp_ip_chksum=$8 exp_icmp_chksum=$9
-    shift; shift; shift; shift; shift; shift; shift
-    shift; shift
-
-    # Use ttl to exercise section 4.2.2.9 of RFC1812
-    local ip_ttl=01
-    local icmp_id=5fbf
-    local icmp_seq=0001
-    local icmp_data=$(seq 1 56 | xargs printf "%02x")
-    local icmp_type_code_request=0800
-    local icmp_payload=${icmp_type_code_request}${icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
-    local packet=${eth_dst}${eth_src}08004500005400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${icmp_payload}
-
-    as hv1 ovs-appctl netdev-dummy/receive vif$inport $packet
-    if test X$exp_icmp_chksum != X; then
-        # Expect to receive the reply, if any. In same port where packet was sent.
-        # Note: src and dst fields are expected to be reversed.
-        local icmp_type_code_response=0000
-        local reply_icmp_ttl=fe
-        local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_id}${icmp_seq}${icmp_data}
-        local reply=${eth_src}${eth_dst}08004500005400004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
-        echo $reply >> vif$inport.expected
-    fi
-}
-
-# Send ping packet to router's ip addresses, from each of the 2 logical ports.
-rtr_l1_ip=$(ip_to_hex 192 168 1 1)
-rtr_l2_ip=$(ip_to_hex 172 16 1 1)
-l1_ip=$(ip_to_hex 192 168 1 2)
-l2_ip=$(ip_to_hex 172 16 1 2)
-
-# Ping router ip address that is on same subnet as the logical port
-test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l1_ip 0000 8510 02ff 8d10
-test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l2_ip 0000 8510 02ff 8d10
-
-# Ping router ip address that is on the other side of the logical ports
-test_ipv4_icmp_request 1 000000010203 0000000102f1 $l1_ip $rtr_l2_ip 0000 8510 02ff 8d10
-test_ipv4_icmp_request 2 000000010204 0000000102f2 $l2_ip $rtr_l1_ip 0000 8510 02ff 8d10
-
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list logical_flow
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-# Now check the packets actually received against the ones expected.
-for inport in 1 2; do
-    OVN_CHECK_PACKETS([hv1/vif${inport}-tx.pcap], [vif$inport.expected])
-done
-
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- policy-based routing: 1 HVs, 2 LSs, 1 lport/LS, 1 LR])
-AT_KEYWORDS([policy-based-routing])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
-# and has switch ls2 (172.16.1.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-ovn-nbctl ls-add ls3
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 192.168.1.1/24
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
-    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
-
-# Connect ls2 to R1
-ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 172.16.1.1/24
-ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
-    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
-
-# Connect ls3 to R1
-ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 20.20.1.1/24
-ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
-    type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.168.1.2"
-
-# Create logical port ls2-lp1 in ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 172.16.1.2"
-
-# Create logical port ls3-lp1 in ls3
-ovn-nbctl lsp-add ls3 ls3-lp1 \
--- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 20.20.1.2"
-
-# Create one hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add pbr-hv
-as pbr-hv
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-
-ovs-vsctl -- add-port br-int vif1 -- \
-    set interface vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=pbr-hv/vif1-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif2 -- \
-    set interface vif2 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=pbr-hv/vif2-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif3 -- \
-    set interface vif3 external-ids:iface-id=ls3-lp1 \
-    options:tx_pcap=pbr-hv/vif3-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
-    ofport-request=1
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ls1_ro_mac=00:00:00:01:02:f1
-ls1_ro_ip=192.168.1.1
-
-ls2_ro_mac=00:00:00:01:02:f2
-ls2_ro_ip=172.16.1.1
-
-ls3_ro_mac=00:00:00:01:02:f3
-
-ls1_p1_mac=00:00:00:01:02:03
-ls1_p1_ip=192.168.1.2
-
-ls2_p1_mac=00:00:00:01:02:04
-ls2_p1_ip=172.16.1.2
-
-ls3_p1_mac=00:00:00:01:02:05
-
-# Create a drop policy
-ovn-nbctl lr-policy-add R1 10 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" drop
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl
-1
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Check if packet hit the drop policy
-AT_CHECK([ovs-ofctl dump-flows br-int | \
-    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24 actions=drop" | \
-    grep "priority=10" | \
-    grep "n_packets=1" | wc -l], [0], [dnl
-1
-])
-
-# Expected to drop the packet.
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets
-rcvd_packet=`cat vif2.packets`
-AT_FAIL_IF([rcvd_packet = ""])
-
-# Override drop policy with allow
-ovn-nbctl lr-policy-add R1 20 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" allow
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "192.168.1.0" | wc -l], [0], [dnl
-2
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Check if packet hit the allow policy
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
-    grep "192.168.1.0" | \
-    grep "priority=20" | wc -l], [0], [dnl
-1
-])
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
-       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > expected
-
-OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
-
-# Override allow policy with reroute
-ovn-nbctl lr-policy-add R1 30 "ip4.src==192.168.1.0/24 && ip4.dst==172.16.1.0/24" reroute 20.20.1.2
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
-    grep "192.168.1.0" | \
-    grep "priority=30" | wc -l], [0], [dnl
-1
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip4 && ip.ttl==64 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-echo "southbound flows"
-
-ovn-sbctl dump-flows | grep lr_in_policy
-echo "ovs flows"
-ovs-ofctl dump-flows br-int
-# Check if packet hit the allow policy
-AT_CHECK([ovs-ofctl dump-flows br-int | \
-    grep "nw_src=192.168.1.0/24,nw_dst=172.16.1.0/24" | \
-    grep "priority=30" | \
-    grep "n_packets=1" | wc -l], [0], [dnl
-1
-])
-echo "packet hit reroute policy"
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
-       ip4 && ip.ttl==63 && ip4.src==$ls1_p1_ip && ip4.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > 3.expected
-
-OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
-
-OVN_CLEANUP([pbr-hv])
-AT_CLEANUP
-
-AT_SETUP([ovn -- policy-based routing IPv6: 1 HVs, 3 LSs, 1 lport/LS, 1 LR])
-AT_KEYWORDS([policy-based-routing])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR - R1 has switch ls1 (191.168.1.0/24) connected to it,
-# and has switch ls2 (172.16.1.0/24) connected to it.
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-ovn-nbctl ls-add ls3
-
-# Connect ls1 to R1
-ovn-nbctl lrp-add R1 ls1 00:00:00:01:02:f1 2001::1/64
-ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \
-    type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\"
-
-# Connect ls2 to R1
-ovn-nbctl lrp-add R1 ls2 00:00:00:01:02:f2 2002::1/64
-ovn-nbctl lsp-add ls2 rp-ls2 -- set Logical_Switch_Port rp-ls2 \
-    type=router options:router-port=ls2 addresses=\"00:00:00:01:02:f2\"
-
-# Connect ls3 to R1
-ovn-nbctl lrp-add R1 ls3 00:00:00:01:02:f3 2003::1/64
-ovn-nbctl lsp-add ls3 rp-ls3 -- set Logical_Switch_Port rp-ls3 \
-    type=router options:router-port=ls3 addresses=\"00:00:00:01:02:f3\"
-
-# Create logical port ls1-lp1 in ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 2001::2"
-
-# Create logical port ls2-lp1 in ls2
-ovn-nbctl lsp-add ls2 ls2-lp1 \
--- lsp-set-addresses ls2-lp1 "00:00:00:01:02:04 2002::2"
-
-# Create logical port ls3-lp1 in ls3
-ovn-nbctl lsp-add ls3 ls3-lp1 \
--- lsp-set-addresses ls3-lp1 "00:00:00:01:02:05 2003::2"
-
-# Create one hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add pbr-hv
-as pbr-hv
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-
-ovs-vsctl -- add-port br-int vif1 -- \
-    set interface vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=pbr-hv/vif1-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif2 -- \
-    set interface vif2 external-ids:iface-id=ls2-lp1 \
-    options:tx_pcap=pbr-hv/vif2-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif2-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int vif3 -- \
-    set interface vif3 external-ids:iface-id=ls3-lp1 \
-    options:tx_pcap=pbr-hv/vif3-tx.pcap \
-    options:rxq_pcap=pbr-hv/vif3-rx.pcap \
-    ofport-request=1
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ls1_ro_mac=00:00:00:01:02:f1
-ls1_ro_ip=2001::1
-
-ls2_ro_mac=00:00:00:01:02:f2
-ls2_ro_ip=2002::1
-
-ls3_ro_mac=00:00:00:01:02:f3
-
-ls1_p1_mac=00:00:00:01:02:03
-ls1_p1_ip=2001::2
-
-ls2_p1_mac=00:00:00:01:02:04
-ls2_p1_ip=2002::2
-
-ls3_p1_mac=00:00:00:01:02:05
-
-# Create a drop policy
-ovn-nbctl lr-policy-add R1 10 "ip6.src==2001::/64 && ip6.dst==2002::/64" drop
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc -l], [0], [dnl
-1
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Check if packet hit the drop policy
-AT_CHECK([ovs-ofctl dump-flows br-int | \
-    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64 actions=drop" | \
-    grep "priority=10" | \
-    grep "n_packets=1" | wc -l], [0], [dnl
-1
-])
-
-# Expected to drop the packet.
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" pbr-hv/vif2-tx.pcap > vif2.packets
-rcvd_packet=`cat vif2.packets`
-AT_FAIL_IF([rcvd_packet = ""])
-
-# Override drop policy with allow
-ovn-nbctl lr-policy-add R1 20 "ip6.src==2001::/64 && ip6.dst==2002::/64" allow
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | grep "2001" | wc -l], [0], [dnl
-2
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Check if packet hit the allow policy
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
-    grep "2001" | \
-    grep "priority=20" | wc -l], [0], [dnl
-1
-])
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$ls2_ro_mac && eth.dst==$ls2_p1_mac &&
-       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > expected
-
-OVN_CHECK_PACKETS([pbr-hv/vif2-tx.pcap], [expected])
-
-# Override allow policy with reroute
-ovn-nbctl lr-policy-add R1 30 "ip6.src==2001::/64 && ip6.dst==2002::/64" reroute 2003::2
-
-# Check logical flow
-AT_CHECK([ovn-sbctl dump-flows | grep lr_in_policy | \
-    grep "2001" | \
-    grep "priority=30" | wc -l], [0], [dnl
-1
-])
-
-# Send packet.
-packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$ls1_ro_mac &&
-       ip6 && ip.ttl==64 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-as pbr-hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-echo "southbound flows"
-
-ovn-sbctl dump-flows | grep lr_in_policy
-echo "ovs flows"
-ovs-ofctl dump-flows br-int
-# Check if packet hit the allow policy
-AT_CHECK([ovs-ofctl dump-flows br-int | \
-    grep "ipv6_src=2001::/64,ipv6_dst=2002::/64" | \
-    grep "priority=30" | \
-    grep "n_packets=1" | wc -l], [0], [dnl
-1
-])
-echo "packet hit reroute policy"
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$ls3_ro_mac && eth.dst==$ls3_p1_mac &&
-       ip6 && ip.ttl==63 && ip6.src==$ls1_p1_ip && ip6.dst==$ls2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > 3.expected
-
-OVN_CHECK_PACKETS([pbr-hv/vif3-tx.pcap], [3.expected])
-
-OVN_CLEANUP([pbr-hv])
-AT_CLEANUP
-
-# 1 hypervisor, 1 port
-# make sure that the port state is properly set to up and back down
-# when created and deleted.
-AT_SETUP([ovn -- port state up and down])
-ovn_start
-
-ovn-nbctl ls-add ls1
-ovn-nbctl lsp-add ls1 lp1
-ovn-nbctl lsp-set-addresses lp1 unknown
-
-net_add n1
-sim_add hv1
-as hv1 ovs-vsctl add-br br-phys
-as hv1 ovn_attach n1 br-phys 192.168.0.1
-
-as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
-
-as hv1 ovs-vsctl del-port br-int vif1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-# 1 hypervisor, 1 port
-# make sure that the OF rules created to support a datapath are added/cleared
-# when logical switch is created and removed.
-AT_SETUP([ovn -- datapath rules added/removed])
-AT_KEYWORDS([cleanup])
-ovn_start
-
-net_add n1
-sim_add hv1
-as hv1 ovs-vsctl add-br br-phys
-as hv1 ovn_attach n1 br-phys 192.168.0.1
-
-# This shell function checks if OF rules in br-int have clauses
-# related to OVN datapaths. The caller determines if it should find
-# a match in the output, or not.
-#
-# EXPECT_DATAPATH param determines whether flows that refer to
-#                 datapath to should be present or not. 0 means
-#                 they should not be.
-# STAGE_INFO param is a simple string to help identify the stage
-#            in the test when this function was invoked.
-test_datapath_in_of_rules() {
-    local expect_datapath=$1 stage_info=$2
-    echo "------ ovn-nbctl show ${stage_info} ------"
-    ovn-nbctl show
-    echo "------ ovn-sbctl show ${stage_info} ------"
-    ovn-sbctl show
-    echo "------ OF rules ${stage_info} ------"
-    AT_CHECK([ovs-ofctl dump-flows br-int], [0], [stdout])
-    # if there is a datapath mentioned in the output, check for the
-    # magic keyword that represents one, based on the exit status of
-    # a quiet grep
-    if test $expect_datapath != 0; then
-       AT_CHECK([grep -q -i 'metadata=' stdout], [0], [ignore-nolog])
-    else
-       AT_CHECK([grep -q -i 'metadata=' stdout], [1], [ignore-nolog])
-    fi
-}
-
-test_datapath_in_of_rules 0 "before ls+port create"
-
-ovn-nbctl ls-add ls1
-ovn-nbctl lsp-add ls1 lp1
-ovn-nbctl lsp-set-addresses lp1 unknown
-
-as hv1 ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
-
-test_datapath_in_of_rules 1 "after port is bound"
-
-as hv1 ovs-vsctl del-port br-int vif1
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xdown])
-
-ovn-nbctl lsp-set-addresses lp1
-ovn-nbctl lsp-del lp1
-ovn-nbctl ls-del ls1
-
-# wait for earlier changes to take effect
-AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
-
-# ensure OF rules are no longer present. There used to be a bug here.
-test_datapath_in_of_rules 0 "after lport+ls removal"
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- nd_na ])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-#TODO: since patch port for IPv6 logical router port is not ready not,
-#  so we are not going to test vifs on different lswitches cases. Try
-#  to update for that once relevant stuff implemented.
-
-# In this test cases we create 1 lswitch, it has 2 VIF ports attached
-# with. NS packet we test, from one VIF for another VIF, will be replied
-# by local ovn-controller, but not by target VIF.
-
-# Create hypervisors and logical switch lsw0.
-ovn-nbctl ls-add lsw0
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-# Add vif1 to hv1 and lsw0, turn on l2 port security on vif1.
-ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=hv1/vif1-tx.pcap options:rxq_pcap=hv1/vif1-rx.pcap ofport-request=1
-ovn-nbctl lsp-add lsw0 lp1
-ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
-ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:94:05:98 192.168.0.3 fd81:ce49:a948:0:f816:3eff:fe94:598"
-
-# Add vif2 to hv1 and lsw0, turn on l2 port security on vif2.
-ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=hv1/vif2-tx.pcap options:rxq_pcap=hv1/vif2-rx.pcap ofport-request=2
-ovn-nbctl lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
-ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:a1:f9:ae 192.168.0.4 fd81:ce49:a948:0:f816:3eff:fea1:f9ae"
-
-# Add ACL rule for ICMPv6 on lsw0
-ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'  allow-related
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv1${1%?}
-}
-for i in 1 2; do
-    : > $i.expected
-done
-
-# Complete Neighbor Solicitation packet and Neighbor Advertisement packet
-# vif1 -> NS -> vif2.  vif1 <- NA <- ovn-controller.
-# vif2 will not receive NS packet, since ovn-controller will reply for it.
-ns_packet=3333ffa1f9aefa163e94059886dd6000000000203afffd81ce49a9480000f8163efffe940598fd81ce49a9480000f8163efffea1f9ae8700e01160000000fd81ce49a9480000f8163efffea1f9ae0101fa163e940598
-na_packet=fa163e940598fa163ea1f9ae86dd6000000000203afffd81ce49a9480000f8163efffea1f9aefd81ce49a9480000f8163efffe9405988800e9ed60000000fd81ce49a9480000f8163efffea1f9ae0201fa163ea1f9ae
-
-as hv1 ovs-appctl netdev-dummy/receive vif1 $ns_packet
-echo $na_packet >> 1.expected
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-ofctl -O OpenFlow13 show br-int
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-
-for i in 1 2; do
-    OVN_CHECK_PACKETS([hv1/vif$i-tx.pcap], [$i.expected])
-done
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- address sets modification/removal smoke test])
-ovn_start
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-
-row=`ovn-nbctl create Address_Set name=set1 addresses=\"1.1.1.1\"`
-ovn-nbctl set Address_Set $row name=set1 addresses=\"1.1.1.1,1.1.1.2\"
-ovn-nbctl destroy Address_Set $row
-
-sleep 1
-
-# A bug previously existed in the address set support code
-# that caused ovn-controller to crash after an address set
-# was updated and then removed.  This test case ensures
-# that ovn-controller is at least still running after
-# creating, updating, and deleting an address set.
-AT_CHECK([ovs-appctl -t ovn-controller version], [0], [ignore])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ipam])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Add a port to a switch that does not have a subnet set, then set the
-# subnet which should result in an address being allocated for the port.
-ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
-ovn-nbctl ls-add sw0
-ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
-ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=192.168.1.0/24
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:03 192.168.1.2"
-])
-
-# Add 9 more ports to sw0, addresses should all be unique.
-for n in `seq 1 9`; do
-    ovn-nbctl --wait=sb lsp-add sw0 "p$n" -- lsp-set-addresses "p$n" dynamic
-done
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p1 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:04 192.168.1.3"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p2 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:05 192.168.1.4"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p3 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:06 192.168.1.5"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p4 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:07 192.168.1.6"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p5 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:08 192.168.1.7"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p6 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:09 192.168.1.8"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p7 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:0a 192.168.1.9"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p8 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:0b 192.168.1.10"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p9 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:0c 192.168.1.11"
-])
-
-# Trying similar tests with a second switch. MAC addresses should be unique
-# across both switches but IP's only need to be unique within the same switch.
-ovn-nbctl ls-add sw1
-ovn-nbctl lsp-add sw1 p10 -- lsp-set-addresses p10 dynamic
-ovn-nbctl --wait=sb add Logical-Switch sw1 other_config subnet=192.168.1.0/24
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p10 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:0d 192.168.1.2"
-])
-
-for n in `seq 11 19`; do
-    ovn-nbctl --wait=sb lsp-add sw1 "p$n" -- lsp-set-addresses "p$n" dynamic
-done
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p11 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:0e 192.168.1.3"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p12 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:0f 192.168.1.4"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p13 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:10 192.168.1.5"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p14 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:11 192.168.1.6"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p15 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:12 192.168.1.7"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p16 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:13 192.168.1.8"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p17 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:14 192.168.1.9"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p18 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:15 192.168.1.10"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p19 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:16 192.168.1.11"
-])
-
-# Change a port's address to test for multiple ip's for a single address entry
-# and addresses set by the user.
-ovn-nbctl lsp-set-addresses p0 "0a:00:00:a8:01:17 192.168.1.2 192.168.1.12 192.168.1.14"
-ovn-nbctl --wait=sb lsp-add sw0 p20 -- lsp-set-addresses p20 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p20 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:18 192.168.1.13"
-])
-
-# Test for logical router port address management.
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw0 \
-network="192.168.1.1/24" mac=\"0a:00:00:a8:01:19\" \
--- add Logical_Router R1 ports @lrp -- lsp-add sw0 rp-sw0 \
--- set Logical_Switch_Port rp-sw0 type=router options:router-port=sw0
-ovn-nbctl --wait=sb lsp-add sw0 p21 -- lsp-set-addresses p21 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p21 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:1a 192.168.1.15"
-])
-
-# Test for address reuse after logical port is deleted.
-ovn-nbctl lsp-del p0
-ovn-nbctl --wait=sb lsp-add sw0 p23 -- lsp-set-addresses p23 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p23 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:03 192.168.1.2"
-])
-
-# Test for multiple addresses to one logical port.
-ovn-nbctl lsp-add sw0 p25 -- lsp-set-addresses p25 \
-"0a:00:00:a8:01:1b 192.168.1.12" "0a:00:00:a8:01:1c 192.168.1.14"
-ovn-nbctl --wait=sb lsp-add sw0 p26 -- lsp-set-addresses p26 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p26 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:17 192.168.1.16"
-])
-
-# Test for exhausting subnet address space.
-ovn-nbctl ls-add sw2 -- add Logical-Switch sw2 other_config subnet=172.16.1.0/30
-ovn-nbctl --wait=sb lsp-add sw2 p27 -- lsp-set-addresses p27 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p27 dynamic_addresses], [0],
-     ["0a:00:00:10:01:03 172.16.1.2"
-])
-
-ovn-nbctl --wait=sb lsp-add sw2 p28 -- lsp-set-addresses p28 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p28 dynamic_addresses], [0],
-     ["0a:00:00:00:00:01"
-])
-
-# Test that address management does not add duplicate MAC for lsp/lrp peers.
-ovn-nbctl create Logical_Router name=R2
-ovn-nbctl ls-add sw3
-ovn-nbctl lsp-add sw3 p29 -- lsp-set-addresses p29 \
-"0a:00:00:a8:01:18"
-ovn-nbctl -- --id=@lrp create Logical_Router_port name=sw3 \
-network="192.168.2.1/24" mac=\"0a:00:00:a8:01:18\" \
--- add Logical_Router R2 ports @lrp -- lsp-add sw3 rp-sw3 \
--- set Logical_Switch_Port rp-sw3 type=router options:router-port=sw3
-ovn-nbctl --wait=sb lsp-add sw0 p30 -- lsp-set-addresses p30 dynamic
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p30 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:1d 192.168.1.17"
-])
-
-# Test static MAC address with dynamically allocated IP
-ovn-nbctl --wait=sb lsp-add sw0 p31 -- lsp-set-addresses p31 \
-"fe:dc:ba:98:76:54 dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
-     ["fe:dc:ba:98:76:54 192.168.1.18"
-])
-
-# Update the static MAC address with dynamically allocated IP and check
-# if the MAC address is updated in 'Logical_Switch_Port.dynamic_adddresses'
-ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:55 dynamic"
-
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
-     ["fe:dc:ba:98:76:55 192.168.1.18"
-])
-
-ovn-nbctl --wait=sb lsp-set-addresses p31 "dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:1e 192.168.1.18"
-])
-
-ovn-nbctl --wait=sb lsp-set-addresses p31 "fe:dc:ba:98:76:56 dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p31 dynamic_addresses], [0],
-     ["fe:dc:ba:98:76:56 192.168.1.18"
-])
-
-
-# Test the exclude_ips from the IPAM list
-ovn-nbctl --wait=sb set logical_switch sw0 \
-other_config:exclude_ips="192.168.1.19 192.168.1.21 192.168.1.23..192.168.1.50"
-
-ovn-nbctl --wait=sb lsp-add sw0 p32 -- lsp-set-addresses p32 \
-"dynamic"
-# 192.168.1.20 should be assigned as 192.168.1.19 is excluded.
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p32 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:1e 192.168.1.20"
-])
-
-ovn-nbctl --wait=sb lsp-add sw0 p33 -- lsp-set-addresses p33 \
-"dynamic"
-# 192.168.1.22 should be assigned as 192.168.1.21 is excluded.
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p33 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:1f 192.168.1.22"
-])
-
-ovn-nbctl --wait=sb lsp-add sw0 p34 -- lsp-set-addresses p34 \
-"dynamic"
-# 192.168.1.51 should be assigned as 192.168.1.23-192.168.1.50 is excluded.
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p34 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:34 192.168.1.51"
-])
-
-# Now clear the exclude_ips list. 192.168.1.19 should be assigned.
-ovn-nbctl --wait=sb set Logical-switch sw0 other_config:exclude_ips="invalid"
-ovn-nbctl --wait=sb lsp-add sw0 p35 -- lsp-set-addresses p35 \
-"dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p35 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:20 192.168.1.19"
-])
-
-# Set invalid data in exclude_ips list. It should be ignored.
-ovn-nbctl --wait=sb set Logical-switch sw0 other_config:exclude_ips="182.168.1.30"
-ovn-nbctl --wait=sb lsp-add sw0 p36 -- lsp-set-addresses p36 \
-"dynamic"
-# 192.168.1.21 should be assigned as that's the next free one.
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:21 192.168.1.21"
-])
-
-# Clear the dynamic addresses assignment request.
-ovn-nbctl --wait=sb clear logical_switch_port p36 addresses
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p36 dynamic_addresses], [0],
-         [[[]]
-])
-
-# Set IPv6 prefix
-ovn-nbctl --wait=sb set Logical-switch sw0 other_config:ipv6_prefix="aef0::"
-ovn-nbctl --wait=sb lsp-add sw0 p37 -- lsp-set-addresses p37 \
-"dynamic"
-
-# With prefix aef0 and mac 0a:00:00:00:00:26, the dynamic IPv6 should be
-# - aef0::800:ff:fe00:26 (EUI64)
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p37 dynamic_addresses], [0],
-     ["0a:00:00:a8:01:21 192.168.1.21 aef0::800:ff:fea8:121"
-])
-
-ovn-nbctl --wait=sb ls-add sw4
-ovn-nbctl --wait=sb set Logical-switch sw4 other_config:ipv6_prefix="bef0::" \
--- set Logical-switch sw4 other_config:subnet=192.168.2.0/30
-ovn-nbctl --wait=sb lsp-add sw4 p38 -- lsp-set-addresses p38 \
-"dynamic"
-
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p38 dynamic_addresses], [0],
-     ["0a:00:00:a8:02:03 192.168.2.2 bef0::800:ff:fea8:203"
-])
-
-ovn-nbctl --wait=sb lsp-add sw4 p39 -- lsp-set-addresses p39 \
-"f0:00:00:00:10:12 dynamic"
-
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p39 dynamic_addresses], [0],
-     ["f0:00:00:00:10:12 bef0::f200:ff:fe00:1012"
-])
-
-# Test the case where IPv4 addresses are exhausted and IPv6 prefix is set
-# p40 should not have an IPv4 address since the pool is exhausted
-ovn-nbctl --wait=sb lsp-add sw4 p40 -- lsp-set-addresses p40 \
-"dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p40 dynamic_addresses], [0],
-         ["0a:00:00:00:00:02 bef0::800:ff:fe00:2"
-])
-
-# Test dynamic changes on switch ports.
-#
-ovn-nbctl --wait=sb ls-add sw5
-ovn-nbctl --wait=sb lsp-add sw5 p41 -- lsp-set-addresses p41 \
-"dynamic"
-# p41 will start with nothing
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         [[[]]
-])
-
-# Set a subnet. Now p41 should have an ipv4 address, too
-ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=192.168.1.0/24
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["0a:00:00:a8:01:22 192.168.1.2"
-])
-
-# Clear the other_config. The IPv4 address should be gone
-ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         [[[]]
-])
-
-# Set an IPv6 prefix. Now p41 should have an IPv6 address.
-ovn-nbctl --wait=sb set Logical-Switch sw5 other_config:ipv6_prefix="aef0::"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["0a:00:00:00:00:03 aef0::800:ff:fe00:3"
-])
-
-# Change the MAC address to a static one. The IPv6 address should update.
-ovn-nbctl --wait=sb lsp-set-addresses p41 "f0:00:00:00:10:2b dynamic"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["f0:00:00:00:10:2b aef0::f200:ff:fe00:102b"
-])
-
-# Change the IPv6 prefix. The IPv6 address should update.
-ovn-nbctl --wait=sb set Logical-Switch sw5 other_config:ipv6_prefix="bef0::"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["f0:00:00:00:10:2b bef0::f200:ff:fe00:102b"
-])
-
-# Clear the other_config. The IPv6 address should be gone
-ovn-nbctl --wait=sb clear Logical-Switch sw5 other_config
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         [[[]]
-])
-
-# Set the subnet again. Now p41 should get the IPv4 address again.
-ovn-nbctl --wait=sb add Logical-Switch sw5 other_config subnet=192.168.1.0/24
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["f0:00:00:00:10:2b 192.168.1.2"
-])
-
-# Add an excluded IP address that conflicts with p41. p41 should update.
-ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \
-exclude_ips="192.168.1.2"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["f0:00:00:00:10:2b 192.168.1.3"
-])
-
-# Add static ip address
-ovn-nbctl --wait=sb lsp-set-addresses p41 "dynamic 192.168.1.100"
-ovn-nbctl list Logical-Switch-Port p41
-ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \
-"dynamic 192.168.1.101"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0],
-         ["0a:00:00:a8:01:65 192.168.1.100"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p42 dynamic_addresses], [0],
-         ["0a:00:00:a8:01:66 192.168.1.101"
-])
-
-# define a mac address prefix
-ovn-nbctl ls-add sw6
-ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22:33:44:55"
-ovn-nbctl --wait=sb set Logical-Switch sw6 other_config:subnet=192.168.100.0/24
-for n in $(seq 1 3); do
-    ovn-nbctl --wait=sb lsp-add sw6 "p5$n" -- lsp-set-addresses "p5$n" dynamic
-done
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p51 dynamic_addresses], [0],
-    ["00:11:22:a8:64:03 192.168.100.2"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p52 dynamic_addresses], [0],
-    ["00:11:22:a8:64:04 192.168.100.3"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p53 dynamic_addresses], [0],
-    ["00:11:22:a8:64:05 192.168.100.4"
-])
-
-# verify configuration order does not break IPAM/MACAM
-ovn-nbctl ls-add sw7
-for n in $(seq 1 3); do
-    ovn-nbctl --wait=sb lsp-add sw7 "p7$n" -- lsp-set-addresses "p7$n" dynamic
-done
-ovn-nbctl --wait=sb set Logical-Switch sw7 other_config:ipv6_prefix="bef0::"
-p71_addr=$(ovn-nbctl get Logical-Switch-Port p71 dynamic_addresses)
-p72_addr=$(ovn-nbctl get Logical-Switch-Port p72 dynamic_addresses)
-p73_addr=$(ovn-nbctl get Logical-Switch-Port p73 dynamic_addresses)
-AT_CHECK([test "$p71_addr" != "$p72_addr"], [0], [])
-AT_CHECK([test "$p71_addr" != "$p73_addr"], [0], [])
-AT_CHECK([test "$p72_addr" != "$p73_addr"], [0], [])
-
-# request to assign mac only
-#
-ovn-nbctl ls-add sw8
-ovn-nbctl --wait=sb set Logical-Switch sw8 other_config:mac_only=true
-for n in $(seq 1 3); do
-    ovn-nbctl --wait=sb lsp-add sw8 "p8$n" -- lsp-set-addresses "p8$n" dynamic
-done
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p81 dynamic_addresses], [0],
-    ["00:11:22:00:00:06"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p82 dynamic_addresses], [0],
-    ["00:11:22:00:00:07"
-])
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p83 dynamic_addresses], [0],
-    ["00:11:22:00:00:08"
-])
-
-# clear mac_prefix and check it is allocated in a random manner
-ovn-nbctl --wait=hv remove NB_Global . options mac_prefix
-ovn-nbctl ls-add sw9
-ovn-nbctl --wait=sb set Logical-Switch sw9 other_config:mac_only=true
-ovn-nbctl --wait=sb lsp-add sw9 p91 -- lsp-set-addresses p91 dynamic
-
-mac_prefix=$(ovn-nbctl --wait=sb get NB_Global . options:mac_prefix | tr -d \")
-port_addr=$(ovn-nbctl get Logical-Switch-Port p91 dynamic_addresses | tr -d \")
-AT_CHECK([test "$port_addr" = "${mac_prefix}:00:00:09"], [0], [])
-
-ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="00:11:22"
-ovn-nbctl ls-add sw10
-ovn-nbctl --wait=sb set Logical-Switch sw10 other_config:ipv6_prefix="ae01::"
-ovn-nbctl --wait=sb lsp-add sw10 p101 -- lsp-set-addresses p101 "dynamic ae01::1"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p101 dynamic_addresses], [0],
-    ["00:11:22:00:00:0a ae01::1"
-])
-
-ovn-nbctl --wait=sb set Logical-Switch sw10 other_config:subnet=192.168.110.0/24
-ovn-nbctl --wait=sb lsp-add sw10 p102 -- lsp-set-addresses p102 "dynamic 192.168.110.10 ae01::2"
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p102 dynamic_addresses], [0],
-    ["00:11:22:a8:6e:0b 192.168.110.10 ae01::2"
-])
-
-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 northd-backup
-OVS_APP_EXIT_AND_WAIT([ovn-northd])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ipam connectivity])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl lr-add R1
-
-# Test for a ping using dynamically allocated addresses.
-ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
-ovn-nbctl ls-add foo -- add Logical_Switch foo other_config subnet=192.168.1.0/24
-ovn-nbctl ls-add alice -- add Logical_Switch alice other_config subnet=192.168.2.0/24
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-          options:router-port=foo \
-          -- lsp-set-addresses rp-foo router
-
-# Connect alice to R1
-ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice type=router \
-          options:router-port=alice addresses=\"00:00:00:01:02:04\"
-
-# Create logical port foo1 in foo
-ovn-nbctl --wait=sb lsp-add foo foo1 \
--- lsp-set-addresses foo1 "dynamic"
-AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo1 dynamic_addresses='"0a:00:00:a8:01:03 192.168.1.2"'], [0])
-
-# Create logical port alice1 in alice
-ovn-nbctl --wait=sb lsp-add alice alice1 \
--- lsp-set-addresses alice1 "dynamic"
-AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port alice1 dynamic_addresses='"0a:00:00:a8:02:03 192.168.2.2"'])
-
-# Create logical port foo2 in foo
-ovn-nbctl --wait=sb lsp-add foo foo2 \
--- lsp-set-addresses foo2 "dynamic"
-AT_CHECK([ovn-nbctl --timeout=10 wait-until Logical-Switch-Port foo2 dynamic_addresses='"0a:00:00:a8:01:04 192.168.1.3"'])
-
-# Create a hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=foo2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-ovs-vsctl -- add-port br-int hv1-vif3 -- \
-    set interface hv1-vif3 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv1/vif3-tx.pcap \
-    options:rxq_pcap=hv1/vif3-rx.pcap \
-    ofport-request=3
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and foo2
-src_mac="0a0000a80103"
-dst_mac="0a0000a80104"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 1 3`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-# Send ip packets between foo1 and alice1
-src_mac="0a0000a80103"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-
-# Packet to Expect at foo2
-src_mac="0a0000a80103"
-dst_mac="0a0000a80104"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 1 3`
-expected=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > received1.packets
-echo $expected > expout
-AT_CHECK([cat received1.packets], [0], [expout])
-
-# Packet to Expect at alice1
-src_mac="000000010204"
-dst_mac="0a0000a80203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap > received2.packets
-echo $expected > expout
-AT_CHECK([cat received2.packets], [0], [expout])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ovs-vswitchd restart])
-AT_KEYWORDS([vswitchd])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-net_add n1
-sim_add hv1
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-OVN_POPULATE_ARP
-sleep 2
-
-as hv1 ovs-vsctl show
-
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl dump-flows br-int
-total_flows=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
-
-echo "Total flows before vswitchd restart = " $total_flows
-
-# Code taken from ovs-save utility
-save_flows () {
-    echo "ovs-ofctl add-flows br-int - << EOF" > restore_flows.sh
-    as hv1 ovs-ofctl dump-flows "br-int" | sed -e '/NXST_FLOW/d' \
-            -e 's/\(idle\|hard\)_age=[^,]*,//g' >> restore_flows.sh
-    echo "EOF" >> restore_flows.sh
-}
-
-restart_vswitchd () {
-    restore_flows=$1
-
-    if test $restore_flows = true; then
-        save_flows
-    fi
-
-    as hv1
-    OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
-
-    if test $restore_flows = true; then
-        as hv1
-        ovs-vsctl --no-wait set open_vswitch . other_config:flow-restore-wait="true"
-    fi
-
-    as hv1
-    start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl
-    ovs-ofctl dump-flows br-int
-
-    if test $restore_flows = true; then
-        sh ./restore_flows.sh
-        echo "Flows after restore"
-        as hv1
-        ovs-ofctl dump-flows br-int
-        ovs-vsctl --no-wait --if-exists remove open_vswitch . other_config \
-            flow-restore-wait="true"
-    fi
-}
-
-# Save the flows, restart vswitchd and restore the flows
-restart_vswitchd true
-OVS_WAIT_UNTIL([
-    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
-    echo "Total flows after vswitchd restart = " $total_flows_after_restart
-    test "${total_flows}" = "${total_flows_after_restart}"
-])
-
-# Restart vswitchd without restoring
-restart_vswitchd false
-OVS_WAIT_UNTIL([
-    total_flows_after_restart=`as hv1 ovs-ofctl dump-flows br-int | wc -l`
-    echo "Total flows after vswitchd restart = " $total_flows_after_restart
-    test "${total_flows}" = "${total_flows_after_restart}"
-])
-
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- send arp for nexthop])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Topology: Two LSs - ls1 and ls2 are connected via router r0
-
-# Create logical switches
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-
-# Create  router
-ovn-nbctl create Logical_Router name=lr0
-
-# Add router ls1p1 port to gateway router
-ovn-nbctl lrp-add lr0 lrp-ls1lp1 f0:00:00:00:00:01 192.168.0.1/24
-ovn-nbctl lsp-add ls1 ls1lp1 -- set Logical_Switch_Port ls1lp1  \
-    type=router options:router-port=lrp-ls1lp1 \
-    addresses='"f0:00:00:00:00:01 192.168.0.1"'
-
-# Add router ls2p2 port to gateway router
-ovn-nbctl lrp-add lr0 lrp-ls2lp1 f0:00:00:00:00:02 192.168.1.1/24
-ovn-nbctl lsp-add ls2 ls2lp1 -- set Logical_Switch_Port ls2lp1 \
-    type=router options:router-port=lrp-ls2lp1 \
-    addresses='"f0:00:00:00:00:02 192.168.1.1"'
-
-# Set default gateway (nexthop) to 192.168.1.254
-ovn-nbctl lr-route-add lr0 "0.0.0.0/0" 192.168.1.254 lrp-ls2lp1
-
-# Create logical port ls1lp2 in ls1
-ovn-nbctl lsp-add ls1 ls1lp2 \
--- lsp-set-addresses ls1lp2 "f0:00:00:00:00:03 192.168.0.2"
-
-# Create logical port ls2lp2 in ls2
-ovn-nbctl lsp-add ls2 ls2lp2 \
--- lsp-set-addresses ls2lp2 "f0:00:00:00:00:04 192.168.1.10"
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-ls1lp2 -- \
-    set interface hv1-ls1lp2 external-ids:iface-id=ls1lp2 \
-    options:tx_pcap=hv1/ls1lp2-tx.pcap \
-    options:rxq_pcap=hv1/ls1lp2-rx.pcap \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv1-ls2lp2 -- \
-    set interface hv1-ls2lp2 external-ids:iface-id=ls2lp2 \
-    options:tx_pcap=hv1/ls2lp2-tx.pcap \
-    options:rxq_pcap=hv1/ls2lp2-rx.pcap \
-    ofport-request=2
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-ovn-sbctl list chassis
-ovn-sbctl list encap
-echo "---------------------"
-
-echo "------Flows dump-----"
-as hv1
-ovs-ofctl dump-flows
-echo "---------------------"
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-src_mac="f00000000003"
-dst_mac="f00000000001"
-src_ip=`ip_to_hex 192 168 0 2`
-dst_ip=`ip_to_hex 8 8 8 8`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-# Send IP packet destined to 8.8.8.8 from lsp1lp2
-as hv1 ovs-appctl netdev-dummy/receive hv1-ls1lp2 $packet
-
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-# ARP packet should be received with Target IP Address set to 192.168.1.254 and
-# not 8.8.8.8
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ls2lp2-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000208060001080006040001f00000000002c0a80101000000000000c0a801fe"
-echo $expected > expout
-AT_CHECK([cat packets], [0], [expout])
-cat packets
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- send gratuitous arp for nat ips in localnet])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-# Create logical switch
-ovn-nbctl ls-add ls0
-# Create gateway router
-ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
-# Add router port to gateway router
-ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
-ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
-    type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
-# Add nat-address option
-ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="f0:00:00:00:00:01 192.168.0.2"
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0
-
-ovn_attach n1 br-phys 192.168.0.1
-
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
-AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
-
-# Wait until the patch ports are created in hv1 to connect br-int to br-eth0
-OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | \
-grep "Port patch-br-int-to-ln_port" | wc -l`])
-
-# Wait for packet to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
-echo $expected > expout
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
-echo $expected >> expout
-AT_CHECK([sort packets], [0], [expout])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- send gratuitous arp with nat-addresses router in localnet])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-# Create logical switch
-ovn-nbctl ls-add ls0
-# Create gateway router
-ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
-# Add router port to gateway router
-ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24
-ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
-    type=router options:router-port=lrp0 addresses='"f0:00:00:00:00:01"'
-# Add nat-address option
-ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
-# Add NAT rules
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.1])
-# Add load balancers
-AT_CHECK([ovn-nbctl lb-add lb0 192.168.0.3:80 10.0.0.2:80,10.0.0.3:80])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb0])
-AT_CHECK([ovn-nbctl lb-add lb1 192.168.0.3:8080 10.0.0.2:8080,10.0.0.3:8080])
-AT_CHECK([ovn-nbctl lr-lb-add lr0 lb1])
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl \
-    -- add-br br-phys \
-    -- add-br br-eth0
-
-ovn_attach n1 br-phys 192.168.0.1
-
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
-AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
-
-# Wait until the patch ports are created to connect br-int to br-eth0
-OVS_WAIT_UNTIL([test 1 = `ovs-vsctl show | \
-grep "Port patch-br-int-to-ln_port" | wc -l`])
-
-ovn-sbctl list port_binding lrp0-rp
-echo "*****"
-ovn-nbctl list logical_switch_port lrp0-rp
-ovn-nbctl list logical_router_port lrp0
-ovn-nbctl show
-# Wait for packet to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 50])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
-echo $expected > expout
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
-echo $expected >> expout
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80003000000000000c0a80003"
-echo $expected >> expout
-AT_CHECK([sort packets], [0], [expout])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- delete mac bindings])
-ovn_start
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl -- add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-# Create logical switch ls0
-ovn-nbctl ls-add ls0
-# Create ports lp0, lp1 in ls0
-ovn-nbctl lsp-add ls0 lp0
-ovn-nbctl lsp-add ls0 lp1
-ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1"
-ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2"
-dp_uuid=`ovn-sbctl find datapath | grep uuid | cut -f2 -d ":" | cut -f2 -d " "`
-ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp0 mac="mac1"
-ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp1 mac="mac2"
-ovn-sbctl find MAC_Binding
-# Delete port lp0 and check that its MAC_Binding is deleted.
-ovn-nbctl lsp-del lp0
-ovn-sbctl find MAC_Binding
-OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding logical_port=lp0 | wc -l` = 0])
-# Delete logical switch ls0 and check that its MAC_Binding is deleted.
-ovn-nbctl ls-del ls0
-ovn-sbctl find MAC_Binding
-OVS_WAIT_UNTIL([test `ovn-sbctl find MAC_Binding | wc -l` = 0])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- conntrack zone allocation])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# 2 logical switches "foo" (192.168.1.0/24) and "bar" (172.16.1.0/24)
-# connected to a router R1.
-# foo has foo1 to act as a client.
-# bar has bar1, bar2, bar3 to act as servers.
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-for i in foo1 bar1 bar2 bar3; do
-    ovs-vsctl -- add-port br-int $i -- \
-        set interface $i external-ids:iface-id=$i \
-        options:tx_pcap=hv1/$i-tx.pcap \
-        options:rxq_pcap=hv1/$i-rx.pcap
-done
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port bar1, bar2 and bar3 in bar
-for i in `seq 1 3`; do
-    ip=`expr $i + 1`
-    ovn-nbctl lsp-add bar bar$i \
-    -- lsp-set-addresses bar$i "f0:00:0a:01:02:$i 172.16.1.$ip"
-done
-
-OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=0 | grep REG13 | wc -l` -eq 4])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- tag allocation])
-ovn_start
-
-AT_CHECK([ovn-nbctl ls-add ls0])
-AT_CHECK([ovn-nbctl lsp-add ls0 parent1])
-AT_CHECK([ovn-nbctl lsp-add ls0 parent2])
-AT_CHECK([ovn-nbctl ls-add ls1])
-
-dnl When a tag is provided, no allocation is done
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c0 parent1 3])
-AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
-])
-dnl The same 'tag' gets created in southbound database.
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c0"], [0], [3
-])
-
-dnl Allocate tags and see it getting created in both NB and SB
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c1 parent1 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c1], [0], [1
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c1"], [0], [1
-])
-
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c2 parent1 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c2"], [0], [2
-])
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c3 parent1 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c3"], [0], [4
-])
-
-dnl A different parent.
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c4 parent2 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c4"], [0], [1
-])
-
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c5 parent2 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c5"], [0], [2
-])
-
-dnl Delete a logical port and create a new one.
-AT_CHECK([ovn-nbctl --wait=sb lsp-del c1])
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c6 parent1 0])
-AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c6"], [0], [1
-])
-
-dnl Restart northd to see that the same allocation remains.
-as northd
-OVS_APP_EXIT_AND_WAIT([ovn-northd])
-start_daemon ovn-northd \
-    --ovnnb-db=unix:"$ovs_base"/ovn-nb/ovn-nb.sock \
-    --ovnsb-db=unix:"$ovs_base"/ovn-sb/ovn-sb.sock
-
-dnl Create a switch to make sure that ovn-northd has run through the main loop.
-AT_CHECK([ovn-nbctl --wait=sb ls-add ls-dummy])
-AT_CHECK([ovn-nbctl lsp-get-tag c0], [0], [3
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c6], [0], [1
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c2], [0], [2
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c3], [0], [4
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c4], [0], [1
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
-])
-
-dnl Create a switch port with a tag that has already been allocated.
-dnl It should go through fine with a duplicate tag.
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls1 c7 parent2 2])
-AT_CHECK([ovn-nbctl lsp-get-tag c7], [0], [2
-])
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="c7"], [0], [2
-])
-AT_CHECK([ovn-nbctl lsp-get-tag c5], [0], [2
-])
-
-AT_CHECK([ovn-nbctl ls-add ls2])
-dnl When there is no parent_name provided (for say, 'localnet'), 'tag_request'
-dnl gets copied to 'tag'
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local0 "" 25])
-AT_CHECK([ovn-nbctl lsp-get-tag local0], [0], [25
-])
-dnl The same 'tag' gets created in southbound database.
-AT_CHECK([ovn-sbctl --data=bare --no-heading --columns=tag find port_binding \
-logical_port="local0"], [0], [25
-])
-dnl If 'tag_request' is 0 for localnet, nothing gets written to 'tag'
-AT_CHECK([ovn-nbctl --wait=sb lsp-add ls2 local1 "" 0])
-AT_CHECK([ovn-nbctl lsp-get-tag local1])
-dnl change the tag_request.
-AT_CHECK([ovn-nbctl --wait=sb  set logical_switch_port local1 tag_request=50])
-AT_CHECK([ovn-nbctl lsp-get-tag local1], [0], [50
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- lsp deletion and broadcast-flow deletion on localnet])
-ovn_start
-ovn-nbctl ls-add lsw0
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-    ovs-vsctl add-br br-eth0
-    AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0])
-done
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add lsw0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
-
-
-# Create 3 vifs.
-AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1])
-AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01 192.168.1.1"])
-AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"])
-AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2])
-AT_CHECK([ovn-nbctl lsp-set-addresses localvif2 "f0:00:00:00:00:02 192.168.1.2"])
-AT_CHECK([ovn-nbctl lsp-set-port-security localvif2 "f0:00:00:00:00:02"])
-AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3])
-AT_CHECK([ovn-nbctl lsp-set-addresses localvif3 "f0:00:00:00:00:03 192.168.1.3"])
-AT_CHECK([ovn-nbctl lsp-set-port-security localvif3 "f0:00:00:00:00:03"])
-
-# Bind the localvif1 to hv1.
-as hv1
-AT_CHECK([ovs-vsctl add-port br-int localvif1 -- set Interface localvif1 external_ids:iface-id=localvif1])
-
-# On hv1, check that there are no flows outputting bcast to tunnel
-OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
-
-# On hv2, check that no flow outputs bcast to tunnel to hv1.
-as hv2
-OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
-
-# Now bind vif2 on hv2.
-AT_CHECK([ovs-vsctl add-port br-int localvif2 -- set Interface localvif2 external_ids:iface-id=localvif2])
-
-# At this point, the broadcast flow on vif2 should be deleted.
-# because, there is now a localnet vif bound (table=32 programming logic)
-OVS_WAIT_UNTIL([test `ovs-ofctl dump-flows br-int table=32 | ofctl_strip | grep output | wc -l` -eq 0])
-
-# Verify that the local net patch port exists on hv2.
-OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
-
-# Now bind vif3 on hv2.
-AT_CHECK([ovs-vsctl add-port br-int localvif3 -- set Interface localvif3 external_ids:iface-id=localvif3])
-
-# Verify that the local net patch port still exists on hv2
-OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
-
-# Delete localvif2
-AT_CHECK([ovn-nbctl lsp-del localvif2])
-
-# Verify that the local net patch port still exists on hv2,
-# because, localvif3 is still bound.
-OVS_WAIT_UNTIL([test `ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l` -eq 1])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-
-AT_SETUP([ovn -- ACL logging])
-AT_KEYWORDS([ovn])
-ovn_start
-
-net_add n1
-
-sim_add hv
-as hv
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-for i in lp1 lp2; do
-    ovs-vsctl -- add-port br-int $i -- \
-        set interface $i external-ids:iface-id=$i \
-        options:tx_pcap=hv/$i-tx.pcap \
-        options:rxq_pcap=hv/$i-rx.pcap
-done
-
-lp1_mac="f0:00:00:00:00:01"
-lp1_ip="192.168.1.2"
-
-lp2_mac="f0:00:00:00:00:02"
-lp2_ip="192.168.1.3"
-
-ovn-nbctl ls-add lsw0
-ovn-nbctl --wait=sb lsp-add lsw0 lp1
-ovn-nbctl --wait=sb lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp1 $lp1_mac
-ovn-nbctl lsp-set-addresses lp2 $lp2_mac
-ovn-nbctl --wait=sb sync
-
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
-ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport 1000 'tcp.dst==81' drop
-
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
-ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 to-lport 1000 'tcp.dst==83' allow
-
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
-ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85' allow-related
-
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
-ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
-
-ovn-sbctl dump-flows
-
-
-# Send packet that should be dropped without logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should be dropped with logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should be allowed without logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should be allowed with logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should allow related flows without logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should allow related flows with logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should be rejected without logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Send packet that should be rejected with logging.
-packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
-        ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
-        tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
-as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-OVS_WAIT_UNTIL([ test 4 = $(grep -c 'acl_log' hv/ovn-controller.log) ])
-
-AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed 's/.*name=/name=/'], [0], [dnl
-name="drop-flow", verdict=drop, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn
-name="allow-flow", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn
-name="<unnamed>", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn
-name="reject-flow", verdict=reject, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn
-])
-
-OVN_CLEANUP([hv])
-AT_CLEANUP
-
-
-AT_SETUP([ovn -- ACL rate-limited logging])
-AT_KEYWORDS([ovn])
-ovn_start
-
-net_add n1
-
-sim_add hv
-as hv
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-for i in lp1 lp2; do
-    ovs-vsctl -- add-port br-int $i -- \
-        set interface $i external-ids:iface-id=$i \
-        options:tx_pcap=hv/$i-tx.pcap \
-        options:rxq_pcap=hv/$i-rx.pcap
-done
-
-lp1_mac="f0:00:00:00:00:01"
-lp1_ip="192.168.1.2"
-
-lp2_mac="f0:00:00:00:00:02"
-lp2_ip="192.168.1.3"
-
-ovn-nbctl ls-add lsw0
-ovn-nbctl --wait=sb lsp-add lsw0 lp1
-ovn-nbctl --wait=sb lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp1 $lp1_mac
-ovn-nbctl lsp-set-addresses lp2 $lp2_mac
-ovn-nbctl --wait=sb sync
-
-
-# Add an ACL that rate-limits logs at 10 per second.
-ovn-nbctl meter-add http-rl1 drop 10 pktps
-ovn-nbctl --log --severity=alert --meter=http-rl1 --name=http-acl1 acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
-
-# Add an ACL that rate-limits logs at 5 per second.
-ovn-nbctl meter-add http-rl2 drop 5 pktps
-ovn-nbctl --log --severity=alert --meter=http-rl2 --name=http-acl2 acl-add lsw0 to-lport 1000 'tcp.dst==81' allow
-
-# Add an ACL that doesn't rate-limit logs.
-ovn-nbctl --log --severity=alert --name=http-acl3 acl-add lsw0 to-lport 1000 'tcp.dst==82' drop
-ovn-nbctl --wait=hv sync
-
-# For each ACL, send 100 packets.
-for i in `seq 1 100`; do
-    ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=80)'
-
-    ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=81)'
-
-    ovs-appctl netdev-dummy/receive lp1 'in_port(1),eth(src=f0:00:00:00:00:01,dst=f0:00:00:00:00:02),eth_type(0x0800),ipv4(src=192.168.1.2,dst=192.168.1.3,proto=6,tos=0,ttl=64,frag=no),tcp(src=7777,dst=82)'
-done
-
-# The rate at which packets are sent is highly system-dependent, so we
-# can't count on precise drop counts.  To work around that, we just
-# check that exactly 100 "http-acl3" actions were logged and that there
-# were more "http-acl1" actions than "http-acl2" ones.
-OVS_WAIT_UNTIL([ test 100 = $(grep -c 'http-acl3' hv/ovn-controller.log) ])
-
-# On particularly slow or overloaded systems, the transmission rate may
-# be lower than the configured meter rate.  To prevent false test
-# failures, we check the duration count of the meter, and if it's
-# greater than nine seconds, just skip the test.
-d_secs=$(as hv ovs-ofctl -O OpenFlow13 meter-stats br-int | grep "meter:1" | sed 's/.* duration:\([[0-9]]\{1,\}\)\.[[0-9]]\+s .*/\1/')
-
-echo "Meter duration: $d_secs"
-AT_SKIP_IF([test $d_secs -gt 9])
-
-# Print some information that may help debugging.
-as hv ovs-appctl -t ovn-controller meter-table-list
-as hv ovs-ofctl -O OpenFlow13 meter-stats br-int
-
-n_acl1=$(grep -c 'http-acl1' hv/ovn-controller.log)
-n_acl2=$(grep -c 'http-acl2' hv/ovn-controller.log)
-n_acl3=$(grep -c 'http-acl3' hv/ovn-controller.log)
-
-AT_CHECK([ test $n_acl3 -gt $n_acl1 ], [0], [])
-AT_CHECK([ test $n_acl1 -gt $n_acl2 ], [0], [])
-
-OVN_CLEANUP([hv])
-AT_CLEANUP
-
-
-AT_SETUP([ovn -- DSCP marking and meter check])
-AT_KEYWORDS([ovn])
-ovn_start
-
-ovn-nbctl ls-add lsw0
-ovn-nbctl --wait=sb lsp-add lsw0 lp1
-ovn-nbctl --wait=sb lsp-add lsw0 lp2
-ovn-nbctl --wait=sb lsp-add lsw0 lp3
-ovn-nbctl lsp-set-addresses lp1 f0:00:00:00:00:01
-ovn-nbctl lsp-set-addresses lp2 f0:00:00:00:00:02
-ovn-nbctl lsp-set-addresses lp3 f0:00:00:00:00:03
-ovn-nbctl lsp-set-port-security lp1 f0:00:00:00:00:01
-ovn-nbctl lsp-set-port-security lp2 f0:00:00:00:00:02
-ovn-nbctl --wait=sb sync
-net_add n1
-sim_add hv
-as hv
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1 options:tx_pcap=vif1-tx.pcap options:rxq_pcap=vif1-rx.pcap ofport-request=1
-ovs-vsctl add-port br-int vif2 -- set Interface vif2 external-ids:iface-id=lp2 options:tx_pcap=vif2-tx.pcap options:rxq_pcap=vif2-rx.pcap ofport-request=2
-
-AT_CAPTURE_FILE([trace])
-ovn_trace () {
-    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
-}
-
-# Extracts nw_tos from the final flow from ofproto/trace output and prints
-# it on stdout.  Prints "none" if no nw_tos was included.
-get_final_nw_tos() {
-    if flow=$(grep '^Final flow:' stdout); then :; else
-       # The output didn't have a final flow.
-       return 99
-    fi
-
-    tos=$(echo "$flow" | sed -n 's/.*nw_tos=\([[0-9]]\{1,\}\).*/\1/p')
-    case $tos in
-        '') echo none ;;
-        *) echo $tos ;;
-    esac
-}
-
-# check_tos TOS
-#
-# Checks that a packet from 1.1.1.1 to 1.1.1.2 gets its DSCP set to TOS.
-check_tos() {
-    # First check with ovn-trace for logical flows.
-    echo "checking for tos $1"
-    (if test $1 != 0; then echo "ip.dscp = $1;"; fi;
-     echo 'output("lp2");') > expout
-    AT_CHECK_UNQUOTED([ovn_trace lsw0 'inport == "lp1" && eth.src == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02 && ip4.src == 1.1.1.1 && ip4.dst == 1.1.1.2'], [0], [expout])
-
-    # Then re-check with ofproto/trace for a physical packet.
-    AT_CHECK([ovs-appctl ofproto/trace br-int 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,dl_type=0x800,nw_src=1.1.1.1,nw_dst=1.1.1.2'], [0], [stdout-nolog])
-    AT_CHECK_UNQUOTED([get_final_nw_tos], [0], [`expr $1 \* 4`
-])
-}
-
-# check at L2
-AT_CHECK([ovn_trace lsw0 'inport == "lp1" && eth.src == f0:00:00:00:00:01 && eth.dst == f0:00:00:00:00:02'], [0], [output("lp2");
-])
-AT_CHECK([ovs-appctl ofproto/trace br-int 'in_port=1,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02'], [0], [stdout-nolog])
-AT_CHECK([get_final_nw_tos], [0], [none
-])
-
-# check at L3 without dscp marking
-check_tos 0
-
-# Mark DSCP with a valid value
-qos_id=$(ovn-nbctl --wait=hv -- --id=@lp1-qos create QoS priority=100 action=dscp=48 match="inport\=\=\"lp1\"\ &&\ is_chassis_resident(\"lp1\")" direction="from-lport" -- set Logical_Switch lsw0 qos_rules=@lp1-qos)
-AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
-])
-check_tos 48
-
-# check at hv without qos meter
-AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
-])
-
-# Update the meter rate
-ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=100
-
-# check at hv with a qos meter table
-AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep rate=100 | wc -l], [0], [1
-])
-AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [1
-])
-
-# Update the DSCP marking
-ovn-nbctl --wait=hv set QoS $qos_id action=dscp=63
-check_tos 63
-
-# Update the meter rate
-ovn-nbctl --wait=hv set QoS $qos_id bandwidth=rate=4294967295,burst=4294967295
-
-# check at hv with a qos meter table
-AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep burst_size=4294967295 | wc -l], [0], [1
-])
-AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [1
-])
-
-ovn-nbctl --wait=hv set QoS $qos_id match="outport\=\=\"lp2\"" direction="to-lport"
-check_tos 63
-
-# Disable DSCP marking
-ovn-nbctl --wait=hv qos-del lsw0
-AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [0
-])
-check_tos 0
-
-# check at hv without qos meter
-AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
-])
-
-# check meter with chassis not resident
-ovn-nbctl qos-add lsw0 to-lport 1001 'inport=="lp3" && is_chassis_resident("lp3")' rate=11123 burst=111230
-AT_CHECK([as hv ovn-nbctl qos-list lsw0 | wc -l], [0], [1
-])
-
-# check no meter table
-AT_CHECK([as hv ovs-ofctl dump-flows br-int -O OpenFlow13 | grep meter | wc -l], [0], [0
-])
-AT_CHECK([as hv ovs-ofctl dump-meters br-int -O OpenFlow13 | grep rate=11123 | wc -l], [0], [0
-])
-
-OVN_CLEANUP([hv])
-AT_CLEANUP
-
-AT_SETUP([ovn -- read-only sb db:ptcp access])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-
-: > .$1.db.~lock~
-ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
-
-# Add read-only remote to sb ovsdb-server
-AT_CHECK(
-  [ovsdb-tool transact ovn-sb.db \
-     ['["OVN_Southbound",
-       {"op": "insert",
-        "table": "SB_Global",
-        "row": {
-          "connections": ["set", [["named-uuid", "xyz"]]]}},
-       {"op": "insert",
-        "table": "Connection",
-        "uuid-name": "xyz",
-        "row": {"target": "ptcp:0:127.0.0.1",
-               "read_only": true}}]']], [0], [ignore], [ignore])
-
-start_daemon ovsdb-server --remote=punix:ovn-sb.sock --remote=db:OVN_Southbound,SB_Global,connections ovn-sb.db
-
-PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
-
-# read-only accesses should succeed
-AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list SB_Global], [0], [stdout], [ignore])
-AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT list Connection], [0], [stdout], [ignore])
-
-# write access should fail
-AT_CHECK([ovn-sbctl --db=tcp:127.0.0.1:$TCP_PORT chassis-add ch vxlan 1.2.4.8], [1], [ignore],
-[ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}
-])
-
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-AT_CLEANUP
-
-AT_SETUP([ovn -- read-only sb db:pssl access])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
-PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
-AT_SKIP_IF([expr "$PKIDIR" : ".*[ 	'\"
-\\]"])
-
-: > .$1.db.~lock~
-ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
-
-# Add read-only remote to sb ovsdb-server
-AT_CHECK(
-  [ovsdb-tool transact ovn-sb.db \
-     ['["OVN_Southbound",
-       {"op": "insert",
-        "table": "SB_Global",
-        "row": {
-          "connections": ["set", [["named-uuid", "xyz"]]]}},
-       {"op": "insert",
-        "table": "Connection",
-        "uuid-name": "xyz",
-        "row": {"target": "pssl:0:127.0.0.1",
-               "read_only": true}}]']], [0], [ignore], [ignore])
-
-start_daemon ovsdb-server --remote=punix:ovn-sb.sock \
-                          --remote=db:OVN_Southbound,SB_Global,connections \
-                          --private-key="$PKIDIR/testpki-privkey2.pem" \
-                          --certificate="$PKIDIR/testpki-cert2.pem" \
-                          --ca-cert="$PKIDIR/testpki-cacert.pem" \
-                          ovn-sb.db
-
-PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
-
-# read-only accesses should succeed
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-                    list SB_Global], [0], [stdout], [ignore])
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-                    list Connection], [0], [stdout], [ignore])
-
-# write access should fail
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-                    chassis-add ch vxlan 1.2.4.8], [1], [ignore],
-[ovn-sbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}
-])
-
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-AT_CLEANUP
-
-AT_SETUP([ovn -- nb connection/ssl commands])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
-PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
-AT_SKIP_IF([expr "$PKIDIR" : ".*[ 	'\"
-\\]"])
-
-: > .$1.db.~lock~
-ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
-
-# Start nb db server using db connection/ssl entries (unpopulated initially)
-start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
-                          --remote=db:OVN_Northbound,NB_Global,connections \
-                          --private-key=db:OVN_Northbound,SSL,private_key \
-                          --certificate=db:OVN_Northbound,SSL,certificate \
-                          --ca-cert=db:OVN_Northbound,SSL,ca_cert \
-                          ovn-nb.db
-
-# Populate SSL configuration entries in nb db
-AT_CHECK(
-    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
-                       $PKIDIR/testpki-cert.pem \
-                       $PKIDIR/testpki-cacert.pem], [0], [stdout], [ignore])
-
-# Populate a passive SSL connection in nb db
-AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0], [stdout], [ignore])
-
-PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
-
-# Verify SSL connetivity to nb db server
-AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          list NB_Global],
-         [0], [stdout], [ignore])
-AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          list Connection],
-         [0], [stdout], [ignore])
-AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          get-connection],
-         [0], [stdout], [ignore])
-
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-AT_CLEANUP
-
-AT_SETUP([ovn -- sb connection/ssl commands])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
-PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
-AT_SKIP_IF([expr "$PKIDIR" : ".*[ 	'\"
-\\]"])
-
-: > .$1.db.~lock~
-ovsdb-tool create ovn-sb.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema
-
-# Start sb db server using db connection/ssl entries (unpopulated initially)
-start_daemon ovsdb-server --remote=punix:ovnsb_db.sock \
-                          --remote=db:OVN_Southbound,SB_Global,connections \
-                          --private-key=db:OVN_Southbound,SSL,private_key \
-                          --certificate=db:OVN_Southbound,SSL,certificate \
-                          --ca-cert=db:OVN_Southbound,SSL,ca_cert \
-                          ovn-sb.db
-
-# Populate SSL configuration entries in sb db
-AT_CHECK(
-    [ovn-sbctl set-ssl $PKIDIR/testpki-privkey.pem \
-                       $PKIDIR/testpki-cert.pem \
-                       $PKIDIR/testpki-cacert.pem], [0], [stdout], [ignore])
-
-# Populate a passive SSL connection in sb db
-AT_CHECK([ovn-sbctl set-connection pssl:0:127.0.0.1], [0], [stdout], [ignore])
-
-PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
-
-# Verify SSL connetivity to sb db server
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          list SB_Global],
-         [0], [stdout], [ignore])
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          list Connection],
-         [0], [stdout], [ignore])
-AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
-                    --private-key=$PKIDIR/testpki-privkey.pem \
-                    --certificate=$PKIDIR/testpki-cert.pem \
-                    --ca-cert=$PKIDIR/testpki-cacert.pem \
-          get-connection],
-         [0], [stdout], [ignore])
-
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-AT_CLEANUP
-
-AT_SETUP([ovn -- nested containers])
-ovn_start
-
-# Physical network:
-# 2 HVs. HV1 has 2 VMs - "VM1" and "bar3". HV2 has 1 VM - "VM2"
-
-# Logical network:
-# 3 Logical switches - "mgmt" (172.16.1.0/24), "foo" (192.168.1.0/24)
-# and "bar" (192.168.2.0/24). They are all connected to router R1.
-
-ovn-nbctl lr-add R1
-ovn-nbctl ls-add mgmt
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-
-# Connect mgmt to R1
-ovn-nbctl lrp-add R1 mgmt 00:00:00:01:02:02 172.16.1.1/24
-ovn-nbctl lsp-add mgmt rp-mgmt -- set Logical_Switch_Port rp-mgmt type=router \
-          options:router-port=mgmt addresses=\"00:00:00:01:02:02\"
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-          options:router-port=foo addresses=\"00:00:00:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:00:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar type=router \
-          options:router-port=bar addresses=\"00:00:00:01:02:04\"
-
-# "mgmt" has VM1 and VM2 connected
-ovn-nbctl lsp-add mgmt vm1 \
--- lsp-set-addresses vm1 "f0:00:00:01:02:03 172.16.1.2"
-
-ovn-nbctl lsp-add mgmt vm2 \
--- lsp-set-addresses vm2 "f0:00:00:01:02:04 172.16.1.3"
-
-# "foo1" and "foo2" are containers belonging to switch "foo"
-# "foo1" has "VM1" as parent_port and "foo2" has "VM2" as parent_port.
-ovn-nbctl lsp-add foo foo1 vm1 1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:05 192.168.1.2"
-
-ovn-nbctl lsp-add foo foo2 vm2 2 \
--- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
-
-# "bar1" and "bar2" are containers belonging to switch "bar"
-# "bar1" has "VM1" as parent_port and "bar2" has "VM2" as parent_port.
-ovn-nbctl lsp-add bar bar1 vm1 2 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:07 192.168.2.2"
-
-ovn-nbctl lsp-add bar bar2 vm2 1 \
--- lsp-set-addresses bar2 "f0:00:00:01:02:08 192.168.2.3"
-
-# bar3 is a standalone VM belonging to switch "bar"
-ovn-nbctl lsp-add bar bar3 \
--- lsp-set-addresses bar3 "f0:00:00:01:02:09 192.168.2.4"
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int vm1 -- \
-    set interface vm1 external-ids:iface-id=vm1 \
-    options:tx_pcap=hv1/vm1-tx.pcap \
-    options:rxq_pcap=hv1/vm1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int bar3 -- \
-    set interface bar3 external-ids:iface-id=bar3 \
-    options:tx_pcap=hv1/bar3-tx.pcap \
-    options:rxq_pcap=hv1/bar3-rx.pcap \
-    ofport-request=2
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int vm2 -- \
-    set interface vm2 external-ids:iface-id=vm2 \
-    options:tx_pcap=hv2/vm2-tx.pcap \
-    options:rxq_pcap=hv2/vm2-rx.pcap \
-    ofport-request=1
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and foo2 (same switch, different HVs and
-# different VLAN tags).
-src_mac="f00000010205"
-dst_mac="f00000010206"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 1 3`
-packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at foo2
-packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-echo  $packet > expected
-OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
-
-# Send ip packets between foo1 and bar2 (different switch, different HV)
-src_mac="f00000010205"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 3`
-packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at bar2
-src_mac="000000010204"
-dst_mac="f00000010208"
-packet=${dst_mac}${src_mac}8100000108004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo  $packet >> expected
-OVN_CHECK_PACKETS([hv2/vm2-tx.pcap], [expected])
-
-# Send ip packets between foo1 and bar1
-# (different switch, loopback to same vm but different tag)
-src_mac="f00000010205"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at bar1
-src_mac="000000010204"
-dst_mac="f00000010207"
-packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo  $packet > expected1
-OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
-
-# Send ip packets between bar1 and bar3
-# (same switch. But one is container and another is a standalone VM)
-src_mac="f00000010207"
-dst_mac="f00000010209"
-src_ip=`ip_to_hex 192 168 2 2`
-dst_ip=`ip_to_hex 192 168 2 3`
-packet=${dst_mac}${src_mac}8100000208004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at bar3
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-echo  $packet > expected
-OVN_CHECK_PACKETS([hv1/bar3-tx.pcap], [expected])
-
-# Send ip packets between foo1 and vm1.
-(different switch, container to the VM hosting it.)
-src_mac="f00000010205"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 2`
-packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at vm1
-src_mac="000000010202"
-dst_mac="f00000010203"
-packet=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo  $packet >> expected1
-OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
-
-# Send packets from vm1 to bar1.
-(different switch, A hosting VM to a container inside it)
-src_mac="f00000010203"
-dst_mac="000000010202"
-src_ip=`ip_to_hex 172 16 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at vm1
-src_mac="000000010204"
-dst_mac="f00000010207"
-packet=${dst_mac}${src_mac}8100000208004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo  $packet >> expected1
-OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
-
-# Send broadcast packet from foo1. foo1 should not receive the same packet.
-src_mac="f00000010205"
-dst_mac="ffffffffffff"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 255 255 255 255`
-packet=${dst_mac}${src_mac}8100000108004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive vm1 $packet
-
-# expected packet at VM1
-OVN_CHECK_PACKETS([hv1/vm1-tx.pcap], [expected1])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 3 HVs, 3 LRs connected via LS, source IP based routes])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and bar
-# (192.168.2.0/24) connected to it.
-#
-# R2 and R3 are gateway routers.
-# R2 has alice (172.16.1.0/24) and R3 has bob (172.16.1.0/24)
-# connected to it. Note how both alice and bob have the same subnet behind it.
-# We are trying to simulate external network via those 2 switches. In real
-# world the switch ports of these switches will have addresses set as "unknown"
-# to make them learning switches. Or those switches will be "localnet" ones.
-
-# Create three hypervisors and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=bar1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-int hv3-vif1 -- \
-    set interface hv3-vif1 external-ids:iface-id=bob1 \
-    options:tx_pcap=hv3/vif1-tx.pcap \
-    options:rxq_pcap=hv3/vif1-rx.pcap \
-    ofport-request=1
-
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis="hv2"
-ovn-nbctl create Logical_Router name=R3 options:chassis="hv3"
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add bob
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-    options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar type=router \
-    options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect bob to R3
-ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
-ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
-    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Connect R3 to join
-ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
-ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
-    type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
-
-# Install static routes with source ip address as the policy for routing.
-# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via R3.
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
-
-# Install static routes with destination ip address as the policy for routing.
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-
-ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port bar1 in bar
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
-
-# Create logical port alice1 in alice
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.3"
-
-# Create logical port bob1 in bob
-ovn-nbctl lsp-add bob bob1 \
--- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-# Send ip packets between foo1 and bar1
-# (East-west traffic should flow normally)
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-# Send ip packets between foo1 and alice1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 3`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-as hv1 ovs-appctl ofproto/trace br-int in_port=1 $packet
-
-# Send ip packets between bar1 and bob1
-src_mac="f00000010204"
-dst_mac="000001010204"
-src_ip=`ip_to_hex 192 168 2 2`
-dst_ip=`ip_to_hex 172 16 1 4`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
-#as hv1 ovs-appctl ofproto/trace br-int in_port=2 $packet
-
-# Packet to expect at bar1
-src_mac="000001010204"
-dst_mac="f00000010204"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 192 168 2 2`
-expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-echo $expected > expected
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-
-# Packet to Expect at alice1
-src_mac="000002010203"
-dst_mac="f00000010205"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 3`
-expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
-echo $expected > expected
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Packet to Expect at bob1
-src_mac="000003010203"
-dst_mac="f00000010206"
-src_ip=`ip_to_hex 192 168 2 2`
-dst_ip=`ip_to_hex 172 16 1 4`
-expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
-echo $expected > expected
-OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- dns lookup : 1 HV, 2 LS, 2 LSPs/LS])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
-
-ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4"
-
-ovn-nbctl lsp-add ls1 ls1-lp2 \
--- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
-
-ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6 20.0.0.4"
-
-DNS1=`ovn-nbctl create DNS records={}`
-DNS2=`ovn-nbctl create DNS records={}`
-
-ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
-ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6 20.0.0.4"
-ovn-nbctl set DNS $DNS2 records:vm3.ovn.org="40.0.0.4"
-
-ovn-nbctl set Logical_switch ls1 dns_records="$DNS1"
-
-net_add n1
-sim_add hv1
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-OVN_POPULATE_ARP
-sleep 2
-as hv1 ovs-vsctl show
-
-echo "*************************"
-ovn-sbctl list DNS
-echo "*************************"
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-# set_dns_params host_name
-# Sets the dns_req_data and dns_resp_data
-set_dns_params() {
-    local hname=$1
-    local ttl=00000e10
-    an_count=0001
-    type=0001
-    case $hname in
-    vm1)
-        # vm1.ovn.org
-        query_name=03766d31036f766e036f726700
-        # IPv4 address - 10.0.0.4
-        expected_dns_answer=${query_name}00010001${ttl}00040a000004
-        ;;
-    vm2)
-        # vm2.ovn.org
-        query_name=03766d32036f766e036f726700
-        # IPv4 address - 10.0.0.6
-        expected_dns_answer=${query_name}00010001${ttl}00040a000006
-        # IPv4 address - 20.0.0.4
-        expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004
-        an_count=0002
-        ;;
-    vm3)
-        # vm3.ovn.org
-        query_name=03766d33036f766e036f726700
-        # IPv4 address - 40.0.0.4
-        expected_dns_answer=${query_name}00010001${ttl}000428000004
-        ;;
-    vm1_ipv6_only)
-        # vm1.ovn.org
-        query_name=03766d31036f766e036f726700
-        # IPv6 address - aef0::4
-        type=001c
-        expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004
-        ;;
-    vm1_ipv4_v6)
-        # vm1.ovn.org
-        query_name=03766d31036f766e036f726700
-        type=00ff
-        an_count=0002
-        # IPv4 address - 10.0.0.4
-        # IPv6 address - aef0::4
-        expected_dns_answer=${query_name}00010001${ttl}00040a000004
-        expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010
-        expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004
-        ;;
-    vm1_invalid_type)
-        # vm1.ovn.org
-        query_name=03766d31036f766e036f726700
-        # IPv6 address - aef0::4
-        type=0002
-        ;;
-    vm1_incomplete)
-        # set type to none
-        type=''
-    esac
-    # TTL - 3600
-    local dns_req_header=010201200001000000000000
-    local dns_resp_header=010281200001${an_count}00000000
-    dns_req_data=${dns_req_header}${query_name}${type}0001
-    dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer}
-}
-
-# This shell function sends a DNS request packet
-# test_dns INPORT SRC_MAC DST_MAC SRC_IP DST_IP DNS_QUERY EXPEC
-test_dns() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
-    local dns_query_data=$7
-    shift; shift; shift; shift; shift; shift; shift;
-    # Packet size => IPv4 header (20) + UDP header (8) +
-    #                DNS data (header + query)
-    ip_len=`expr 28 + ${#dns_query_data} / 2`
-    udp_len=`expr $ip_len - 20`
-    ip_len=$(printf "%x" $ip_len)
-    udp_len=$(printf "%x" $udp_len)
-    local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000
-    request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000
-    # dns data
-    request=${request}${dns_query_data}
-
-    if test $dns_reply != 0; then
-        local dns_reply=$1
-        ip_len=`expr 28 + ${#dns_reply} / 2`
-        udp_len=`expr $ip_len - 20`
-        ip_len=$(printf "%x" $ip_len)
-        udp_len=$(printf "%x" $udp_len)
-        local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000
-        reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply}
-        echo $reply >> $inport.expected
-    else
-        for outport; do
-            echo $request >> $outport.expected
-        done
-    fi
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
-}
-
-test_dns6() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
-    local dns_query_data=$7
-    shift; shift; shift; shift; shift; shift; shift;
-    # Packet size => UDP header (8) +
-    #                DNS data (header + query)
-    ip_len=`expr 8 + ${#dns_query_data} / 2`
-    udp_len=$ip_len
-    ip_len=$(printf "%x" $ip_len)
-    udp_len=$(printf "%x" $udp_len)
-    local request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
-    request=${request}9234003500${udp_len}0000
-    #dns data
-    request=${request}${dns_query_data}
-
-    if test $dns_reply != 0; then
-        local dns_reply=$1
-        ip_len=`expr 8 + ${#dns_reply} / 2`
-        udp_len=$ip_len
-        ip_len=$(printf "%x" $ip_len)
-        udp_len=$(printf "%x" $udp_len)
-        local reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
-        reply=${reply}0035923400${udp_len}0000${dns_reply}
-        echo $reply >> $inport.expected
-    else
-        for outport; do
-            echo $request >> $outport.expected
-        done
-    fi
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
-}
-
-AT_CAPTURE_FILE([ofctl_monitor0.log])
-as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
-
-set_dns_params vm2
-src_ip=`ip_to_hex 10 0 0 4`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=1
-test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 1.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
-cat 1.expected | cut -c -48 > expout
-AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 1.expected | cut -c 53- > expout
-AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-set_dns_params vm1
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=1
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Clear the query name options for ls1-lp2
-ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org
-
-set_dns_params vm2
-src_ip=`ip_to_hex 10 0 0 4`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=0
-test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply $dns_req_data
-
-# NXT_RESUMEs should be 3.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
-AT_CHECK([cat 1.packets], [0], [])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Clear the query name for ls1-lp1
-# Since ls1 has no query names configued,
-# ovn-northd should not add the DNS flows.
-ovn-nbctl --wait=hv remove DNS $DNS1 records vm1.ovn.org
-
-set_dns_params vm1
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=0
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
-
-# NXT_RESUMEs should be 3 only.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-AT_CHECK([cat 2.packets], [0], [])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Test IPv6 (AAAA records) using IPv4 packet.
-# Add back the DNS options for ls1-lp1.
-ovn-nbctl --wait=hv set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4"
-
-set_dns_params vm1_ipv6_only
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=1
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 4.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Test both IPv4 (A) and IPv6 (AAAA records) using IPv4 packet.
-set_dns_params vm1_ipv4_v6
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=1
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 5.
-OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-cat 2.expected | cut -c -48 > expout
-AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 2.expected | cut -c 53- > expout
-AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Invalid type.
-set_dns_params vm1_invalid_type
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=0
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
-
-# NXT_RESUMEs should be 6.
-OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-AT_CHECK([cat 2.packets], [0], [])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Incomplete DNS packet.
-set_dns_params vm1_incomplete
-src_ip=`ip_to_hex 10 0 0 6`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=0
-test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data
-
-# NXT_RESUMEs should be 7.
-OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-AT_CHECK([cat 2.packets], [0], [])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Add one more DNS record to the ls1.
-ovn-nbctl --wait=hv set Logical_switch ls1 dns_records="$DNS1 $DNS2"
-
-set_dns_params vm3
-src_ip=`ip_to_hex 10 0 0 4`
-dst_ip=`ip_to_hex 10 0 0 1`
-dns_reply=1
-test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 8.
-OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
-cat 1.expected | cut -c -48 > expout
-AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat 1.expected | cut -c 53- > expout
-AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-# Try DNS query over IPv6
-set_dns_params vm1
-src_ip=aef00000000000000000000000000004
-dst_ip=aef00000000000000000000000000001
-dns_reply=1
-test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
-
-# NXT_RESUMEs should be 9.
-OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
-# Skipping the UDP checksum.
-cat 1.expected | cut -c 1-120,125- > expout
-AT_CHECK([cat 1.packets | cut -c 1-120,125-], [0], [expout])
-
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-rm -f 1.expected
-rm -f 2.expected
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4 HV, 1 LS, 1 LR, packet test with HA distributed router gateway port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add gw1
-as gw1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-sim_add gw2
-as gw2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.4
-
-sim_add ext1
-as ext1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-int ext1-vif1 -- \
-    set interface ext1-vif1 external-ids:iface-id=outside1 \
-    options:tx_pcap=ext1/vif1-tx.pcap \
-    options:rxq_pcap=ext1/vif1-rx.pcap \
-    ofport-request=1
-
-# 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
-
-ovn-nbctl create Logical_Router name=R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add outside
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect alice to R1 as distributed router gateway port on gw1
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
-
-ovn-nbctl \
-    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
-                                     chassis_name=gw1 \
-                                     priority=20 -- \
-    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
-                                     chassis_name=gw2 \
-                                     priority=10 -- \
-    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
-
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port outside1 in outside
-ovn-nbctl lsp-add outside outside1 \
--- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
-
-# Create localnet port in alice
-ovn-nbctl lsp-add alice ln-alice
-ovn-nbctl lsp-set-addresses ln-alice unknown
-ovn-nbctl lsp-set-type ln-alice localnet
-ovn-nbctl lsp-set-options ln-alice network_name=phys
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
-# mapping to the external network, is the one generating packets
-as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-test_ip_packet()
-{
-    local active_gw=$1
-    local backup_gw=$2
-    local backup_vswitchd_dead=$3
-
-    # Send ip packet between foo1 and outside1
-    src_mac="f00000010203" # foo1 mac
-    dst_mac="000001010203" # rp-foo mac (internal router leg)
-    src_ip=`ip_to_hex 192 168 1 2`
-    dst_ip=`ip_to_hex 172 16 1 3`
-    packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-    # ARP request packet to expect at outside1
-    #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
-
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-    # Send ARP reply from outside1 back to the router
-    # XXX: note, we could avoid this if we plug this port into a netns
-    # and setup the IP address into the port, so the kernel would simply reply
-    src_mac="000002010203"
-    reply_mac="f00000010204"
-    dst_ip=`ip_to_hex 172 16 1 3`
-    src_ip=`ip_to_hex 172 16 1 1`
-    arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
-
-    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
-
-    OVS_WAIT_UNTIL([
-        test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 | \
-grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
-    ])
-
-    # Packet to Expect at ext1 chassis, outside1 port
-    src_mac="000002010203"
-    dst_mac="f00000010204"
-    src_ip=`ip_to_hex 192 168 1 2`
-    dst_ip=`ip_to_hex 172 16 1 3`
-    expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-    echo $expected > ext1-vif1.expected
-    exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
-    echo $exp_gw_ip_garp >> ext1-vif1.expected
-    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
-
-    if test $backup_vswitchd_dead != 1; then
-        # Reset the file only if vswitchd in backup gw is alive
-        as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
-    fi
-    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
-
-    # Resend packet from foo1 to outside1
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-    sleep 1
-
-    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
-    $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap  > packets
-    cat packets | grep $expected > exp
-    # Its possible that $active_gw/br-phys_n1-tx.pcap may have received multiple
-    # garp packets. So consider only the first packet.
-    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
-    AT_CHECK([cat exp], [0], [expout])
-    rm -f expout
-    if test $backup_vswitchd_dead != 1; then
-        # Check for backup gw only if vswitchd is alive
-        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap  > packets
-        AT_CHECK([grep $expected packets | sort], [0], [])
-    fi
-}
-
-test_ip_packet gw1 gw2 0
-
-ovn-nbctl --timeout=3 --wait=hv \
-    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
-                                     chassis_name=gw1 \
-                                     priority=10 -- \
-    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
-                                     chassis_name=gw2 \
-                                     priority=20 -- \
-    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
-
-test_ip_packet gw2 gw1 0
-
-# Get the claim count of both gw1 and gw2.
-gw1_claim_ct=`grep "cr-alice: Claiming" gw1/ovn-controller.log | wc -l`
-gw2_claim_ct=`grep "cr-alice: Claiming" gw2/ovn-controller.log | wc -l`
-
-# Stop ovs-vswitchd in gw2. gw1 should claim the gateway port.
-as gw2
-OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
-
-# gw1 should claim the cr-alice and the claim count of gw1 should be
-# incremented by 1.
-gw1_claim_ct=$((gw1_claim_ct+1))
-
-OVS_WAIT_UNTIL([test $gw1_claim_ct = `cat gw1/ovn-controller.log \
-| grep -c "cr-alice: Claiming"`])
-
-AT_CHECK([test $gw2_claim_ct = `cat gw2/ovn-controller.log | \
-grep -c "cr-alice: Claiming"`])
-
-test_ip_packet gw1 gw2 1
-
-as gw2
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-OVS_APP_EXIT_AND_WAIT([ovsdb-server])
-
-OVN_CLEANUP([hv1],[gw1],[ext1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 4 HV, 3 LS, 2 LR, packet test with HA distributed router gateway port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add gw1
-as gw1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-sim_add gw2
-as gw2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.4
-
-sim_add ext1
-as ext1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-int ext1-vif1 -- \
-    set interface ext1-vif1 external-ids:iface-id=outside1 \
-    options:tx_pcap=ext1/vif1-tx.pcap \
-    options:rxq_pcap=ext1/vif1-rx.pcap \
-    ofport-request=1
-
-# 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
-
-ovn-nbctl create Logical_Router name=R0
-ovn-nbctl create Logical_Router name=R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add join
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add outside
-
-#Connect foo to R0
-ovn-nbctl lrp-add R0 R0-foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo foo-R0 -- set Logical_Switch_Port foo-R0 \
-    type=router options:router-port=R0-foo \
-    -- lsp-set-addresses foo-R0 router
-
-#Connect R0 to join
-ovn-nbctl lrp-add R0 R0-join 00:00:0d:01:02:03 100.60.1.1/24
-ovn-nbctl lsp-add join join-R0 -- set Logical_Switch_Port join-R0 \
-    type=router options:router-port=R0-join \
-    -- lsp-set-addresses join-R0 router
-
-#Connect join to R1
-ovn-nbctl lrp-add R1 R1-join 00:00:0e:01:02:03 100.60.1.2/24
-ovn-nbctl lsp-add join join-R1 -- set Logical_Switch_Port join-R1 \
-    type=router options:router-port=R1-join \
-    -- lsp-set-addresses join-R1 router
-
-#add route rules
-ovn-nbctl lr-route-add R0 0.0.0.0/0 100.60.1.2
-ovn-nbctl lr-route-add R1 192.168.0.0/16 100.60.1.1
-
-# Connect alice to R1 as distributed router gateway port on gw1
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24
-
-ovn-nbctl \
-    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
-                                     chassis_name=gw1 \
-                                     priority=20 -- \
-    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
-                                     chassis_name=gw2 \
-                                     priority=10 -- \
-    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
-
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port outside1 in outside
-ovn-nbctl lsp-add outside outside1 \
--- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
-
-# Create localnet port in alice
-ovn-nbctl lsp-add alice ln-alice
-ovn-nbctl lsp-set-addresses ln-alice unknown
-ovn-nbctl lsp-set-type ln-alice localnet
-ovn-nbctl lsp-set-options ln-alice network_name=phys
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Create bridge-mappings on gw1, gw2 and ext1, hv1 doesn't need
-# mapping to the external network, is the one generating packets
-as gw1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-as gw2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-as ext1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore])
-
-# hv1 should be in 'ref_chassis' of the ha_chasssi_group as logical
-# switch 'foo' can reach the router 'R1' (which has gw router port)
-# via foo1 -> foo -> R0 -> join -> R1
-hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$hv1_ch_uuid" = "$ref_ch_list"])
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-test_ip_packet()
-{
-    local active_gw=$1
-    local backup_gw=$2
-
-    # Send ip packet between foo1 and outside1
-    src_mac="f00000010203" # foo1 mac
-    dst_mac="000001010203" # foo-R0 mac (internal router leg)
-    src_ip=`ip_to_hex 192 168 1 2`
-    dst_ip=`ip_to_hex 172 16 1 3`
-    packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-    # ARP request packet to expect at outside1
-    #arp_request=ffffffffffff${src_mac}08060001080006040001${src_mac}${src_ip}000000000000${dst_ip}
-
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-    # Send ARP reply from outside1 back to the router
-    # XXX: note, we could avoid this if we plug this port into a netns
-    # and setup the IP address into the port, so the kernel would simply reply
-    src_mac="000002010203"
-    reply_mac="f00000010204"
-    dst_ip=`ip_to_hex 172 16 1 3`
-    src_ip=`ip_to_hex 172 16 1 1`
-    arp_reply=${src_mac}${reply_mac}08060001080006040002${reply_mac}${dst_ip}${src_mac}${src_ip}
-
-    as ext1 ovs-appctl netdev-dummy/receive ext1-vif1 $arp_reply
-
-    OVS_WAIT_UNTIL([
-        test `as $active_gw ovs-ofctl dump-flows br-int | grep table=66 | \
-grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
-    ])
-
-    # Packet to Expect at ext1 chassis, outside1 port
-    src_mac="000002010203"
-    dst_mac="f00000010204"
-    src_ip=`ip_to_hex 192 168 1 2`
-    dst_ip=`ip_to_hex 172 16 1 3`
-    expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000
-    echo $expected > ext1-vif1.expected
-    exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
-    echo $exp_gw_ip_garp >> ext1-vif1.expected
-
-    as $active_gw reset_pcap_file br-phys_n1 $active_gw/br-phys_n1
-    as $backup_gw reset_pcap_file br-phys_n1 $backup_gw/br-phys_n1
-    as ext1 reset_pcap_file ext1-vif1 ext1/vif1
-
-    # Resend packet from foo1 to outside1
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-    OVN_CHECK_PACKETS([ext1/vif1-tx.pcap], [ext1-vif1.expected])
-    $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $active_gw/br-phys_n1-tx.pcap  > packets
-    cat packets | grep $expected > exp
-    cat packets | grep $exp_gw_ip_garp | head -1 >> exp
-    AT_CHECK([cat exp], [0], [expout])
-
-    $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $backup_gw/br-phys_n1-tx.pcap  > packets
-    AT_CHECK([grep $expected packets | sort], [0], [])
-}
-
-test_ip_packet gw1 gw2
-
-ovn-nbctl --timeout=3 --wait=hv \
-    --id=@gc0 create Gateway_Chassis name=alice_gw1 \
-                                     chassis_name=gw1 \
-                                     priority=10 -- \
-    --id=@gc1 create Gateway_Chassis name=alice_gw2 \
-                                     chassis_name=gw2 \
-                                     priority=20 -- \
-    set Logical_Router_Port alice 'gateway_chassis=[@gc0,@gc1]'
-
-test_ip_packet gw2 gw1
-
-OVN_CLEANUP([hv1],[gw1],[gw2],[ext1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 1 LR with distributed router gateway port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR R1 that has switches foo (192.168.1.0/24) and
-# alice (172.16.1.0/24) connected to it.  The logical port
-# between R1 and alice has a "redirect-chassis" specified,
-# i.e. it is the distributed router gateway port.
-# Switch alice also has a localnet port defined.
-# An additional switch outside has a localnet port and the
-# same subnet as alice (172.16.1.0/24).
-
-# Physical network:
-# Three hypervisors hv[123].
-# hv1 hosts vif foo1.
-# hv2 is the "redirect-chassis" that hosts the distributed
-# router gateway port.
-# hv3 hosts vif outside1.
-# In order to show that connectivity works only through hv2,
-# an initial round of tests is run without any bridge-mapping
-# defined for the localnet on hv2.  These tests are expected
-# to fail.
-# Subsequent tests are run after defining the bridge-mapping
-# for the localnet on hv2. These tests are expected to succeed.
-
-# Create three hypervisors and create OVS ports corresponding
-# to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-int hv3-vif1 -- \
-    set interface hv3-vif1 external-ids:iface-id=outside1 \
-    options:tx_pcap=hv3/vif1-tx.pcap \
-    options:rxq_pcap=hv3/vif1-rx.pcap \
-    ofport-request=1
-
-# 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
-
-ovn-nbctl create Logical_Router name=R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add outside
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect alice to R1 as distributed router gateway port on hv2
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
-    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port outside1 in outside
-ovn-nbctl lsp-add outside outside1 \
--- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.3"
-
-# Create localnet port in alice
-ovn-nbctl lsp-add alice ln-alice
-ovn-nbctl lsp-set-addresses ln-alice unknown
-ovn-nbctl lsp-set-type ln-alice localnet
-ovn-nbctl lsp-set-options ln-alice network_name=phys
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Create bridge-mappings on hv1 and hv3, leaving hv2 for later
-as hv1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-as hv3 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-ovn-sbctl list chassis
-ovn-sbctl list encap
-echo "------ Gateway_Chassis dump (SBDB) -------"
-ovn-sbctl list Gateway_Chassis
-echo "------ Port_Binding chassisredirect -------"
-ovn-sbctl find Port_Binding type=chassisredirect
-echo "-------------------------------------------"
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-echo "------ hv3 dump ----------"
-as hv3 ovs-ofctl show br-int
-as hv3 ovs-ofctl dump-flows br-int
-echo "--------------------------"
-
-
-# Check that redirect mapping is programmed only on hv2
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=33 | grep =0x3,metadata=0x1 | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=33 | grep =0x3,metadata=0x1 | grep load:0x2- | wc -l], [0], [1
-])
-# Check that hv1 sends chassisredirect port traffic to hv2
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 | grep =0x3,metadata=0x1 | grep output | wc -l], [0], [1
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=32 | grep =0x3,metadata=0x1 | wc -l], [0], [0
-])
-# Check that arp reply on distributed gateway port is only programmed on hv2
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep arp | grep load:0x2- | grep =0x2,metadata=0x1 | wc -l], [0], [1
-])
-
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-
-: > hv2-vif1.expected
-: > hv3-vif1.expected
-
-# test_arp INPORT SHA SPA TPA [REPLY_HA]
-#
-# Causes a packet to be received on INPORT.  The packet is an ARP
-# request with SHA, SPA, and TPA as specified.  If REPLY_HA is provided, then
-# it should be the hardware address of the target to expect to receive in an
-# ARP reply; otherwise no reply is expected.
-#
-# INPORT is an logical switch port number, e.g. 11 for vif11.
-# SHA and REPLY_HA are each 12 hex digits.
-# SPA and TPA are each 8 hex digits.
-test_arp() {
-    local hv=$1 inport=$2 sha=$3 spa=$4 tpa=$5 reply_ha=$6
-    local request=ffffffffffff${sha}08060001080006040001${sha}${spa}ffffffffffff${tpa}
-    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
-
-    if test X$reply_ha != X; then
-        # Expect to receive the reply, if any.
-        local reply=${sha}${reply_ha}08060001080006040002${reply_ha}${tpa}${sha}${spa}
-        echo $reply >> hv${hv}-vif$inport.expected
-    fi
-}
-
-rtr_ip=$(ip_to_hex 172 16 1 1)
-foo_ip=$(ip_to_hex 192 168 1 2)
-outside_ip=$(ip_to_hex 172 16 1 3)
-
-echo $rtr_ip
-echo $foo_ip
-echo $outside_ip
-
-# ARP for router IP address from outside1, no response expected
-test_arp 3 1 f00000010204 $outside_ip $rtr_ip
-
-# Now check the packets actually received against the ones expected.
-OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
-
-# Send ip packet between foo1 and outside1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 3`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-# Now check the packets actually received against the ones expected.
-OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
-
-# Now add bridge-mappings on hv2, which should make everything work
-as hv2 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-# Wait until the patch ports are created in hv2 to connect br-int to br-phys
-OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
-grep "Port patch-br-int-to-ln-alice" | wc -l`])
-
-# ARP for router IP address from outside1
-test_arp 3 1 f00000010204 $outside_ip $rtr_ip 000002010203
-
-# hv3-vif1.expected should also have the gw router port garp packet.
-exp_gw_ip_garp=ffffffffffff00000201020308060001080006040001000002010203ac100101000000000000ac100101
-echo $exp_gw_ip_garp >> hv3-vif1.expected
-
-# Now check the packets actually received against the ones expected.
-OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
-
-# Send ip packet between foo1 and outside1
-src_mac="f00000010203"
-dst_mac="000001010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 172 16 1 3`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-# Packet to Expect at outside1
-src_mac="000002010203"
-dst_mac="f00000010204"
-expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-echo "------ hv1 dump ----------"
-as hv1 ovs-ofctl show br-int
-as hv1 ovs-ofctl dump-flows br-int
-echo "------ hv2 dump ----------"
-as hv2 ovs-ofctl show br-int
-as hv2 ovs-ofctl dump-flows br-int
-echo "------ hv3 dump ----------"
-as hv3 ovs-ofctl show br-int
-as hv3 ovs-ofctl dump-flows br-int
-echo "----------------------------"
-
-echo $expected >> hv3-vif1.expected
-OVN_CHECK_PACKETS([hv3/vif1-tx.pcap], [hv3-vif1.expected])
-
-#Check ovn-trace over "chassisredirect" port
-AT_CAPTURE_FILE([trace])
-ovn_trace () {
-    ovn-trace --all "$@" | tee trace | sed '1,/Minimal trace/d'
-}
-
-echo 'ip.ttl--;' > expout
-echo 'eth.src = 00:00:02:01:02:03;' >> expout
-echo 'eth.dst = f0:00:00:01:02:04;' >> expout
-echo 'output("ln-alice");' >> expout
-AT_CHECK_UNQUOTED([ovn_trace foo 'inport == "foo1" && eth.src == f0:00:00:01:02:03 && eth.dst == 00:00:01:01:02:03 && ip4.src == 192.168.1.2 && ip4.dst == 172.16.1.3 && ip.ttl == 0xff'], [0], [expout])
-
-# Create logical port alice1 in alice on hv1
-as hv1 ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=1
-
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.4"
-
-# Create logical port foo2 in foo on hv2
-as hv2 ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=foo2 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-ovn-nbctl lsp-add foo foo2 \
--- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-: > hv1-vif2.expected
-
-# Send ip packet between alice1 and foo2
-src_mac="f00000010205"
-dst_mac="000002010203"
-src_ip=`ip_to_hex 172 16 1 4`
-dst_ip=`ip_to_hex 192 168 1 3`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif2 $packet
-
-# Packet to Expect at foo2
-src_mac="000001010203"
-dst_mac="f00000010206"
-src_ip=`ip_to_hex 172 16 1 4`
-dst_ip=`ip_to_hex 192 168 1 3`
-expected=${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000
-
-echo $expected >> hv2-vif1.expected
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [hv2-vif1.expected])
-
-AT_CHECK([ovn-sbctl --bare --columns _uuid find Port_Binding logical_port=cr-alice | wc -l], [0], [1
-])
-
-ovn-nbctl --timeout=3 --wait=sb remove Logical_Router_Port alice options redirect-chassis
-
-AT_CHECK([ovn-sbctl find Port_Binding logical_port=cr-alice | wc -l], [0], [0
-])
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- send gratuitous arp for NAT rules on distributed router])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-# Create logical switches
-ovn-nbctl ls-add ls0
-ovn-nbctl ls-add ls1
-# Create distributed router
-ovn-nbctl create Logical_Router name=lr0
-# Add distributed gateway port to distributed router
-ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.1/24 \
-    -- set Logical_Router_Port lrp0 options:redirect-chassis="hv2"
-ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
-    type=router options:router-port=lrp0 addresses="router"
-# Add router port to ls1
-ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
-ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
-    type=router options:router-port=lrp1 addresses="router"
-# Add logical ports for NAT rules
-ovn-nbctl lsp-add ls1 foo1 \
--- lsp-set-addresses foo1 "00:00:00:00:00:03 10.0.0.3"
-ovn-nbctl lsp-add ls1 foo2 \
--- lsp-set-addresses foo2 "00:00:00:00:00:04 10.0.0.4"
-# Add nat-addresses option
-ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
-# Add NAT rules
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.1 10.0.0.0/24])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 192.168.0.2 10.0.0.2])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.3 10.0.0.3 foo1 f0:00:00:00:00:03])
-AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 192.168.0.4 10.0.0.4 foo2 f0:00:00:00:00:04])
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-# Initially test with no bridge-mapping on hv2, expect to receive no packets
-
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-# Initially test with no bridge-mapping on hv3
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl --wait=hv lsp-set-options ln_port network_name=physnet1])
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-# Expect no packets when hv2 bridge-mapping is not present
-: > packets
-OVN_CHECK_PACKETS([hv1/snoopvif-tx.pcap], [packets])
-
-# Add bridge-mapping on hv2
-AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-
-# Wait until the patch ports are created in hv2 to connect br-int to br-phys
-OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | \
-grep "Port patch-br-int-to-ln_port" | wc -l`])
-
-# Wait for packets to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001"
-echo $expected > expout
-expected="fffffffffffff0000000000108060001080006040001f00000000001c0a80002000000000000c0a80002"
-echo $expected >> expout
-AT_CHECK([sort packets], [0], [expout])
-sort packets | cat
-
-# Temporarily remove nat-addresses option to avoid race conditions
-# due to GARP backoff
-ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses=""
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-as hv1 reset_pcap_file snoopvif hv1/snoopvif
-
-# Add OVS ports for foo1 and foo2 on hv3
-ovs-vsctl -- add-port br-int hv3-vif1 -- \
-    set interface hv3-vif1 external-ids:iface-id=foo1 \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv3-vif2 -- \
-    set interface hv3-vif2 external-ids:iface-id=foo2 \
-    ofport-request=2
-
-# Add bridge-mapping on hv3
-AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-
-# Wait until the patch ports are created in hv3 to connect br-int to br-phys
-OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-vsctl show | \
-grep "Port patch-br-int-to-ln_port" | wc -l`])
-
-# Re-add nat-addresses option
-ovn-nbctl lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
-
-# Wait for packets to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 250])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > packets
-garp_1="fffffffffffff0000000000308060001080006040001f00000000003c0a80003000000000000c0a80003"
-echo $garp_1 > expout
-garp_2="fffffffffffff0000000000408060001080006040001f00000000004c0a80004000000000000c0a80004"
-echo $garp_2 >> expout
-
-cat packets | grep $garp_1 | head -1 > exp
-cat packets | grep $garp_2 | head -1 >> exp
-AT_CHECK([cat exp], [0], [expout])
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-# VLAN traffic for external network redirected through distributed router
-# gateway port should use vlans(i.e input network vlan tag) across hypervisors
-# instead of tunneling.
-AT_SETUP([ovn -- vlan traffic for external network with distributed router gateway port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# # One LR R1 that has switches foo (192.168.1.0/24) and
-# # alice (172.16.1.0/24) connected to it.  The logical port
-# # between R1 and alice has a "redirect-chassis" specified,
-# # i.e. it is the distributed router gateway port(172.16.1.6).
-# # Switch alice also has a localnet port defined.
-# # An additional switch outside has the same subnet as alice
-# # (172.16.1.0/24), a localnet port and nexthop port(172.16.1.1)
-# # which will receive the packet destined for external network
-# # (i.e 8.8.8.8 as destination ip).
-
-# Physical network:
-# # Four hypervisors hv[1234].
-# # hv1 hosts vif foo1.
-# # hv2 is the "redirect-chassis" that hosts the distributed router gateway port.
-# # Later to test GARPs for the router port - foo, hv2 and hv4 are added to the ha_chassis_group
-# # hv3 hosts nexthop port vif outside1.
-# # All other tests connect hypervisors to network n1 through br-phys for tunneling.
-# # But in this test, hv1 won't connect to n1(and no br-phys in hv1), and
-# # in order to show vlans(instead of tunneling) used between hv1 and hv2,
-# # a new network n2 created and hv1 and hv2 connected to this network through br-ex.
-# # hv2 and hv3 are still connected to n1 network through br-phys.
-net_add n1
-
-# We are not calling ovn_attach for hv1, to avoid adding br-phys.
-# Tunneling won't work in hv1 as ovn-encap-ip is not added to any bridge in hv1
-sim_add hv1
-as hv1
-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,vxlan \
-    -- set Open_vSwitch . external-ids:ovn-encap-ip=192.168.0.1 \
-    -- add-br br-int \
-    -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \
-    -- set Open_vSwitch . external-ids:ovn-bridge-mappings=public:br-ex
-
-start_daemon ovn-controller
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
-
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-int hv3-vif1 -- \
-    set interface hv3-vif1 external-ids:iface-id=outside1 \
-    options:tx_pcap=hv3/vif1-tx.pcap \
-    options:rxq_pcap=hv3/vif1-rx.pcap \
-    ofport-request=1
-ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings="phys:br-phys"
-
-sim_add hv4
-as hv4
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.4
-ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings="public:br-ex,phys:br-phys"
-
-# Create network n2 for vlan connectivity between hv1 and hv2
-net_add n2
-
-as hv1
-ovs-vsctl add-br br-ex
-net_attach n2 br-ex
-
-as hv2
-ovs-vsctl add-br br-ex
-net_attach n2 br-ex
-
-as hv4
-ovs-vsctl add-br br-ex
-net_attach n2 br-ex
-
-OVN_POPULATE_ARP
-
-ovn-nbctl create Logical_Router name=R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add outside
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect alice to R1 as distributed router gateway port (172.16.1.6) on hv2
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.6/24 \
-    -- set Logical_Router_Port alice options:redirect-chassis="hv2"
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router \
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port outside1 in outside, which is a nexthop address
-# for 172.16.1.0/24
-ovn-nbctl lsp-add outside outside1 \
--- lsp-set-addresses outside1 "f0:00:00:01:02:04 172.16.1.1"
-
-# Set default gateway (nexthop) to 172.16.1.1
-ovn-nbctl lr-route-add R1 "0.0.0.0/0" 172.16.1.1 alice
-AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.6 192.168.1.1/24])
-ovn-nbctl set Logical_Switch_Port rp-alice options:nat-addresses=router
-
-ovn-nbctl lsp-add foo ln-foo
-ovn-nbctl lsp-set-addresses ln-foo unknown
-ovn-nbctl lsp-set-options ln-foo network_name=public
-ovn-nbctl lsp-set-type ln-foo localnet
-AT_CHECK([ovn-nbctl set Logical_Switch_Port ln-foo tag=2])
-
-# Create localnet port in alice
-ovn-nbctl lsp-add alice ln-alice
-ovn-nbctl lsp-set-addresses ln-alice unknown
-ovn-nbctl lsp-set-type ln-alice localnet
-ovn-nbctl lsp-set-options ln-alice network_name=phys
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-ovn-nbctl --wait=hv --timeout=3 sync
-
-# Check that there is a logical flow in logical switch foo's pipeline
-# to set the outport to rp-foo (which is expected).
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup | \
-grep rp-foo | grep -v is_chassis_resident | wc -l`])
-
-# Set the option 'reside-on-redirect-chassis' for foo
-ovn-nbctl set logical_router_port foo options:reside-on-redirect-chassis=true
-# Check that there is a logical flow in logical switch foo's pipeline
-# to set the outport to rp-foo with the condition is_chassis_redirect.
-ovn-sbctl dump-flows foo
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl dump-flows foo | grep ls_in_l2_lkup | \
-grep rp-foo | grep is_chassis_resident | wc -l`])
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list nat
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-ovn-sbctl list chassis
-echo "---------------------"
-
-for chassis in hv1 hv2 hv3; do
-    as $chassis
-    echo "------ $chassis dump ----------"
-    ovs-vsctl show br-int
-    ovs-ofctl show br-int
-    ovs-ofctl dump-flows br-int
-    echo "--------------------------"
-done
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-foo1_ip=$(ip_to_hex 192 168 1 2)
-gw_ip=$(ip_to_hex 172 16 1 6)
-dst_ip=$(ip_to_hex 8 8 8 8)
-nexthop_ip=$(ip_to_hex 172 16 1 1)
-
-foo1_mac="f00000010203"
-foo_mac="000001010203"
-gw_mac="000002010203"
-nexthop_mac="f00000010204"
-
-# Send ip packet from foo1 to 8.8.8.8
-src_mac="f00000010203"
-dst_mac="000001010203"
-packet=${foo_mac}${foo1_mac}08004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
-
-# Wait for GARPs announcing gw IP to arrive
-OVS_WAIT_UNTIL([
-    test `as hv2 ovs-ofctl dump-flows br-int | grep table=66 | \
-grep actions=mod_dl_dst:f0:00:00:01:02:04 | wc -l` -eq 1
-    ])
-
-# VLAN tagged packet with router port(192.168.1.1) MAC as destination MAC
-# is expected on bridge connecting hv1 and hv2
-expected=${foo_mac}${foo1_mac}8100000208004500001c0000000040110000${foo1_ip}${dst_ip}0035111100080000
-echo $expected > hv1-br-ex_n2.expected
-
-# Packet to Expect at outside1 i.e nexthop(172.16.1.1) port.
-# As connection tracking not enabled for this test, snat can't be done on the packet.
-# We still see foo1 as the source ip address. But source mac(gateway MAC) and
-# dest mac(nexthop mac) are properly configured.
-expected=${nexthop_mac}${gw_mac}08004500001c000000003f110100${foo1_ip}${dst_ip}0035111100080000
-echo $expected > hv3-vif1.expected
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-as hv1 reset_pcap_file br-ex_n2 hv1/br-ex_n2
-as hv3 reset_pcap_file hv3-vif1 hv3/vif1
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-sleep 2
-
-# On hv1, table 32 check that no packet goes via the tunnel port
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=32 \
-| grep "NXM_NX_TUN_ID" | grep -v n_packets=0 | wc -l], [0], [[0
-]])
-
-ip_packet() {
-    grep "1010203f00000010203"
-}
-
-# Check vlan tagged packet on the bridge connecting hv1 and hv2 with the
-# foo1's mac.
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-ex_n2-tx.pcap | ip_packet | uniq > hv1-br-ex_n2
-cat hv1-br-ex_n2.expected > expout
-AT_CHECK([sort hv1-br-ex_n2], [0], [expout])
-
-# Check expected packet on nexthop interface
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/vif1-tx.pcap | grep ${foo1_ip}${dst_ip} | uniq > hv3-vif1
-cat hv3-vif1.expected > expout
-AT_CHECK([sort hv3-vif1], [0], [expout])
-
-# Test the GARP for the router port ip - 192.168.1.1
-ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
-
-as hv1 reset_pcap_file hv1-vif1 hv1/vif1
-as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
-as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
-
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv2 30
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 20
-
-hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1`
-ovn-nbctl remove logical_router_port alice options redirect-chassis
-ovn-nbctl --wait=sb set logical_router_port alice ha_chassis_group=$hagrp1_uuid
-
-# When hv2 claims the gw router port cr-alice, it should send out
-# GARP for 192.168.1.1 and it should be received by foo1 on hv1.
-
-# foo1 (on hv1) should receive GARP without VLAN tag
-exp_garp_on_foo1="ffffffffffff00000101020308060001080006040001000001010203c0a80101000000000000c0a80101"
-echo $exp_garp_on_foo1 > foo1.expout
-
-# ovn-controller on hv2 should send garp with VLAN tag
-sent_garp="ffffffffffff0000010102038100000208060001080006040001000001010203c0a80101000000000000c0a80101"
-
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
-# Wait until we receive atleast 1 packet
-OVS_WAIT_UNTIL([test 1=`$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-ex_n2-tx.pcap | wc -l`])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-ex_n2-tx.pcap | head -1 > packets
-echo $sent_garp > expout
-AT_CHECK([cat packets], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv4/br-ex_n2-tx.pcap > empty
-AT_CHECK([cat empty], [0], [])
-
-# Make hv4 master
-as hv1 reset_pcap_file hv1-vif1 hv1/vif1
-as hv4 reset_pcap_file br-ex_n2 hv4/br-ex_n2
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 hv4 40
-
-# Wait till cr-alice is claimed by hv4
-hv4_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=hv4)
-# check that the chassis redirect port has been claimed by the gw1 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-alice | grep $hv4_chassis | wc -l], [0],[[1
-]])
-
-# Reset the pcap file for hv2/br-ex_n2. From now on ovn-controller in hv2
-# should not send GARPs for the router ports.
-as hv2 reset_pcap_file br-ex_n2 hv2/br-ex_n2
-
-echo $sent_garp > br-ex_n2.expout
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [foo1.expout])
-OVN_CHECK_PACKETS([hv4/br-ex_n2-tx.pcap], [br-ex_n2.expout])
-
-sleep 2
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-ex_n2-tx.pcap > empty
-AT_CHECK([cat empty], [0], [])
-
-OVN_CLEANUP([hv1],[hv2],[hv3], [hv4])
-AT_CLEANUP
-
-AT_SETUP([ovn -- IPv6 ND Router Solicitation responder])
-AT_KEYWORDS([ovn-nd_ra])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# In this test case we create 1 lswitch with 3 VIF ports attached,
-# and a lrouter connected to the lswitch.
-# We generate the Router solicitation packet and verify the Router Advertisement
-# reply packet from the ovn-controller.
-
-# Create hypervisor and logical switch lsw0, logical router lr0, attach lsw0
-# onto lr0, set Logical_Router_Port.ipv6_ra_configs:address_mode column to
-# 'slaac' to allow lrp0 send RA for SLAAC mode.
-ovn-nbctl ls-add lsw0
-ovn-nbctl lr-add lr0
-ovn-nbctl lrp-add lr0 lrp0 fa:16:3e:00:00:01 fdad:1234:5678::1/64
-ovn-nbctl set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode="slaac"
-ovn-nbctl \
-    -- lsp-add lsw0 lsp0 \
-    -- set Logical_Switch_Port lsp0 type=router \
-                     options:router-port=lrp0 \
-                     addresses='"fa:16:3e:00:00:01 fdad:1234:5678::1"'
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-ovn-nbctl lsp-add lsw0 lp1
-ovn-nbctl lsp-set-addresses lp1 "fa:16:3e:00:00:02 10.0.0.12 fdad:1234:5678:0:f816:3eff:fe:2"
-ovn-nbctl lsp-set-port-security lp1 "fa:16:3e:00:00:02 10.0.0.12 fdad:1234:5678:0:f816:3eff:fe:2"
-
-ovn-nbctl lsp-add lsw0 lp2
-ovn-nbctl lsp-set-addresses lp2 "fa:16:3e:00:00:03 10.0.0.13 fdad:1234:5678:0:f816:3eff:fe:3"
-ovn-nbctl lsp-set-port-security lp2 "fa:16:3e:00:00:03 10.0.0.13 fdad:1234:5678:0:f816:3eff:fe:3"
-
-ovn-nbctl lsp-add lsw0 lp3
-ovn-nbctl lsp-set-addresses lp3 "fa:16:3e:00:00:04 10.0.0.14 fdad:1234:5678:0:f816:3eff:fe:4"
-ovn-nbctl lsp-set-port-security lp3 "fa:16:3e:00:00:04 10.0.0.14 fdad:1234:5678:0:f816:3eff:fe:4"
-
-# Add ACL rule for ICMPv6 on lsw0
-ovn-nbctl acl-add lsw0 from-lport 1002 'ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp1" && ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp2" && ip6 && icmp6'  allow-related
-ovn-nbctl acl-add lsw0 to-lport 1002 'outport == "lp3" && ip6 && icmp6'  allow-related
-
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-ovs-vsctl -- add-port br-int hv1-vif3 -- \
-    set interface hv1-vif3 external-ids:iface-id=lp3 \
-    options:tx_pcap=hv1/vif3-tx.pcap \
-    options:rxq_pcap=hv1/vif3-rx.pcap \
-    ofport-request=3
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-# Make sure that ovn-controller has installed the corresponding OF Flow.
-OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
-
-# This shell function sends a Router Solicitation packet.
-# test_ipv6_ra INPORT SRC_MAC SRC_LLA ADDR_MODE MTU RA_PREFIX_OPT
-test_ipv6_ra() {
-    local inport=$1 src_mac=$2 src_lla=$3 addr_mode=$4 mtu=$5 prefix_opt=$6
-    local request=333300000002${src_mac}86dd6000000000103aff${src_lla}ff02000000000000000000000000000285000efc000000000101${src_mac}
-
-    local len=24
-    local mtu_opt=""
-    if test $mtu != 0; then
-        len=`expr $len + 8`
-        mtu_opt=05010000${mtu}
-    fi
-
-    if test ${#prefix_opt} != 0; then
-        prefix_opt=${prefix_opt}fdad1234567800000000000000000000
-        len=`expr $len + ${#prefix_opt} / 2`
-    fi
-
-    len=$(printf "%x" $len)
-    local lrp_mac=fa163e000001
-    local lrp_lla=fe80000000000000f8163efffe000001
-    local reply=${src_mac}${lrp_mac}86dd6000000000${len}3aff${lrp_lla}${src_lla}8600XXXXff${addr_mode}ffff00000000000000000101${lrp_mac}${mtu_opt}${prefix_opt}
-    echo $reply >> $inport.expected
-
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $request
-}
-
-AT_CAPTURE_FILE([ofctl_monitor0.log])
-as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
-
-# MTU is not set and the address mode is set to slaac
-addr_mode=00
-default_prefix_option_config=030440c0ffffffffffffffff00000000
-src_mac=fa163e000002
-src_lla=fe80000000000000f8163efffe000002
-test_ipv6_ra 1 $src_mac $src_lla $addr_mode 0 $default_prefix_option_config
-
-# NXT_RESUME should be 1.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
-
-cat 1.expected | cut -c -112 > expout
-AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum.
-cat 1.expected | cut -c 117- > expout
-AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
-
-rm -f *.expected
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-reset_pcap_file hv1-vif3 hv1/vif3
-
-# Set the MTU to 1500
-ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500
-
-# Make sure that ovn-controller has installed the corresponding OF Flow.
-OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
-
-addr_mode=00
-default_prefix_option_config=030440c0ffffffffffffffff00000000
-src_mac=fa163e000003
-src_lla=fe80000000000000f8163efffe000003
-mtu=000005dc
-
-test_ipv6_ra 2 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
-
-# NXT_RESUME should be 2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap  > 2.packets
-
-cat 2.expected | cut -c -112 > expout
-AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum.
-cat 2.expected | cut -c 117- > expout
-AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
-
-rm -f *.expected
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-reset_pcap_file hv1-vif3 hv1/vif3
-
-# Set the address mode to dhcpv6_stateful
-ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateful
-# Make sure that ovn-controller has installed the corresponding OF Flow.
-OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
-
-addr_mode=80
-default_prefix_option_config=03044080ffffffffffffffff00000000
-src_mac=fa163e000004
-src_lla=fe80000000000000f8163efffe000004
-mtu=000005dc
-
-test_ipv6_ra 3 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
-
-# NXT_RESUME should be 3.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif3-tx.pcap  > 3.packets
-
-cat 3.expected | cut -c -112 > expout
-AT_CHECK([cat 3.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum.
-cat 3.expected | cut -c 117- > expout
-AT_CHECK([cat 3.packets | cut -c 117-], [0], [expout])
-
-rm -f *.expected
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-reset_pcap_file hv1-vif3 hv1/vif3
-
-# Set the address mode to dhcpv6_stateless
-ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateless
-# Make sure that ovn-controller has installed the corresponding OF Flow.
-OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
-
-addr_mode=40
-default_prefix_option_config=030440c0ffffffffffffffff00000000
-src_mac=fa163e000002
-src_lla=fe80000000000000f8163efffe000002
-mtu=000005dc
-
-test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
-
-# NXT_RESUME should be 4.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
-
-cat 1.expected | cut -c -112 > expout
-AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum.
-cat 1.expected | cut -c 117- > expout
-AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
-
-rm -f *.expected
-reset_pcap_file hv1-vif1 hv1/vif1
-reset_pcap_file hv1-vif2 hv1/vif2
-reset_pcap_file hv1-vif3 hv1/vif3
-
-# Set the address mode to invalid.
-ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=invalid
-# Make sure that ovn-controller has not installed any OF Flow for IPv6 ND RA.
-OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
-
-addr_mode=40
-default_prefix_option_config=""
-src_mac=fa163e000002
-src_lla=fe80000000000000f8163efffe000002
-mtu=000005dc
-
-test_ipv6_ra 1 $src_mac $src_lla $addr_mode $mtu $default_prefix_option_config
-
-# NXT_RESUME should be 4 only.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > 1.packets
-AT_CHECK([cat 1.packets], [0], [])
-
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- /32 router IP address])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# 2 LS 'foo' and 'alice' connected via router R1.
-# R1 connects to 'alice' with a /32 IP address. We use static routes and
-# nexthop to push traffic to a logical port in switch 'alice'
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:00:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo type=router \
-          options:router-port=foo addresses=\"00:00:00:01:02:03\"
-
-# Connect alice to R1.
-ovn-nbctl lrp-add R1 alice 00:00:00:01:02:04 172.16.1.1/32
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-          type=router options:router-port=alice addresses=\"00:00:00:01:02:04\"
-
-# Create logical port foo1 in foo
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical port alice1 in alice
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 10.0.0.2"
-
-#install default route in R1 to use alice1's IP address as nexthop
-ovn-nbctl lr-route-add R1 0.0.0.0/0 10.0.0.2 alice
-
-# Create two hypervisor and create OVS ports corresponding to logical ports.
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=foo1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=alice1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-
-# 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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-# Send ip packets between foo1 and alice1
-src_mac="f00000010203"
-dst_mac="000000010203"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 10 0 0 2`
-packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-
-# Send the first packet to trigger a ARP response and population of
-# mac_bindings table.
-as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding ip="10.0.0.2" | wc -l` -gt 0])
-ovn-nbctl --wait=hv sync
-
-# Packet to Expect at 'alice1'
-src_mac="000000010204"
-dst_mac="f00000010204"
-src_ip=`ip_to_hex 192 168 1 2`
-dst_ip=`ip_to_hex 10 0 0 2`
-echo "${dst_mac}${src_mac}08004500001c000000003f110100${src_ip}${dst_ip}0035111100080000" > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 1 lport/HV, localport ports])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-# Add localport to the switch
-ovn-nbctl lsp-add ls1 lp01
-ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01
-ovn-nbctl lsp-set-type lp01 localport
-
-net_add n1
-
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-    ovs-vsctl add-port br-int vif01 -- \
-        set Interface vif01 external-ids:iface-id=lp01 \
-                              options:tx_pcap=hv${i}/vif01-tx.pcap \
-                              options:rxq_pcap=hv${i}/vif01-rx.pcap \
-                              ofport-request=${i}0
-
-    ovs-vsctl add-port br-int vif${i}1 -- \
-        set Interface vif${i}1 external-ids:iface-id=lp${i}1 \
-                              options:tx_pcap=hv${i}/vif${i}1-tx.pcap \
-                              options:rxq_pcap=hv${i}/vif${i}1-rx.pcap \
-                              ofport-request=${i}1
-
-    ovn-nbctl lsp-add ls1 lp${i}1
-    ovn-nbctl lsp-set-addresses lp${i}1 f0:00:00:00:00:${i}1
-    ovn-nbctl lsp-set-port-security lp${i}1 f0:00:00:00:00:${i}1
-
-        OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup])
-done
-
-ovn-nbctl --wait=sb sync
-ovn-sbctl dump-flows
-
-OVN_POPULATE_ARP
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    echo hv${1%?}
-}
-#
-# test_packet INPORT DST SRC ETHTYPE EOUT LOUT DEFHV
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  INPORT is specified as
-# logical switch port numbers, e.g. 11 for vif11.
-#
-# EOUT is the end-to-end output port, that is, where the packet will end up
-# after possibly bouncing through one or more localnet ports.  LOUT is the
-# logical output port, which might be a localnet port, as seen by ovn-trace
-# (which doesn't know what localnet ports are connected to and therefore can't
-# figure out the end-to-end answer).
-#
-# DEFHV is the default hypervisor from where the packet is going to be sent
-# if the source port is a localport.
-for i in 1 2; do
-    for j in 0 1; do
-        : > $i$j.expected
-    done
-done
-test_packet() {
-    local inport=$1 dst=$2 src=$3 eth=$4 eout=$5 lout=$6 defhv=$7
-    echo "$@"
-
-    # First try tracing the packet.
-    uflow="inport==\"lp$inport\" && eth.dst==$dst && eth.src==$src && eth.type==0x$eth"
-    if test $lout != drop; then
-        echo "output(\"$lout\");"
-    fi > expout
-    AT_CAPTURE_FILE([trace])
-    AT_CHECK([ovn-trace --all ls1 "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])
-
-    # Then actually send a packet, for an end-to-end test.
-    local packet=$(echo $dst$src | sed 's/://g')${eth}
-    hv=`vif_to_hv $inport`
-    # If hypervisor 0 (localport) use the defhv parameter
-    if test $hv = hv0; then
-        hv=$defhv
-    fi
-    vif=vif$inport
-    as $hv ovs-appctl netdev-dummy/receive $vif $packet
-    if test $eout != drop; then
-        echo $packet >> ${eout#lp}.expected
-    fi
-}
-
-
-# lp11 and lp21 are on different hypervisors
-test_packet 11 f0:00:00:00:00:21 f0:00:00:00:00:11 1121 lp21 lp21
-test_packet 21 f0:00:00:00:00:11 f0:00:00:00:00:21 2111 lp11 lp11
-
-# Both VIFs should be able to reach the localport on their own HV
-test_packet 11 f0:00:00:00:00:01 f0:00:00:00:00:11 1101 lp01 lp01
-test_packet 21 f0:00:00:00:00:01 f0:00:00:00:00:21 2101 lp01 lp01
-
-# Packet sent from localport on same hv should reach the vif
-test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 lp11 lp11 hv1
-test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 lp21 lp21 hv2
-
-# Packet sent from localport on different hv should be dropped
-test_packet 01 f0:00:00:00:00:21 f0:00:00:00:00:01 0121 drop lp21 hv1
-test_packet 01 f0:00:00:00:00:11 f0:00:00:00:00:01 0111 drop lp11 hv2
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2; do
-    for j in 0 1; do
-        OVN_CHECK_PACKETS([hv$i/vif$i$j-tx.pcap], [$i$j.expected])
-    done
-done
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- 1 LR with HA distributed router gateway port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-
-# create gateways with external network connectivity
-
-for i in 1 2; do
-    sim_add gw$i
-    as gw$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-done
-
-ovn-nbctl ls-add inside
-ovn-nbctl ls-add outside
-
-# create hypervisors with a vif port each to an internal network
-
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.1$i
-    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
-        set interface hv$i-vif1 external-ids:iface-id=inside$i \
-        options:tx_pcap=hv$i/vif1-tx.pcap \
-        options:rxq_pcap=hv$i/vif1-rx.pcap \
-        ofport-request=1
-
-        ovn-nbctl lsp-add inside inside$i \
-            -- lsp-set-addresses inside$i "f0:00:00:01:22:$i 192.168.1.10$i"
-
-done
-
-OVN_POPULATE_ARP
-
-ovn-nbctl create Logical_Router name=R1
-
-# Connect inside to R1
-ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
-    type=router options:router-port=inside \
-    -- lsp-set-addresses rp-inside router
-
-# Connect outside to R1 as distributed router gateway port on gw1+gw2
-ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
-
-ovn-nbctl --id=@gc0 create Gateway_Chassis \
-                    name=outside_gw1 chassis_name=gw1 priority=20 -- \
-          --id=@gc1 create Gateway_Chassis \
-                    name=outside_gw2 chassis_name=gw2 priority=10 -- \
-          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
-
-ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port rp-outside \
-    type=router options:router-port=outside \
-    -- lsp-set-addresses rp-outside router
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-ovn-nbctl --wait=hv --timeout=3 sync
-
-echo "---------NB dump-----"
-ovn-nbctl show
-echo "---------------------"
-ovn-nbctl list logical_router
-echo "---------------------"
-ovn-nbctl list logical_router_port
-echo "---------------------"
-
-echo "---------SB dump-----"
-ovn-sbctl list datapath_binding
-echo "---------------------"
-ovn-sbctl list port_binding
-echo "---------------------"
-ovn-sbctl dump-flows
-echo "---------------------"
-ovn-sbctl list chassis
-ovn-sbctl list encap
-echo "---------------------"
-echo "------ Gateway_Chassis dump (SBDB) -------"
-ovn-sbctl list Gateway_Chassis
-echo "------ Port_Binding chassisredirect -------"
-ovn-sbctl find Port_Binding type=chassisredirect
-echo "-------------------------------------------"
-
-# There should be one ha_chassis_group with the name "outside"
-ha_chassi_grp_name=`ovn-sbctl --bare --columns name find \
-ha_chassis_group name="outside"`
-
-AT_CHECK([test $ha_chassi_grp_name = outside])
-
-# There should be 2 ha_chassis rows in SB DB.
-AT_CHECK([ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | awk '{print $3}' \
-| grep '-' | wc -l ], [0], [2
-])
-
-ha_ch=`ovn-sbctl --bare --columns ha_chassis  find ha_chassis_group`
-# Trim the spaces.
-ha_ch=`echo $ha_ch | sed 's/ //g'`
-
-ha_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list ha_chassis | sort`
-do
-    ha_ch_list="$ha_ch_list $i"
-done
-
-# Trim the spaces.
-ha_ch_list=`echo $ha_ch_list | sed 's/ //g'`
-
-AT_CHECK([test "$ha_ch_list" = "$ha_ch"])
-
-for chassis in gw1 gw2 hv1 hv2; do
-    as $chassis
-    echo "------ $chassis dump ----------"
-    ovs-ofctl show br-int
-    ovs-ofctl dump-flows br-int
-    echo "--------------------------"
-done
-bfd_dump() {
-    for chassis in gw1 gw2 hv1 hv2; do
-        as $chassis
-        echo "------ $chassis dump (BFD)----"
-        echo "BFD (from $chassis):"
-        # dump BFD config and status to the other chassis
-        for chassis2 in gw1 gw2 hv1 hv2; do
-            if [[ "$chassis" != "$chassis2" ]]; then
-                echo " -> $chassis2:"
-                echo "   $(ovs-vsctl --bare --columns bfd,bfd_status find Interface name=ovn-$chassis2-0)"
-            fi
-        done
-        echo "--------------------------"
-    done
-}
-
-bfd_dump
-
-hv1_gw1_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw1-0)
-hv1_gw2_ofport=$(as hv1 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0)
-hv2_gw1_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw1-0)
-hv2_gw2_ofport=$(as hv2 ovs-vsctl --bare --columns ofport find Interface name=ovn-gw2-0)
-
-echo $hv1_gw1_ofport
-echo $hv1_gw2_ofport
-echo $hv2_gw1_ofport
-echo $hv2_gw2_ofport
-
-echo "--- hv1 ---"
-as hv1 ovs-ofctl dump-flows br-int table=32
-
-echo "--- hv2 ---"
-as hv2 ovs-ofctl dump-flows br-int table=32
-
-gw1_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw1)
-gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
-
-OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
-| wc -l], [0], [1
-])
-
-OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
-| wc -l], [0], [1
-])
-
-# make sure that flows for handling the outside router port reside on gw1
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# make sure ARP responder flows for outside router port reside on gw1 too
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
-grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0
-]])
-
-# check that the chassis redirect port has been claimed by the gw1 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
-]])
-
-hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
-hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
-
-exp_ref_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
-do
-    if test $i = $hv1_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    elif test $i = $hv2_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    fi
-done
-
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-
-# at this point, we invert the priority of the gw chassis between gw1 and gw2
-
-ovn-nbctl --id=@gc0 create Gateway_Chassis \
-                    name=outside_gw1 chassis_name=gw1 priority=10 -- \
-          --id=@gc1 create Gateway_Chassis \
-                    name=outside_gw2 chassis_name=gw2 priority=20 -- \
-          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
-
-
-# XXX: Let the change propagate down to the ovn-controllers
-ovn-nbctl --wait=hv --timeout=3 sync
-
-# we make sure that the hypervisors noticed, and inverted the slave ports
-OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
-| wc -l], [0], [1
-])
-
-OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
-| wc -l], [0], [1
-])
-
-# check that the chassis redirect port has been reclaimed by the gw2 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
-]])
-
-# check BFD enablement on tunnel ports from gw1 #########
-as gw1
-for chassis in gw2 hv1 hv2; do
-    echo "checking gw1 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-
-
-# check BFD enablement on tunnel ports from gw2 ##########
-as gw2
-for chassis in gw1 hv1 hv2; do
-    echo "checking gw2 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-
-# check BFD enablement on tunnel ports from hv1 ###########
-as hv1
-for chassis in gw1 gw2; do
-    echo "checking hv1 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-# make sure BFD is not enabled to hv2, we don't need it
-AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv2-0],[0],
-         [[
-]])
-
-
-# check BFD enablement on tunnel ports from hv2 ##########
-as hv2
-for chassis in gw1 gw2; do
-    echo "checking hv2 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-# make sure BFD is not enabled to hv1, we don't need it
-AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0],
-         [[
-]])
-
-# make sure that flows for handling the outside router port reside on gw2 now
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# disconnect GW2 from the network, GW1 should take over
-as gw2
-port=${sandbox}_br-phys
-as main ovs-vsctl del-port n1 $port
-
-bfd_dump
-
-# make sure that flows for handling the outside router port reside on gw2 now
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=25 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# check that the chassis redirect port has been reclaimed by the gw1 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
-]])
-
-ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-rx"=2000
-as gw2
-for chassis in gw1 hv1 hv2; do
-    echo "checking gw2 -> $chassis"
-    OVS_WAIT_UNTIL([
-    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
-    test "$bfd_cfg" = "enable=true min_rx=2000"
-])
-done
-ovn-nbctl --wait=hv set NB_Global . options:"bfd-min-tx"=1500
-for chassis in gw1 hv1 hv2; do
-    echo "checking gw2 -> $chassis"
-    OVS_WAIT_UNTIL([
-    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
-    test "$bfd_cfg" = "enable=true min_rx=2000 min_tx=1500"
-])
-done
-ovn-nbctl remove NB_Global . options "bfd-min-rx"
-ovn-nbctl --wait=hv set NB_Global . options:"bfd-mult"=5
-for chassis in gw1 hv1 hv2; do
-    echo "checking gw2 -> $chassis"
-    OVS_WAIT_UNTIL([
-    bfd_cfg=$(ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0)
-    test "$bfd_cfg" = "enable=true min_tx=1500 mult=5"
-])
-done
-
-# Delete the inside1 vif. The ref_chassis in ha_chassis_group shouldn't have
-# reference to hv1.
-as hv1 ovs-vsctl del-port hv1-vif1
-
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$hv2_ch_uuid" = "$ref_ch_list"])
-
-# Delete the inside2 vif.
-ovn-sbctl show
-
-echo "Deleting hv2-vif1"
-as hv2 ovs-vsctl del-port hv2-vif1
-
-# ref_chassis of ha_chassis_group should be empty
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     exp_ref_ch_list=""
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# Delete the Gateway_Chassis for lrp - outside
-ovn-nbctl clear Logical_Router_Port outside gateway_chassis
-
-# There shoud be no ha_chassis_group rows in SB DB.
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis_group | wc -l`])
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
-
-ovn-nbctl remove NB_Global . options "bfd-min-rx"
-ovn-nbctl remove NB_Global . options "bfd-min-tx"
-ovn-nbctl remove NB_Global . options "bfd-mult"
-
-# Now test with HA chassis group instead of Gateway chassis in NB DB
-ovn-nbctl --wait=sb ha-chassis-group-add hagrp1
-
-ovn-nbctl list ha_chassis_group
-ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1
-hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name=hagrp1`
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw1 30
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 20
-
-# ovn-northd should not create HA chassis group and HA chassis rows
-# unless the HA chassis group in OVN NB DB is associated to
-# a logical router port.
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list ha_chassis | wc -l`])
-
-# Associate hagrp1 to outside logical router port
-ovn-nbctl set Logical_Router_Port outside ha_chassis_group=$hagrp1_uuid
-
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns _uuid \
-find ha_chassis_group | wc -l`])
-
-OVS_WAIT_UNTIL([test 2 = `ovn-sbctl list ha_chassis | grep chassis | \
-grep -v chassis-name | wc -l`])
-
-OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv1_gw1_ofport,$hv1_gw2_ofport \
-| wc -l], [0], [1
-])
-
-OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv2_gw1_ofport,$hv2_gw2_ofport \
-| wc -l], [0], [1
-])
-
-# make sure that flows for handling the outside router port reside on gw1
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# make sure ARP responder flows for outside router port reside on gw1 too
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=9 | \
-grep arp_tpa=192.168.0.101 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=9 | grep arp_tpa=192.168.0.101 | wc -l], [0], [[0
-]])
-
-# check that the chassis redirect port has been claimed by the gw1 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
-]])
-
-# Re add the ovs ports.
-for i in 1 2; do
-    as hv$i
-    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
-        set interface hv$i-vif1 external-ids:iface-id=inside$i \
-        options:tx_pcap=hv$i/vif1-tx.pcap \
-        options:rxq_pcap=hv$i/vif1-rx.pcap \
-        ofport-request=1
-done
-
-hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
-hv2_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv2"`
-
-exp_ref_ch_list=''
-for i in `ovn-sbctl --bare --columns _uuid list chassis | sort`
-do
-    if test $i = $hv1_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    elif test $i = $hv2_ch_uuid; then
-        exp_ref_ch_list="${exp_ref_ch_list}$i"
-    fi
-done
-
-OVS_WAIT_UNTIL(
-    [ref_ch_list=`ovn-sbctl --bare --columns ref_chassis find ha_chassis_group | sort`
-     # Trim the spaces.
-     ref_ch_list=`echo $ref_ch_list | sed 's/ //g'`
-     test "$exp_ref_ch_list" = "$ref_ch_list"])
-
-# Increase the priority of gw2
-ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 gw2 40
-
-OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv1_gw2_ofport,$hv1_gw1_ofport \
-| wc -l], [0], [1
-])
-
-OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=32 | \
-grep active_backup | grep slaves:$hv2_gw2_ofport,$hv2_gw1_ofport \
-| wc -l], [0], [1
-])
-
-# check that the chassis redirect port has been reclaimed by the gw2 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw2_chassis | wc -l], [0],[[1
-]])
-
-# check BFD enablement on tunnel ports from gw1 #########
-as gw1
-for chassis in gw2 hv1 hv2; do
-    echo "checking gw1 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-
-# check BFD enablement on tunnel ports from gw2 ##########
-as gw2
-for chassis in gw1 hv1 hv2; do
-    echo "checking gw2 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-
-# check BFD enablement on tunnel ports from hv1 ###########
-as hv1
-for chassis in gw1 gw2; do
-    echo "checking hv1 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-# make sure BFD is not enabled to hv2, we don't need it
-AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv2-0],[0],
-         [[
-]])
-
-# check BFD enablement on tunnel ports from hv2 ##########
-as hv2
-for chassis in gw1 gw2; do
-    echo "checking hv2 -> $chassis"
-    AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-$chassis-0],[0],
-             [[enable=true
-]])
-done
-# make sure BFD is not enabled to hv1, we don't need it
-AT_CHECK([ovs-vsctl --bare --columns bfd find Interface name=ovn-hv1-0],[0],
-         [[
-]])
-
-# make sure that flows for handling the outside router port reside on gw2 now
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# disconnect GW2 from the network, GW1 should take over
-as gw2
-port=${sandbox}_br-phys
-as main ovs-vsctl del-port n1 $port
-
-bfd_dump
-
-# make sure that flows for handling the outside router port reside on gw2 now
-OVS_WAIT_UNTIL([as gw1 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[1
-]])
-OVS_WAIT_UNTIL([as gw2 ovs-ofctl dump-flows br-int table=24 | \
-grep 00:00:02:01:02:04 | wc -l], [0], [[0
-]])
-
-# check that the chassis redirect port has been reclaimed by the gw1 chassis
-OVS_WAIT_UNTIL([ovn-sbctl --columns chassis --bare find Port_Binding \
-logical_port=cr-outside | grep $gw1_chassis | wc -l], [0],[[1
-]])
-
-OVN_CLEANUP([gw1],[gw2],[hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA distributed router])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-ovn-nbctl ls-add ls0
-ovn-nbctl ls-add ls1
-ovn-nbctl create Logical_Router name=lr0
-ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24
-
-ovn-nbctl --id=@gc0 create Gateway_Chassis \
-                    name=outside_gw1 chassis_name=hv2 priority=10 -- \
-          --id=@gc1 create Gateway_Chassis \
-                    name=outside_gw2 chassis_name=hv3 priority=1 -- \
-          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
-
-ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \
-    type=router options:router-port=lrp0 addresses="router"
-ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24
-ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \
-    type=router options:router-port=lrp1 addresses="router"
-
-# Add NAT rules
-AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24])
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap])
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-
-sim_add hv3
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys])
-
-# Create a localnet port.
-AT_CHECK([ovn-nbctl lsp-add ls0 ln_port])
-AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown])
-AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet])
-AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1])
-
-# wait for earlier changes to take effect
-AT_CHECK([ovn-nbctl --timeout=3 --wait=hv sync], [0], [ignore])
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-as hv1 reset_pcap_file snoopvif hv1/snoopvif
-as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
-as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
-# add nat-addresses option
-ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
-
-# Wait for packets to be received through hv2.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-only_broadcast_from_lrp1() {
-    grep "fffffffffffff00000000001"
-}
-
-garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064"
-echo $garp > expout
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv1_snoop_tx
-echo "packets on hv1-snoopvif:"
-cat hv1_snoop_tx
-AT_CHECK([sort hv1_snoop_tx], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
-echo "packets on hv2 br-phys tx"
-cat hv2_br_phys_tx
-AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
-echo "packets on hv3 br-phys tx"
-cat hv3_br_phys_tx
-AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [])
-
-
-# at this point, we invert the priority of the gw chassis between hv2 and hv3
-
-ovn-nbctl --wait=hv \
-          --id=@gc0 create Gateway_Chassis \
-                    name=outside_gw1 chassis_name=hv2 priority=1 -- \
-          --id=@gc1 create Gateway_Chassis \
-                    name=outside_gw2 chassis_name=hv3 priority=10 -- \
-          set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]'
-
-
-as hv1 reset_pcap_file snoopvif hv1/snoopvif
-as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
-as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
-
-# Wait for packets to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq >  hv1_snoopvif_tx
-AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
-AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
-AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
-
-# change localnet port tag.
-AT_CHECK([ovn-nbctl set Logical_Switch_Port ln_port tag=2014])
-
-# wait for earlier changes to take effect
-OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-ofctl dump-flows br-int table=65 | \
-grep "actions=mod_vlan_vid:2014" | wc -l`
-])
-
-OVS_WAIT_UNTIL([test 1 = `as hv3 ovs-ofctl dump-flows br-int table=65 | \
-grep "actions=mod_vlan_vid:2014" | wc -l`
-])
-
-# update nat-addresses option
-ovn-nbctl --wait=hv clear logical_switch_port lrp0-rp options
-
-#Wait until the Port_Binding.nat_addresses is cleared.
-OVS_WAIT_UNTIL([test 0 = `ovn-sbctl --bare --columns nat_addresses find port_binding \
-logical_port=lrp0-rp | grep is_chassis | wc -l`])
-
-as hv1 reset_pcap_file snoopvif hv1/snoopvif
-as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1
-as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1
-
-ovn-nbctl --wait=hv lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router"
-
-#Wait until the Port_Binding.nat_addresses is set.
-OVS_WAIT_UNTIL([test 1 = `ovn-sbctl --bare --columns nat_addresses find port_binding \
-logical_port=lrp0-rp | grep is_chassis | wc -l`])
-
-# Wait for packets to be received.
-OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100])
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-garp="fffffffffffff00000000001810007de08060001080006040001f00000000001c0a80064000000000000c0a80064"
-echo $garp > expout
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq >  hv1_snoopvif_tx
-AT_CHECK([sort hv1_snoopvif_tx], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv3_br_phys_tx
-AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros | only_broadcast_from_lrp1 | uniq > hv2_br_phys_tx
-AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [])
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ensure one gw controller restart in HA doesn't bounce the master])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-
-# create two gateways with external network connectivity
-for i in 1 2; do
-    sim_add gw$i
-    as gw$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-done
-
-ovn-nbctl ls-add inside
-ovn-nbctl ls-add outside
-
-# create one hypervisors with a vif port the internal network
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.11
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=inside1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovn-nbctl lsp-add inside inside1 \
-        -- lsp-set-addresses inside1 "f0:00:00:01:22:01 192.168.1.101"
-
-
-OVN_POPULATE_ARP
-
-ovn-nbctl create Logical_Router name=R1
-
-# Connect inside to R1
-ovn-nbctl lrp-add R1 inside 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add inside rp-inside -- set Logical_Switch_Port rp-inside \
-    type=router options:router-port=inside \
-    -- lsp-set-addresses rp-inside router
-
-# Connect outside to R1 as distributed router gateway port on gw1+gw2
-ovn-nbctl lrp-add R1 outside 00:00:02:01:02:04 192.168.0.101/24
-
-ovn-nbctl --id=@gc0 create Gateway_Chassis \
-                    name=outside_gw1 chassis_name=gw1 priority=20 -- \
-          --id=@gc1 create Gateway_Chassis \
-                    name=outside_gw2 chassis_name=gw2 priority=10 -- \
-          set Logical_Router_Port outside 'gateway_chassis=[@gc0,@gc1]'
-
-ovn-nbctl lsp-add outside rp-outside -- set Logical_Switch_Port rp-outside \
-    type=router options:router-port=outside \
-    -- lsp-set-addresses rp-outside router
-
-# Create localnet port in outside
-ovn-nbctl lsp-add outside ln-outside
-ovn-nbctl lsp-set-addresses ln-outside unknown
-ovn-nbctl lsp-set-type ln-outside localnet
-ovn-nbctl lsp-set-options ln-outside network_name=phys
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-ovn-nbctl --wait=hv --timeout=3 sync
-
-# currently when ovn-controller is restarted, the old entry is deleted
-# and a new one is created, which leaves the Gateway_Chassis with
-# an empty chassis for a while. NOTE: restarting ovn-controller in tests
-# doesn't have the same effect because "name" is conserved, and the
-# Chassis entry is not replaced.
-
-> gw1/ovn-controller.log
-
-gw2_chassis=$(ovn-sbctl --bare --columns=_uuid find Chassis name=gw2)
-ovn-sbctl destroy Chassis $gw2_chassis
-
-OVS_WAIT_UNTIL([test 0 = `grep -c "Releasing lport" gw1/ovn-controller.log`])
-
-OVN_CLEANUP([gw1],[gw2],[hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- IPv6 Neighbor Solicitation for unknown MAC])
-AT_KEYWORDS([ovn-nd_ns for unknown mac])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add sw0_ip6
-ovn-nbctl lsp-add sw0_ip6 sw0_ip6-port1
-ovn-nbctl lsp-set-addresses sw0_ip6-port1 \
-"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
-
-ovn-nbctl lsp-set-port-security sw0_ip6-port1 \
-"50:64:00:00:00:02 aef0::5264:00ff:fe00:0002"
-
-ovn-nbctl lr-add lr0_ip6
-ovn-nbctl lrp-add lr0_ip6 lrp0_ip6 00:00:00:00:af:01 aef0:0:0:0:0:0:0:0/64
-ovn-nbctl lsp-add sw0_ip6 lrp0_ip6-attachment
-ovn-nbctl lsp-set-type lrp0_ip6-attachment router
-ovn-nbctl lsp-set-addresses lrp0_ip6-attachment router
-ovn-nbctl lsp-set-options lrp0_ip6-attachment router-port=lrp0_ip6
-ovn-nbctl set logical_router_port lrp0_ip6 ipv6_ra_configs:address_mode=slaac
-
-ovn-nbctl ls-add public
-ovn-nbctl lsp-add public ln-public
-ovn-nbctl lsp-set-addresses ln-public unknown
-ovn-nbctl lsp-set-type ln-public localnet
-ovn-nbctl lsp-set-options ln-public network_name=phys
-
-ovn-nbctl lrp-add lr0_ip6 ip6_public 00:00:02:01:02:04 \
-2001:db8:1:0:200:02ff:fe01:0204/64 \
--- set Logical_Router_port ip6_public options:redirect-chassis="hv1"
-
-#install static route
-ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \
-ip_prefix="\:\:/0" nexthop="2001\:db8\:1\:0\:200\:02ff\:fe01\:1305" \
--- add Logical_Router lr0_ip6 static_routes @lrt
-
-ovn-nbctl lsp-add public rp-ip6_public -- set Logical_Switch_Port \
-rp-ip6_public  type=router options:router-port=ip6_public \
--- lsp-set-addresses rp-ip6_public router
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw0_ip6-port1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup])
-
-# There should be 2 Neighbor Advertisement flows for the router port
-# aef0:: ip address in logical switch pipeline with action nd_na_router.
-AT_CHECK([ovn-sbctl dump-flows sw0_ip6 | grep ls_in_arp_rsp | \
-grep "nd_na_router" | wc -l], [0], [2
-])
-
-# There should be 4 Neighbor Advertisement flows with action nd_na_router
-# in the router pipeline for the router lr0_ip6.
-AT_CHECK([ovn-sbctl dump-flows lr0_ip6 | grep nd_na_router | \
-wc -l], [0], [4
-])
-
-cr_uuid=`ovn-sbctl find port_binding logical_port=cr-ip6_public | grep _uuid | cut -f2 -d ":"`
-
-# There is only one chassis.
-chassis_uuid=`ovn-sbctl list chassis | grep _uuid | cut -f2 -d ":"`
-OVS_WAIT_UNTIL([test $chassis_uuid = `ovn-sbctl get port_binding $cr_uuid chassis`])
-
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-# Test the IPv6 Neighbor Solicitation (NS) - nd_ns action for unknown MAC
-# addresses. ovn-controller should generate an IPv6 NS request for IPv6
-# packets whose MAC is unknown (in the ARP_REQUEST router pipeline stage.
-# test_ipv6 INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-# This function sends ipv6 packet
-test_ipv6() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local dst_mcast_mac=$6 mcast_node_ip=$7 nd_target=$8
-
-    local packet=${dst_mac}${src_mac}86dd6000000000083aff${src_ip}${dst_ip}
-    packet=${packet}8000000000000000
-
-    src_mac=000002010204
-    expected_packet=${dst_mcast_mac}${src_mac}86dd6000000000203aff${src_ip}
-    expected_packet=${expected_packet}${mcast_node_ip}8700XXXX00000000
-    expected_packet=${expected_packet}${nd_target}0101${src_mac}
-
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif${inport} $packet
-    rm -f ipv6_ns.expected
-    echo $expected_packet >> ipv6_ns.expected
-}
-
-src_mac=506400000002
-dst_mac=00000000af01
-src_ip=aef0000000000000526400fffe000002
-dst_ip=20010db800010000020002fffe010205
-dst_mcast_mac=3333ff010205
-mcast_node_ip=ff0200000000000000000001ff010205
-nd_target=20010db800010000020002fffe010205
-# Send an IPv6 packet. Generated IPv6 Neighbor solicitation packet
-# should be received by the ports attached to br-phys.
-test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
-$mcast_node_ip $nd_target
-
-OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
-OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
-trim_zeros > 1.packets
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
-trim_zeros > 2.packets
-
-cat ipv6_ns.expected | cut -c -112 > expout
-AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
-AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum
-cat ipv6_ns.expected | cut -c 117- > expout
-AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
-AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
-
-# Now send a packet with destination ip other than
-# 2001:db8:1:0:200:02ff:fe01:0204/64 prefix.
-reset_pcap_file br-phys_n1 hv1/br-phys_n1
-reset_pcap_file br-phys hv1/br-phys
-
-src_mac=506400000002
-dst_mac=00000000af01
-src_ip=aef0000000000000526400fffe000002
-dst_ip=20020ab8000100000200020000020306
-# multicast mac of the nexthop IP - 2001:db8:1:0:200:02ff:fe01:1305
-dst_mcast_mac=3333ff011305
-mcast_node_ip=ff0200000000000000000001ff011305
-nd_target=20010db800010000020002fffe011305
-test_ipv6 1 $src_mac $dst_mac $src_ip $dst_ip $dst_mcast_mac \
-$mcast_node_ip $nd_target
-
-OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys_n1-tx.pcap | cut -d " " -f1)])
-OVS_WAIT_WHILE([test 24 = $(wc -c hv1/br-phys-tx.pcap | cut -d " " -f1)])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap | \
-trim_zeros > 1.packets
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | \
-trim_zeros > 2.packets
-
-cat ipv6_ns.expected | cut -c -112 > expout
-AT_CHECK([cat 1.packets | cut -c -112], [0], [expout])
-AT_CHECK([cat 2.packets | cut -c -112], [0], [expout])
-
-# Skipping the ICMPv6 checksum
-cat ipv6_ns.expected | cut -c 117- > expout
-AT_CHECK([cat 1.packets | cut -c 117-], [0], [expout])
-AT_CHECK([cat 2.packets | cut -c 117-], [0], [expout])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- options:requested-chassis for logical port])
-ovn_start
-
-net_add n1
-
-ovn-nbctl ls-add ls0
-ovn-nbctl lsp-add ls0 lsp0
-
-# create two hypervisors, each with one vif port
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.11
-ovs-vsctl -- add-port br-int hv1-vif0 -- \
-set Interface hv1-vif0 ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.12
-ovs-vsctl -- add-port br-int hv2-vif0 -- \
-set Interface hv2-vif0 ofport-request=1
-
-# Allow only chassis hv1 to bind logical port lsp0.
-ovn-nbctl lsp-set-options lsp0 requested-chassis=hv1
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-ovn-nbctl --wait=hv --timeout=3 sync
-
-# Retrieve hv1 and hv2 chassis UUIDs from southbound database
-ovn-sbctl wait-until chassis hv1
-ovn-sbctl wait-until chassis hv2
-hv1_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv1)
-hv2_uuid=$(ovn-sbctl --bare --columns _uuid find chassis name=hv2)
-
-# (1) Chassis hv2 should not bind lsp0 when requested-chassis is hv1.
-echo "verifying that hv2 does not bind lsp0 when hv2 physical/logical mapping is added"
-as hv2
-ovs-vsctl set interface hv2-vif0 external-ids:iface-id=lsp0
-
-OVS_WAIT_UNTIL([test 1 = $(grep -c "Not claiming lport lsp0" hv2/ovn-controller.log)])
-AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x], [0], [])
-
-# (2) Chassis hv2 should not add flows in OFTABLE_PHY_TO_LOG and OFTABLE_LOG_TO_PHY tables.
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
-
-# (3) Chassis hv1 should bind lsp0 when physical to logical mapping exists on hv1.
-echo "verifying that hv1 binds lsp0 when hv1 physical/logical mapping is added"
-as hv1
-ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
-
-OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0" hv1/ovn-controller.log)])
-AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
-
-# (4) Chassis hv1 should add flows in OFTABLE_PHY_TO_LOG and OFTABLE_LOG_TO_PHY tables.
-as hv1 ovs-ofctl dump-flows br-int
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
-
-# (5) Chassis hv1 should release lsp0 binding and chassis hv2 should bind lsp0 when
-# the requested chassis for lsp0 is changed from hv1 to hv2.
-echo "verifying that lsp0 binding moves when requested-chassis is changed"
-
-ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
-OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" hv1/ovn-controller.log)])
-OVS_WAIT_UNTIL([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv2_uuid"])
-
-# (6) Chassis hv2 should add flows and hv1 should not.
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
-
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- options:requested-chassis with hostname])
-
-ovn_start
-
-ovn-nbctl ls-add ls0
-ovn-nbctl lsp-add ls0 lsp0
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.11
-ovs-vsctl -- add-port br-int hv1-vif0 -- set Interface hv1-vif0 ofport-request=1
-
-ovn-sbctl wait-until chassis hv1
-hv1_hostname=$(ovn-sbctl --bare --columns hostname find Chassis name=hv1)
-echo "hv1_hostname=${hv1_hostname}"
-ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0 requested-chassis=${hv1_hostname}
-as hv1 ovs-vsctl set interface hv1-vif0 external-ids:iface-id=lsp0
-
-hv1_uuid=$(ovn-sbctl --bare --columns _uuid find Chassis name=hv1)
-echo "hv1_uuid=${hv1_uuid}"
-OVS_WAIT_UNTIL([test 1 = $(grep -c "Claiming lport lsp0" hv1/ovn-controller.log)])
-AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x"$hv1_uuid"], [0], [])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [0], [ignore])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep actions=output:1], [0], [ignore])
-
-ovn-nbctl --wait=hv --timeout=3 lsp-set-options lsp0 requested-chassis=non-existant-chassis
-OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" hv1/ovn-controller.log)])
-ovn-nbctl --wait=hv --timeout=3 sync
-AT_CHECK([test x$(ovn-sbctl --bare --columns chassis find port_binding logical_port=lsp0) = x], [0], [])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], [])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep output], [1], [])
-
-OVN_CLEANUP([hv1])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- IPv6 periodic RA])
-ovn_start
-
-# This test sets up two hypervisors.
-# hv1 and hv2 run ovn-controllers, and
-# each has a VIF connected to the same
-# logical switch in OVN. The logical
-# switch is connected to a logical
-# router port that is configured to send
-# periodic router advertisements.
-#
-# The reason for having two ovn-controller
-# hypervisors is to ensure that the
-# periodic RAs being sent by each ovn-controller
-# are kept to their local hypervisors. If the
-# packets are not kept local, then each port
-# will receive too many RAs.
-
-net_add n1
-sim_add hv1
-sim_add hv2
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-
-ovn-nbctl lr-add ro
-ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
-
-ovn-nbctl ls-add sw
-ovn-nbctl lsp-add sw sw-ro
-ovn-nbctl lsp-set-type sw-ro router
-ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
-ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
-ovn-nbctl lsp-add sw sw-p1
-ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02 aef0::200:ff:fe00:2"
-ovn-nbctl lsp-add sw sw-p2
-ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03 aef0::200:ff:fe00:3"
-
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=4
-ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=3
-
-for i in 1 2 ; do
-    as hv$i
-    ovs-vsctl -- add-port br-int hv$i-vif1 -- \
-        set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
-        options:tx_pcap=hv$i/vif1-tx.pcap \
-        options:rxq_pcap=hv$i/vif1-rx.pcap \
-        ofport-request=1
-done
-
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-
-}
-
-construct_expected_ra() {
-    local src_mac=000000000001
-    local dst_mac=333300000001
-    local src_addr=fe80000000000000020000fffe000001
-    local dst_addr=ff020000000000000000000000000001
-
-    local mtu=$1
-    local ra_mo=$2
-    local ra_prefix_la=$3
-
-    local slla=0101${src_mac}
-    local mtu_opt=""
-    if test $mtu != 0; then
-        mtu_opt=05010000${mtu}
-    fi
-    shift 3
-
-    local prefix=""
-    while [[ $# -gt 0 ]] ; do
-        local size=$1
-        local net=$2
-        prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
-        shift 2
-    done
-
-    local ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}
-    local icmp=8600XXXX${ra}
-
-    local ip_len=$(expr ${#icmp} / 2)
-    ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
-
-    local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
-    local eth=${dst_mac}${src_mac}86dd${ip}
-    local packet=${eth}
-    echo $packet >> expected
-}
-
-ra_test() {
-    construct_expected_ra $@
-
-    for i in hv1 hv2 ; do
-        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut -d " " -f1)])
-
-        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $i/vif1-tx.pcap > packets
-
-        cat expected | cut -c -112 > expout
-        AT_CHECK([cat packets | cut -c -112], [0], [expout])
-
-        # Skip ICMPv6 checksum.
-        cat expected | cut -c 117- > expout
-        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
-
-        rm -f packets
-        as $i reset_pcap_file $i-vif1 $i/vif1
-    done
-
-    rm -f expected
-}
-
-# Baseline test with no MTU
-ra_test 0 00 c0 40 aef00000000000000000000000000000
-
-# Now make sure an MTU option makes it
-ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:mtu=1500
-ra_test 000005dc 00 c0 40 aef00000000000000000000000000000
-
-# Now test for multiple network prefixes
-ovn-nbctl --wait=hv set Logical_Router_port ro-sw networks='aef0\:\:1/64 fd0f\:\:1/48'
-ra_test 000005dc 00 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
-
-# Test a different address mode now
-ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateful
-ra_test 000005dc 80 80 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
-
-# And the other address mode
-ovn-nbctl --wait=hv set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=dhcpv6_stateless
-ra_test 000005dc 40 c0 40 aef00000000000000000000000000000 30 fd0f0000000000000000000000000000
-
-OVN_CLEANUP([hv1],[hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ACL reject rule test])
-AT_KEYWORDS([acl-reject])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
-# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified.
-# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp destination
-# unreachable frame generated from ACL rule hit
-#
-# INPORT is a lport number, e.g. 11 for vif11.
-# HV is a hypervisor number
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC and IPV4_DST are each 8 hex digits.
-# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
-test_ip_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7
-    local exp_ip_chksum=$8 exp_icmp_chksum=$9
-    shift 9
-
-    local ip_ttl=ff
-    local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
-
-    local reply_icmp_ttl=ff
-    local icmp_type_code_response=0301
-    local icmp_data=00000000
-    local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ipv4_dst}${ipv4_src}${reply_icmp_payload}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_ipv6_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST EXP_ICMP_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6 packet with
-# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST as specified.
-# EXP_ICMP_CHKSUM is the icmp6 checksums of the icmp6 destination unreachable frame generated from ACL rule hit
-test_ipv6_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 exp_icmp_chksum=$7
-    shift 7
-
-    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
-    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}0000000000000000
-
-    local reply=${eth_src}${eth_dst}86dd6000000000303aff${ipv6_dst}${ipv6_src}0101${exp_icmp_chksum}00000000${ip6_hdr}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an TCP syn segment with
-# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, TCP_SPORT, TCP_DPORT, TCP_CHKSUM  as specified.
-# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of the tcp reset segment generated from ACL rule hit
-#
-# INPORT is an lport number, e.g. 11 for vif11.
-# HV is an hypervisor number
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC and IPV4_DST are each 8 hex digits.
-# TCP_SPORT and TCP_DPORT are 4 hex digits.
-# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4 hex digits
-test_tcp_syn_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7
-    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
-    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
-    shift 12
-
-    local ip_ttl=ff
-    local packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ipv4_dst}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
-
-    local tcp_rst_ttl=ff
-    local reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ipv4_dst}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# Create hypervisors hv[123].
-# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123] to hv3.
-# Add all of the vifs to a single logical switch sw0.
-
-net_add n1
-ovn-nbctl ls-add sw0
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2 3; do
-        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
-                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j 192.168.1.$i$j"
-
-        ovs-vsctl -- add-port br-int vif$i$j -- \
-                set interface vif$i$j \
-                external-ids:iface-id=sw0-p$i$j \
-                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
-                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
-                ofport-request=$i$j
-    done
-done
-
-OVN_POPULATE_ARP
-# allow some time for ovn-northd and ovn-controller to catch up.
-sleep 1
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-for i in 1 2 3; do
-    : > vif${i}1.expected
-done
-
-ovn-nbctl --log acl-add sw0 to-lport 1000 "outport == \"sw0-p12\"" reject
-ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p11\"" reject
-ovn-nbctl --log acl-add sw0 from-lport 1000 "inport == \"sw0-p21\"" reject
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-ovn-nbctl --timeout=3 --wait=hv sync
-
-test_ip_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 7d8d fcfe
-test_ip_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 7d8d fcfe
-test_ip_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 7d82 fcfe
-
-test_ipv6_packet 11 1 000000000011 000000000021 fe80000000000000020001fffe000001 fe80000000000000020001fffe000002 6183
-
-test_tcp_syn_packet 11 1 000000000011 000000000021 $(ip_to_hex 192 168 1 11) $(ip_to_hex 192 168 1 21) 0000 8b40 3039 0000 7d8d 4486
-test_tcp_syn_packet 21 2 000000000021 000000000011 $(ip_to_hex 192 168 1 21) $(ip_to_hex 192 168 1 11) 0000 8b40 3039 0000 7d8d 4486
-test_tcp_syn_packet 31 3 000000000031 000000000012 $(ip_to_hex 192 168 1 31) $(ip_to_hex 192 168 1 12) 0000 8b40 3039 0000 7d82 4486
-
-for i in 1 2 3; do
-    OVN_CHECK_PACKETS([hv$i/vif${i}1-tx.pcap], [vif${i}1.expected])
-done
-
-OVN_CLEANUP([hv1], [hv2], [hv3])
-AT_CLEANUP
-
-AT_SETUP([ovn -- Port Groups])
-AT_KEYWORDS([ovnpg])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-#
-# Three logical switches ls1, ls2, ls3.
-# One logical router lr0 connected to ls[123],
-# with nine subnets, three per logical switch:
-#
-#    lrp11 on ls1 for subnet 192.168.11.0/24
-#    lrp12 on ls1 for subnet 192.168.12.0/24
-#    lrp13 on ls1 for subnet 192.168.13.0/24
-#    ...
-#    lrp33 on ls3 for subnet 192.168.33.0/24
-#
-# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
-# digits are the subnet and the last digit distinguishes the VIF.
-#
-# This test will create two port groups and uses them in ACL.
-
-get_lsp_uuid () {
-    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
-}
-
-pg1_ports=
-pg2_ports=
-for i in 1 2 3; do
-    ovn-nbctl ls-add ls$i
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            ovn-nbctl \
-                -- lsp-add ls$i lp$i$j$k \
-                -- lsp-set-addresses lp$i$j$k \
-                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
-            # logical ports lp[12]?1 belongs to port group pg1
-            if test $i != 3 && test $k == 1; then
-                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
-            fi
-            # logical ports lp[23]?2 belongs to port group pg2
-            if test $i != 1 && test $k == 2; then
-                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
-            fi
-        done
-    done
-done
-
-ovn-nbctl lr-add lr0
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
-        ovn-nbctl \
-            -- lsp-add ls$i lrp$i$j-attachment \
-            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
-                             options:router-port=lrp$i$j \
-                             addresses='"00:00:00:00:ff:'$i$j'"'
-    done
-done
-
-ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
-ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
-
-# create ACLs on all lswitches to drop traffic from pg2 to pg1
-ovn-nbctl acl-add ls1 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
-ovn-nbctl acl-add ls2 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
-ovn-nbctl acl-add ls3 to-lport 1001 'outport == @pg1 && ip4.src == $pg2_ip4' drop
-
-# Physical network:
-#
-# Three hypervisors hv[123].
-# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
-# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
-# lp?3[123] all on hv3.
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    case $1 in dnl (
-        ?11) echo 1 ;; dnl (
-        ?12 | ?21 | ?22) echo 2 ;; dnl (
-        ?13 | ?23 | ?3?) echo 3 ;;
-    esac
-}
-
-# Given the name of a logical port, prints the name of its logical router
-# port, e.g. "vif_to_lrp 123" yields 12.
-vif_to_lrp() {
-    echo ${1%?}
-}
-
-# Given the name of a logical port, prints the name of its logical
-# switch, e.g. "vif_to_ls 123" yields 1.
-vif_to_ls() {
-    echo ${1%??}
-}
-
-net_add n1
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-done
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            hv=`vif_to_hv $i$j$k`
-                as hv$hv ovs-vsctl \
-                -- add-port br-int vif$i$j$k \
-                -- set Interface vif$i$j$k \
-                    external-ids:iface-id=lp$i$j$k \
-                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
-                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
-                    ofport-request=$i$j$k
-        done
-    done
-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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-#
-# This shell function causes a packet to be received on INPORT.  The packet's
-# content has Ethernet destination DST and source SRC (each exactly 12 hex
-# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
-# more) list the VIFs on which the packet should be received.  INPORT and the
-# OUTPORTs are specified as logical switch port numbers, e.g. 123 for vif123.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            : > $i$j$k.expected
-        done
-    done
-done
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    in_ls=`vif_to_ls $inport`
-    in_lrp=`vif_to_lrp $inport`
-    for outport; do
-        out_ls=`vif_to_ls $outport`
-        if test $in_ls = $out_ls; then
-            # Ports on the same logical switch receive exactly the same packet.
-            echo $packet
-        else
-            # Routing decrements TTL and updates source and dest MAC
-            # (and checksum).
-            out_lrp=`vif_to_lrp $outport`
-            echo f00000000${outport}00000000ff${out_lrp}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
-        fi >> $outport.expected
-    done
-}
-
-as hv1 ovs-vsctl --columns=name,ofport list interface
-as hv1 ovn-sbctl list port_binding
-as hv1 ovn-sbctl list datapath_binding
-as hv1 ovn-sbctl list port_group
-as hv1 ovn-sbctl list address_set
-as hv1 ovn-sbctl dump-flows
-as hv1 ovs-ofctl dump-flows br-int
-
-# Send IP packets between all pairs of source and destination ports,
-# packets matches ACL (pg2 to pg1) should be dropped
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-for is in 1 2 3; do
-  for js in 1 2 3; do
-    for ks in 1 2 3; do
-      bcast=
-      s=$is$js$ks
-      smac=f00000000$s
-      sip=`ip_to_hex 192 168 $is$js $ks`
-      for id in 1 2 3; do
-          for jd in 1 2 3; do
-              for kd in 1 2 3; do
-                d=$id$jd$kd
-                dip=`ip_to_hex 192 168 $id$jd $kd`
-                if test $is = $id; then dmac=f00000000$d; else dmac=00000000ff$is$js; fi
-                if test $d != $s; then unicast=$d; else unicast=; fi
-
-                # packets matches ACL should be dropped
-                if test $id != 3 && test $kd == 1; then
-                    if test $is != 1 && test $ks == 2; then
-                        unicast=
-                    fi
-                fi
-                test_ip $s $smac $dmac $sip $dip $unicast #1
-              done
-          done
-        done
-      done
-  done
-done
-
-# Allow some time for packet forwarding.
-# XXX This can be improved.
-sleep 1
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
-                              [$i$j$k.expected])
-        done
-    done
-done
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1], [hv2], [hv3])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ACLs on Port Groups])
-AT_KEYWORDS([ovnpg_acl])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-#
-# Three logical switches ls1, ls2, ls3.
-# One logical router lr0 connected to ls[123],
-# with nine subnets, three per logical switch:
-#
-#    lrp11 on ls1 for subnet 192.168.11.0/24
-#    lrp12 on ls1 for subnet 192.168.12.0/24
-#    lrp13 on ls1 for subnet 192.168.13.0/24
-#    ...
-#    lrp33 on ls3 for subnet 192.168.33.0/24
-#
-# 27 VIFs, 9 per LS, 3 per subnet: lp[123][123][123], where the first two
-# digits are the subnet and the last digit distinguishes the VIF.
-#
-# This test will create two port groups and ACLs will be applied on them.
-
-get_lsp_uuid () {
-    ovn-nbctl lsp-list ls${1%??} | grep lp$1 | awk '{ print $1 }'
-}
-
-pg1_ports=
-pg2_ports=
-for i in 1 2 3; do
-    ovn-nbctl ls-add ls$i
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            ovn-nbctl \
-                -- lsp-add ls$i lp$i$j$k \
-                -- lsp-set-addresses lp$i$j$k \
-                   "f0:00:00:00:0$i:$j$k 192.168.$i$j.$k"
-            # logical ports lp[12]?1 belongs to port group pg1
-            if test $i != 3 && test $k == 1; then
-                pg1_ports="$pg1_ports `get_lsp_uuid $i$j$k`"
-            fi
-            # logical ports lp[23]?2 belongs to port group pg2
-            if test $i != 1 && test $k == 2; then
-                pg2_ports="$pg2_ports `get_lsp_uuid $i$j$k`"
-            fi
-        done
-    done
-done
-
-ovn-nbctl lr-add lr0
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        ovn-nbctl lrp-add lr0 lrp$i$j 00:00:00:00:ff:$i$j 192.168.$i$j.254/24
-        ovn-nbctl \
-            -- lsp-add ls$i lrp$i$j-attachment \
-            -- set Logical_Switch_Port lrp$i$j-attachment type=router \
-                             options:router-port=lrp$i$j \
-                             addresses='"00:00:00:00:ff:'$i$j'"'
-    done
-done
-
-ovn-nbctl create Port_Group name=pg1 ports="$pg1_ports"
-ovn-nbctl create Port_Group name=pg2 ports="$pg2_ports"
-
-# create ACLs on pg1 to drop traffic from pg2 to pg1
-ovn-nbctl acl-add pg1 to-lport 1001 'outport == @pg1' drop
-ovn-nbctl --type=port-group acl-add pg1 to-lport 1002 \
-        'outport == @pg1 && ip4.src == $pg2_ip4' allow-related
-
-# Physical network:
-#
-# Three hypervisors hv[123].
-# lp?1[123] spread across hv[123]: lp?11 on hv1, lp?12 on hv2, lp?13 on hv3.
-# lp?2[123] spread across hv[23]: lp?21 and lp?22 on hv2, lp?23 on hv3.
-# lp?3[123] all on hv3.
-
-# Given the name of a logical port, prints the name of the hypervisor
-# on which it is located.
-vif_to_hv() {
-    case $1 in dnl (
-        ?11) echo 1 ;; dnl (
-        ?12 | ?21 | ?22) echo 2 ;; dnl (
-        ?13 | ?23 | ?3?) echo 3 ;;
-    esac
-}
-
-# Given the name of a logical port, prints the name of its logical router
-# port, e.g. "vif_to_lrp 123" yields 12.
-vif_to_lrp() {
-    echo ${1%?}
-}
-
-# Given the name of a logical port, prints the name of its logical
-# switch, e.g. "vif_to_ls 123" yields 1.
-vif_to_ls() {
-    echo ${1%??}
-}
-
-net_add n1
-for i in 1 2 3; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-done
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            hv=`vif_to_hv $i$j$k`
-                as hv$hv ovs-vsctl \
-                -- add-port br-int vif$i$j$k \
-                -- set Interface vif$i$j$k \
-                    external-ids:iface-id=lp$i$j$k \
-                    options:tx_pcap=hv$hv/vif$i$j$k-tx.pcap \
-                    options:rxq_pcap=hv$hv/vif$i$j$k-rx.pcap \
-                    ofport-request=$i$j$k
-        done
-    done
-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
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 1
-
-lsp_to_mac() {
-    echo f0:00:00:00:0${1:0:1}:${1:1:2}
-}
-
-lrp_to_mac() {
-    echo 00:00:00:00:ff:$1
-}
-
-# test_icmp INPORT SRC_MAC DST_MAC SRC_IP DST_IP ICMP_TYPE OUTPORT...
-#
-# This shell function causes a ICMP packet to be received on INPORT.
-# The OUTPORTs (zero or more) list the VIFs on which the packet should
-# be received.  INPORT and the OUTPORTs are specified as logical switch
-# port numbers, e.g. 123 for vif123.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            : > $i$j$k.expected
-        done
-    done
-done
-
-test_icmp() {
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
-    local packet="inport==\"lp$inport\" && eth.src==$src_mac &&
-                  eth.dst==$dst_mac && ip.ttl==64 && ip4.src==$src_ip
-                  && ip4.dst==$dst_ip && icmp4.type==$icmp_type &&
-                  icmp4.code==0"
-    shift; shift; shift; shift; shift; shift
-    hv=hv`vif_to_hv $inport`
-    as $hv ovs-appctl -t ovn-controller inject-pkt "$packet"
-    in_ls=`vif_to_ls $inport`
-    in_lrp=`vif_to_lrp $inport`
-    for outport; do
-        out_ls=`vif_to_ls $outport`
-        if test $in_ls = $out_ls; then
-            # Ports on the same logical switch receive exactly the same packet.
-            echo $packet | ovstest test-ovn expr-to-packets
-        else
-            # Routing decrements TTL and updates source and dest MAC
-            # (and checksum).
-            out_lrp=`vif_to_lrp $outport`
-            exp_smac=`lrp_to_mac $out_lrp`
-            exp_dmac=`lsp_to_mac $outport`
-            exp_packet="eth.src==$exp_smac && eth.dst==$exp_dmac &&
-                ip.ttl==63 && ip4.src==$src_ip && ip4.dst==$dst_ip &&
-                icmp4.type==$icmp_type && icmp4.code==0"
-            echo $exp_packet | ovstest test-ovn expr-to-packets
-
-        fi >> $outport.expected
-    done
-}
-
-as hv1 ovs-vsctl --columns=name,ofport list interface
-as hv1 ovn-sbctl list port_binding
-as hv1 ovn-sbctl list datapath_binding
-as hv1 ovn-sbctl list port_group
-as hv1 ovn-sbctl list address_set
-as hv1 ovn-sbctl dump-flows
-as hv1 ovs-ofctl dump-flows br-int
-
-# Send IP packets between all pairs of source and destination ports,
-# packets matches ACL1 but not ACL2 should be dropped
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-for is in 1 2 3; do
-  for js in 1 2 3; do
-    for ks in 1 2 3; do
-      bcast=
-      s=$is$js$ks
-      slsp_mac=`lsp_to_mac $s`
-      slrp_mac=`lrp_to_mac $is$js`
-      sip=192.168.$is$js.$ks
-      for id in 1 2 3; do
-          for jd in 1 2 3; do
-              for kd in 1 2 3; do
-                d=$id$jd$kd
-                dlsp_mac=`lsp_to_mac $d`
-                dlrp_mac=`lrp_to_mac $id$jd`
-                dip=192.168.$id$jd.$kd
-                if test $is = $id; then dmac=$dlsp_mac; else dmac=$slrp_mac; fi
-                if test $d != $s; then unicast=$d; else unicast=; fi
-
-                # packets matches ACL1 but not ACL2 should be dropped
-                if test $id != 3 && test $kd == 1; then
-                    if test $is == 1 || test $ks != 2; then
-                        unicast=
-                    fi
-                fi
-                # icmp request (type = 8)
-                test_icmp $s $slsp_mac $dmac $sip $dip 8 $unicast
-
-                # if packets are not dropped, test the return traffic (icmp echo)
-                # to make sure stateful works, too.
-                if test x$unicast != x; then
-                    if test $is = $id; then dmac=$slsp_mac; else dmac=$dlrp_mac; fi
-                    # icmp echo (type = 0)
-                    test_icmp $unicast $dlsp_mac $dmac $dip $sip 0 $s
-                fi
-              done
-          done
-        done
-      done
-  done
-done
-
-# Allow some time for packet forwarding.
-# XXX This can be improved.
-sleep 1
-
-# Now check the packets actually received against the ones expected.
-for i in 1 2 3; do
-    for j in 1 2 3; do
-        for k in 1 2 3; do
-            OVN_CHECK_PACKETS([hv`vif_to_hv $i$j$k`/vif$i$j$k-tx.pcap],
-                              [$i$j$k.expected])
-        done
-    done
-done
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1], [hv2], [hv3])
-AT_CLEANUP
-
-AT_SETUP([ovn -- Address Set generation from Port Groups (static addressing)])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-ovn-nbctl lsp-add ls1 lp1
-ovn-nbctl lsp-add ls1 lp2
-ovn-nbctl lsp-add ls1 lp3
-
-ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 10.0.0.1 2001:db8::1"
-ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 10.0.0.2 2001:db8::2"
-ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 10.0.0.3 2001:db8::3"
-
-ovn-nbctl create Port_Group name=pg1
-ovn-nbctl create Port_Group name=pg2
-
-ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports @p
-
-ovn-nbctl --wait=sb sync
-
-dnl Check if port group address sets were populated with ports' addresses
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
-         [0], [[["10.0.0.1", "10.0.0.2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
-         [0], [[["10.0.0.2", "10.0.0.3"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
-         [0], [[["2001:db8::1", "2001:db8::2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
-         [0], [[["2001:db8::2", "2001:db8::3"]]
-])
-
-ovn-nbctl --wait=sb lsp-set-addresses lp1 \
-    "02:00:00:00:00:01 10.0.0.11 2001:db8::11"
-
-dnl Check if updated address got propagated to the port group address sets
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
-         [0], [[["10.0.0.11", "10.0.0.2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
-         [0], [[["2001:db8::11", "2001:db8::2"]]
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- Address Set generation from Port Groups (dynamic addressing)])
-ovn_start
-
-ovn-nbctl ls-add ls1
-ovn-nbctl ls-add ls2
-ovn-nbctl ls-add ls3
-
-ovn-nbctl set Logical_Switch ls1 \
-    other_config:subnet=10.1.0.0/24 other_config:ipv6_prefix="2001:db8:1::"
-ovn-nbctl set Logical_Switch ls2 \
-    other_config:subnet=10.2.0.0/24 other_config:ipv6_prefix="2001:db8:2::"
-ovn-nbctl set Logical_Switch ls3 \
-    other_config:subnet=10.3.0.0/24 other_config:ipv6_prefix="2001:db8:3::"
-
-ovn-nbctl lsp-add ls1 lp1
-ovn-nbctl lsp-add ls2 lp2
-ovn-nbctl lsp-add ls3 lp3
-
-ovn-nbctl lsp-set-addresses lp1 "02:00:00:00:00:01 dynamic"
-ovn-nbctl lsp-set-addresses lp2 "02:00:00:00:00:02 dynamic"
-ovn-nbctl lsp-set-addresses lp3 "02:00:00:00:00:03 dynamic"
-
-ovn-nbctl create Port_Group name=pg1
-ovn-nbctl create Port_Group name=pg2
-
-ovn-nbctl --id=@p get Logical_Switch_Port lp1 -- add Port_Group pg1 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg1 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp2 -- add Port_Group pg2 ports @p
-ovn-nbctl --id=@p get Logical_Switch_Port lp3 -- add Port_Group pg2 ports @p
-
-ovn-nbctl --wait=sb sync
-
-dnl Check if port group address sets were populated with ports' addresses
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
-         [0], [[["10.1.0.2", "10.2.0.2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg2_ip4 addresses],
-         [0], [[["10.2.0.2", "10.3.0.2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
-         [0], [[["2001:db8:1::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg2_ip6 addresses],
-         [0], [[["2001:db8:2::ff:fe00:2", "2001:db8:3::ff:fe00:3"]]
-])
-
-ovn-nbctl --wait=sb set Logical_Switch ls1 \
-    other_config:subnet=10.11.0.0/24 other_config:ipv6_prefix="2001:db8:11::"
-
-dnl Check if updated address got propagated to the port group address sets
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip4 addresses],
-         [0], [[["10.11.0.2", "10.2.0.2"]]
-])
-AT_CHECK([ovn-sbctl get Address_Set pg1_ip6 addresses],
-         [0], [[["2001:db8:11::ff:fe00:1", "2001:db8:2::ff:fe00:2"]]
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ACL conjunction])
-ovn_start
-
-ovn-nbctl ls-add ls1
-
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4"
-
-ovn-nbctl lsp-add ls1 ls1-lp2 \
--- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
-
-ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.6"
-
-net_add n1
-sim_add hv1
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=2
-
-ovn-nbctl create Address_Set name=set1 \
-addresses=\"10.0.0.4\",\"10.0.0.5\",\"10.0.0.6\"
-ovn-nbctl create Address_Set name=set2 \
-addresses=\"10.0.0.7\",\"10.0.0.8\",\"10.0.0.9\"
-ovn-nbctl acl-add ls1 to-lport 1002 \
-'ip4 && ip4.src == $set1 && ip4.dst == $set1' allow
-ovn-nbctl acl-add ls1 to-lport 1001 \
-'ip4 && ip4.src == $set1 && ip4.dst == $set2' drop
-
-# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
-#
-# This shell function causes an ip packet to be received on INPORT.
-# The packet's content has Ethernet destination DST and source SRC
-# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
-# The OUTPORTs (zero or more) list the VIFs on which the packet should
-# be received.  INPORT and the OUTPORTs are specified as logical switch
-# port numbers, e.g. 11 for vif11.
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
-${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-    for outport; do
-        echo $packet >> $outport.expected
-    done
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-
-sip=`ip_to_hex 10 0 0 4`
-dip=`ip_to_hex 10 0 0 6`
-
-test_ip 1 f00000000001 f00000000002 $sip $dip 2
-
-cat 2.expected > expout
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-AT_CHECK([cat 2.packets], [0], [expout])
-
-# There should be total of 12 flows present with conjunction action and 2 flows
-# with conj match. Eg.
-# table=44, priority=2002,conj_id=2,metadata=0x1 actions=resubmit(,45)
-# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
-# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(2,2/2)
-# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,2/2)
-# priority=2002,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(2,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(3,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(3,2/2)
-# priority=2002,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(2,1/2)
-# priority=2002,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(2,1/2)
-# priority=2002,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(2,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(3,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(3,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(3,1/2)
-
-OVS_WAIT_UNTIL([test 12 = `as hv1 ovs-ofctl dump-flows br-int | \
-grep conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
-grep conj_id | wc -l`])
-
-as hv1 ovs-ofctl dump-flows br-int
-
-# Set the ip address for ls1-lp2 from set2 so that the drop ACL flow is hit.
-ovn-nbctl lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02 10.0.0.7 20.0.0.4"
-ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 10.0.0.7 20.0.0.4"
-
-reset_pcap_file hv1-vif2 hv1/vif2
-
-rm -f 2.packets
-
-sip=`ip_to_hex 10 0 0 4`
-dip=`ip_to_hex 10 0 0 7`
-
-test_ip 1 f00000000001 f00000000002 $sip $dip
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
-AT_CHECK([cat 2.packets], [0], [])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- TTL exceeded])
-AT_KEYWORDS([ttl-exceeded])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST IPV4_ROUTER IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
-# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM as specified and TTL set to 1.
-# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp time exceeded frame
-# generated by OVN logical router
-#
-# INPORT is a lport number, e.g. 11 for vif11.
-# HV is a hypervisor number
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC, IPV4_DST and IPV4_ROUTER are each 8 hex digits.
-# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
-test_ip_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_router=$7 ip_chksum=$8
-    local exp_ip_chksum=$9 exp_icmp_chksum=${10}
-    shift 10
-
-    local ip_ttl=01
-    local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}
-
-    local reply_icmp_ttl=fe
-    local icmp_type_code_response=0b00
-    local icmp_data=00000000
-    local reply_icmp_payload=${icmp_type_code_response}${exp_icmp_chksum}${icmp_data}
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_ROUTER EXP_ICMP_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6
-# packet with ETH_SRC, ETH_DST, IPV6_SRC and IPV6_DST as specified.
-# IPV6_ROUTER and EXP_ICMP_CHKSUM are the source IP and checksum of the icmpv6 ttl exceeded
-# packet sent by OVN logical router
-test_ip6_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
-    shift 8
-
-    local ip6_hdr=6000000000151101${ipv6_src}${ipv6_dst}
-    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}dbb8303900155bac6b646f65206676676e6d66720a
-
-    local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_router}${ipv6_src}0300${exp_icmp_chksum}00000000${ip6_hdr}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-for i in 1 2; do
-    net_add n$i
-    ovn-nbctl ls-add sw$i
-
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n$i br-phys 192.168.$i.1
-
-    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
-        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1 2001:db8:$i::11"
-
-    ovs-vsctl -- add-port br-int vif$i -- \
-        set interface vif$i \
-        external-ids:iface-id=sw$i-p${i}0 \
-            options:tx_pcap=hv$i/vif$i-tx.pcap \
-            options:rxq_pcap=hv$i/vif$i-rx.pcap \
-            ofport-request=$i
-done
-
-ovn-nbctl lr-add lr0
-for i in 1 2; do
-    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24 2001:db8:$i::1/64
-    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
-              -- set Logical_Switch_Port lrp$i-attachment type=router \
-                options:router-port=lrp$i addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
-done
-
-OVN_POPULATE_ARP
-# allow some time for ovn-northd and ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 1 254) 0000 7dae f4ff
-test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000200000000000000000011 20010db8000100000000000000000001 d461
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
-
-OVN_CLEANUP([hv1], [hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- router port unreachable])
-AT_KEYWORDS([router-port-unreachable])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# test_ip_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER L4_PROTCOL IP_CHKSUM EXP_IP_CHKSUM EXP_ICMP_CHKSUM EXP_ICMP_CODE
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv4 packet with
-# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, L4_PROTCOL, IP_CHKSUM as specified.
-# EXP_IP_CHKSUM and EXP_ICMP_CHKSUM are the ip and icmp checksums of the icmp frame generated by OVN logical router
-# EXP_ICMP_CODE are code and type of the icmp frame generated by OVN logical router
-#
-# INPORT is a lport number, e.g. 11 for vif11.
-# HV is a hypervisor number
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
-# IP_CHKSUM, EXP_IP_CHSUM and EXP_ICMP_CHKSUM are each 4 hex digits
-test_ip_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6 l4_proto=$7 ip_chksum=$8
-    local exp_ip_chksum=$9 exp_icmp_chksum=${10} exp_icmp_code=${11}
-    shift 11
-
-    local ip_ttl=ff
-    local packet=${eth_dst}${eth_src}08004500001400004000${ip_ttl}${l4_proto}${ip_chksum}${ipv4_src}${ip_router}
-
-    local reply_icmp_ttl=fe
-    local icmp_data=00000000
-    local reply_icmp_payload=${exp_icmp_code}${exp_icmp_chksum}${icmp_data}
-    local reply=${eth_src}${eth_dst}08004500001c00004000${reply_icmp_ttl}01${exp_ip_chksum}${ip_router}${ipv4_src}${reply_icmp_payload}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_tcp_syn_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_ROUTER IP_CHKSUM TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_IP_CHKSUM EXP_TCP_RST_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an TCP syn segment with
-# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_ROUTER, IP_CHKSUM, TCP_SPORT, TCP_DPORT, TCP_CHKSUM  as specified.
-# EXP_IP_CHKSUM and EXP_TCP_RST_CHKSUM are the ip and tcp checksums of the tcp reset segment generated by OVN logical router
-#
-# INPORT is an lport number, e.g. 11 for vif11.
-# HV is an hypervisor number
-# ETH_SRC and ETH_DST are each 12 hex digits.
-# IPV4_SRC and IPV4_ROUTER are each 8 hex digits.
-# TCP_SPORT and TCP_DPORT are 4 hex digits.
-# IP_CHKSUM, TCP_CHKSUM, EXP_IP_CHSUM and EXP_TCP_RST_CHKSUM are each 4 hex digits
-test_tcp_syn_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ip_router=$6 ip_chksum=$7
-    local tcp_sport=$8 tcp_dport=$9 tcp_chksum=${10}
-    local exp_ip_chksum=${11} exp_tcp_rst_chksum=${12}
-    shift 12
-
-    local ip_ttl=ff
-    local packet=${eth_dst}${eth_src}08004500002800004000${ip_ttl}06${ip_chksum}${ipv4_src}${ip_router}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
-
-    local tcp_rst_ttl=fe
-    local reply=${eth_src}${eth_dst}08004500002800004000${tcp_rst_ttl}06${exp_ip_chksum}${ip_router}${ipv4_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is a TCP syn segment with
-# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, TCP_SPORT, TCP_DPORT and TCP_CHKSUM as specified.
-# EXP_TCP_RST_CHKSUM is the tcp checksums of the tcp reset segment generated by OVN logical router
-test_tcp6_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_router=$6
-    local tcp_sport=$7 tcp_dport=$8 tcp_chksum=$9
-    local exp_tcp_rst_chksum=${10}
-    shift 10
-
-    local ip6_hdr=60000000001406ff${ipv6_src}${ipv6_router}
-    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${tcp_sport}${tcp_dport}000000010000000050027210${tcp_chksum}0000
-
-    local reply=${eth_src}${eth_dst}86dd60000000001406fe${ipv6_router}${ipv6_src}${tcp_dport}${tcp_sport}000000000000000150040000${exp_tcp_rst_chksum}0000
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-# test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
-#
-# Causes a packet to be received on INPORT of the hypervisor HV. The packet is an IPv6
-# packet with ETH_SRC, ETH_DST, IPV6_SRC, IPV6_DST, IPV6_PROTO, IPV6_LEN and DATA as specified.
-# EXP_ICMP_CODE and EXP_ICMP_CHKSUM are the code and checksum of the icmp6 packet sent by OVN logical router
-test_ip6_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_proto=$7 ipv6_len=$8 data=$9
-    local exp_icmp_code=${10} exp_icmp_chksum=${11}
-    shift 11
-
-    local ip6_hdr=60000000${ipv6_len}${ipv6_proto}ff${ipv6_src}${ipv6_dst}
-    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}${data}
-
-    local reply=${eth_src}${eth_dst}86dd6000000000303afe${ipv6_dst}${ipv6_src}${exp_icmp_code}${exp_icmp_chksum}00000000${ip6_hdr}
-    echo $reply >> vif$inport.expected
-
-    as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-for i in 1 2; do
-    net_add n$i
-    ovn-nbctl ls-add sw$i
-
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n$i br-phys 192.168.$i.1
-
-    ovn-nbctl lsp-add sw$i sw$i-p${i}0 -- \
-        lsp-set-addresses sw$i-p${i}0 "00:00:00:00:00:0$i 192.168.$i.1 2001:db8:$i::11"
-
-    ovs-vsctl -- add-port br-int vif$i -- \
-        set interface vif$i \
-        external-ids:iface-id=sw$i-p${i}0 \
-            options:tx_pcap=hv$i/vif$i-tx.pcap \
-            options:rxq_pcap=hv$i/vif$i-rx.pcap \
-            ofport-request=$i
-done
-
-ovn-nbctl lr-add lr0
-for i in 1 2; do
-    ovn-nbctl lrp-add lr0 lrp$i 00:00:00:00:ff:0$i 192.168.$i.254/24 2001:db8:$i::1/64
-    ovn-nbctl -- lsp-add sw$i lrp$i-attachment \
-              -- set Logical_Switch_Port lrp$i-attachment type=router \
-                options:router-port=lrp$i addresses='"00:00:00:00:ff:0'$i' 192.168.'$i'.254 2001:db8:'$i'::1"'
-done
-
-OVN_POPULATE_ARP
-# allow some time for ovn-northd and ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 11 0000 7dae fcfc 0303
-test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1 1) $(ip_to_hex 192 168 1 254) 84 0000 7dae fcfd 0302
-test_ip6_packet 1 1 000000000001 00000000ff01 20010db8000100000000000000000011 20010db8000100000000000000000001 11 0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 d570
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
-
-test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192 168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 7bae 4486
-test_ip6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 84 0004 01020304 0103 627e
-test_tcp6_packet 2 2 000000000002 00000000ff02 20010db8000200000000000000000011 20010db8000200000000000000000001 8b40 3039 0000 4486
-OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
-
-OVN_CLEANUP([hv1], [hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ovn-controller exit])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-# Logical network:
-# One Logical Router: ro, with two logical switches sw1 and sw2.
-# sw1 is for subnet 10.0.0.0/8
-# sw2 is for subnet 20.0.0.0/8
-# sw1 has a single port bound on hv1
-# sw2 has a single port bound on hv2
-
-ovn-nbctl lr-add ro
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add sw2
-
-sw1_ro_mac=00:00:10:00:00:01
-sw1_ro_ip=10.0.0.1
-sw2_ro_mac=00:00:20:00:00:01
-sw2_ro_ip=20.0.0.1
-sw1_p1_mac=00:00:10:00:00:02
-sw1_p1_ip=10.0.0.2
-sw2_p1_mac=00:00:20:00:00:02
-sw2_p1_ip=20.0.0.2
-
-ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
-ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
-ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro type=router \
-  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
-ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro type=router \
-  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
-
-ovn-nbctl lsp-add sw1 sw1-p1 \
--- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
-
-ovn-nbctl lsp-add sw2 sw2-p1 \
--- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-OVN_POPULATE_ARP
-
-sleep 1
-
-packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac &&
-       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-
-# Start by Sending the packet and make sure it makes it there as expected
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
-       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Stop ovn-controller on hv2
-as hv2 ovs-appctl -t ovn-controller exit
-
-# Now send the packet again. This time, it should not arrive.
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Start ovn-controller again just so OVN_CLEANUP doesn't complain
-as hv2 start_daemon ovn-controller
-
-OVN_CLEANUP([hv1],[hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- external logical port])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-sim_add hv1
-sim_add hv2
-sim_add hv3
-
-ovn-nbctl ls-add ls1
-ovn-nbctl lsp-add ls1 ls1-lp1 \
--- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 ae70::4"
-
-# Add a couple of external logical port
-ovn-nbctl lsp-add ls1 ls1-lp_ext1 \
--- lsp-set-addresses ls1-lp_ext1 "f0:00:00:00:00:03 10.0.0.6 ae70::6"
-ovn-nbctl lsp-set-port-security ls1-lp_ext1 \
-"f0:00:00:00:00:03 10.0.0.6 ae70::6"
-ovn-nbctl lsp-set-type ls1-lp_ext1 external
-
-ovn-nbctl lsp-add ls1 ls1-lp_ext2 \
--- lsp-set-addresses ls1-lp_ext2 "f0:00:00:00:00:04 10.0.0.7 ae70::7"
-ovn-nbctl lsp-set-port-security ls1-lp_ext2 \
-"f0:00:00:00:00:04 10.0.0.7 ae70::8"
-ovn-nbctl lsp-set-type ls1-lp_ext2 external
-
-d1="$(ovn-nbctl create DHCP_Options cidr=10.0.0.0/24 \
-options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
-\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"")"
-
-d2="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
-options="\"server_id\"=\"00:00:00:10:00:01\"")"
-
-ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 ${d1}
-ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext1 ${d1}
-ovn-nbctl lsp-set-dhcpv4-options ls1-lp_ext2 ${d1}
-
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d2}
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext1 ${d2}
-ovn-nbctl lsp-set-dhcpv6-options ls1-lp_ext2 ${d2}
-
-# Create a logical router and connect it to ls1
-ovn-nbctl lr-add lr0
-ovn-nbctl lrp-add lr0 lr0-ls1 a0:10:00:00:00:01 10.0.0.1/24
-ovn-nbctl lsp-add ls1 ls1-lr0
-ovn-nbctl set Logical_Switch_Port ls1-lr0 type=router \
-    options:router-port=lr0-ls1 addresses=router
-
-# Create HA chassis group
-ovn-nbctl ha-chassis-group-add hagrp1
-ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
-
-hagrp1_uuid=`ovn-nbctl --bare --columns _uuid find ha_chassis_group name="hagrp1"`
-
-# There should be 1 HA_Chassis rows with chassis sets
-OVS_WAIT_UNTIL([ovn-sbctl list ha_chassis | grep chassis | awk '{print $3}' \
-| grep '-' | wc -l ], [0], [1
-])
-
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-phys hv1-ext1 -- \
-    set interface hv1-ext1 options:tx_pcap=hv1/ext1-tx.pcap \
-    options:rxq_pcap=hv1/ext1-rx.pcap \
-    ofport-request=2
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-phys hv2-ext2 -- \
-    set interface hv2-ext2 options:tx_pcap=hv2/ext2-tx.pcap \
-    options:rxq_pcap=hv2/ext2-rx.pcap \
-    ofport-request=2
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-as hv3
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.3
-ovs-vsctl -- add-port br-phys hv3-ext3 -- \
-    set interface hv3-ext3 options:tx_pcap=hv3/ext3-tx.pcap \
-    options:rxq_pcap=hv3/ext3-rx.pcap \
-    ofport-request=2
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in hv1 and
-# hv2 as ha-chassis-group is not set and no localnet port added to ls1.
-AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \
-wc -l], [0], [0
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
-])
-
-hv1_uuid=$(ovn-sbctl list chassis hv1 | grep uuid | awk '{print $3}')
-hv2_uuid=$(ovn-sbctl list chassis hv2 | grep uuid | awk '{print $3}')
-hv3_uuid=$(ovn-sbctl list chassis hv3 | grep uuid | awk '{print $3}')
-
-# The port_binding row for ls1-lp_ext1 should have empty chassis
-chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-
-AT_CHECK([test x$chassis == x], [0], [])
-
-# Associate hagrp1 ha-chassis-group to ls1-lp_ext1
-ovn-nbctl --wait=hv set Logical_Switch_Port ls1-lp_ext1 \
-ha-chassis-group=$hagrp1_uuid
-
-# Get the hagrp1 uuid in SB DB.
-sb_hagrp1_uuid=`ovn-sbctl --bare --columns _uuid find ha_chassis_group \
-name="hagrp1"`
-
-# Wait till ls1-lp_ext1 port_binding has ha_chassis_group set
-OVS_WAIT_UNTIL(
-    [sb_pb_hagrp=`ovn-sbctl --bare --columns ha_chassis_group find \
-port_binding logical_port=ls1-lp_ext1`
-     test "$sb_pb_hagrp" = "$sb_hagrp1_uuid"])
-
-# No DHCPv4/v6 flows for the external port - ls1-lp_ext1 - 10.0.0.6 in hv1 and hv2
-# as no localnet port added to ls1 yet.
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
-])
-
-# Add the localnet port to the logical switch ls1
-ovn-nbctl lsp-add ls1 ln-public
-ovn-nbctl lsp-set-addresses ln-public unknown
-ovn-nbctl lsp-set-type ln-public localnet
-ovn-nbctl --wait=hv lsp-set-options ln-public network_name=phys
-
-ln_public_key=$(ovn-sbctl list port_binding ln-public | grep  tunnel_key | \
-awk '{print $3}')
-
-# The ls1-lp_ext1 should be bound to hv1 as only hv1 is part of the
-# ha chassis group.
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = "$hv1_uuid"])
-
-# There should be DHCPv4/v6 OF flows for the ls1-lp_ext1 port in hv1
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
-wc -l], [0], [3
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
-grep reg14=0x$ln_public_key | wc -l], [0], [1
-])
-
-# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv2
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0
-])
-
-# No DHCPv4/v6 flows for the external port - ls1-lp_ext2 - 10.0.0.7 in hv1 and
-# hv2 as requested-chassis option is not set.
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.07" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.07" | wc -l], [0], [0
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.07" | wc -l], [0], [0
-])
-
-as hv1
-ovs-vsctl show
-
-# This shell function sends a DHCP request packet
-# test_dhcp INPORT SRC_MAC DHCP_TYPE OFFER_IP ...
-test_dhcp() {
-    local inport=$1 src_mac=$2 dhcp_type=$3 offer_ip=$4 use_ip=$5
-    shift; shift; shift; shift; shift;
-    if test $use_ip != 0; then
-        src_ip=$1
-        dst_ip=$2
-        shift; shift;
-    else
-        src_ip=`ip_to_hex 0 0 0 0`
-        dst_ip=`ip_to_hex 255 255 255 255`
-    fi
-    local request=ffffffffffff${src_mac}0800451001100000000080110000${src_ip}${dst_ip}
-    # udp header and dhcp header
-    request=${request}0044004300fc0000
-    request=${request}010106006359aa760000000000000000000000000000000000000000${src_mac}
-    # client hardware padding
-    request=${request}00000000000000000000
-    # server hostname
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    # boot file name
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    request=${request}0000000000000000000000000000000000000000000000000000000000000000
-    # dhcp magic cookie
-    request=${request}63825363
-    # dhcp message type
-    request=${request}3501${dhcp_type}ff
-
-    local srv_mac=$1 srv_ip=$2 expected_dhcp_opts=$3
-    # total IP length will be the IP length of the request packet
-    # (which is 272 in our case) + 8 (padding bytes) + (expected_dhcp_opts / 2)
-    ip_len=`expr 280 + ${#expected_dhcp_opts} / 2`
-    udp_len=`expr $ip_len - 20`
-    ip_len=$(printf "%x" $ip_len)
-    udp_len=$(printf "%x" $udp_len)
-    # $ip_len var will be in 3 digits i.e 134. So adding a '0' before $ip_len
-    local reply=${src_mac}${srv_mac}080045100${ip_len}000000008011XXXX${srv_ip}${offer_ip}
-    # udp header and dhcp header.
-    # $udp_len var will be in 3 digits. So adding a '0' before $udp_len
-    reply=${reply}004300440${udp_len}0000020106006359aa760000000000000000
-    # your ip address
-    reply=${reply}${offer_ip}
-    # next server ip address, relay agent ip address, client mac address
-    reply=${reply}0000000000000000${src_mac}
-    # client hardware padding
-    reply=${reply}00000000000000000000
-    # server hostname
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    # boot file name
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    reply=${reply}0000000000000000000000000000000000000000000000000000000000000000
-    # dhcp magic cookie
-    reply=${reply}63825363
-    # dhcp message type
-    local dhcp_reply_type=02
-    if test $dhcp_type = 03; then
-        dhcp_reply_type=05
-    fi
-    reply=${reply}3501${dhcp_reply_type}${expected_dhcp_opts}00000000ff00000000
-    echo $reply >> ext1_v4.expected
-
-    as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport} $request
-}
-
-
-trim_zeros() {
-    sed 's/\(00\)\{1,\}$//'
-}
-
-# This shell function sends a DHCPv6 request packet
-# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
-# The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
-# packet should be received twice (one from ovn-controller and the other
-# from the "ovs-ofctl monitor br-int resume"
-test_dhcpv6() {
-    local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
-    local req_pkt_in_expected=$6
-    local request=ffffffffffff${src_mac}86dd00000000002a1101${src_lla}
-    # dst ip ff02::1:2
-    request=${request}ff020000000000000000000000010002
-    # udp header and dhcpv6 header
-    request=${request}02220223002affff${msg_code}010203
-    # Client identifier
-    request=${request}0001000a00030001${src_mac}
-    # IA-NA (Identity Association for Non Temporary Address)
-    request=${request}0003000c0102030400000e1000001518
-    shift; shift; shift; shift; shift;
-
-    local server_mac=000000100001
-    local server_lla=fe80000000000000020000fffe100001
-    local reply_code=07
-    if test $msg_code = 01; then
-        reply_code=02
-    fi
-    local msg_len=54
-    if test $offer_ip = 1; then
-        msg_len=28
-    fi
-    local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101
-    reply=${reply}${server_lla}${src_lla}
-
-    # udp header and dhcpv6 header
-    reply=${reply}0223022200${msg_len}ffff${reply_code}010203
-    # Client identifier
-    reply=${reply}0001000a00030001${src_mac}
-    # IA-NA
-    if test $offer_ip != 1; then
-        reply=${reply}0003002801020304ffffffffffffffff00050018${offer_ip}
-        reply=${reply}ffffffffffffffff
-    fi
-    # Server identifier
-    reply=${reply}0002000a00030001${server_mac}
-
-    echo $reply | trim_zeros >> ext${inport}_v6.expected
-    # The inport also receives the request packet since it is connected
-    # to the br-phys.
-    #echo $request >> ext${inport}_v6.expected
-
-    as hv1 ovs-appctl netdev-dummy/receive hv${inport}-ext${inport} $request
-}
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-AT_CAPTURE_FILE([ofctl_monitor0_hv1.log])
-as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv1.log
-
-AT_CAPTURE_FILE([ofctl_monitor0_hv2.log])
-as hv2 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv2.log
-
-AT_CAPTURE_FILE([ofctl_monitor0_hv3.log])
-as hv3 ovs-ofctl monitor br-int resume --detach --no-chdir \
---pidfile=ovs-ofctl0.pid 2> ofctl_monitor0_hv3.log
-
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-# Send DHCPDISCOVER.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-server_mac=ff1000000001
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
-$expected_dhcp_opts
-
-# NXT_RESUMEs should be 1 in hv1.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 0 in hv2.
-OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
-cat ext1_v4.expected | cut -c -48 > expout
-AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat ext1_v4.expected | cut -c 53- > expout
-AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
-
-# ovs-ofctl also resumes the packets and this causes other ports to receive
-# the DHCP request packet. So reset the pcap files so that its easier to test.
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-rm -f ext1_v4.expected
-rm -f ext1_v4.packets
-
-# Send DHCPv6 request
-src_mac=f00000000003
-src_lla=fe80000000000000f20000fffe000003
-offer_ip=ae700000000000000000000000000006
-test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
-
-# NXT_RESUMEs should be 2 in hv1.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 0 in hv2.
-OVS_WAIT_UNTIL([test 0 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
-sort > ext1_v6.packets
-cat ext1_v6.expected | cut -c -120 > expout
-AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
-# Skipping the UDP checksum
-cat ext1_v6.expected | cut -c 125- > expout
-AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
-
-rm -f ext1_v6.expected
-rm -f ext1_v6.packets
-
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-# Delete the ha-chassis hv1.
-ovn-nbctl ha-chassis-group-remove-chassis hagrp1 hv1
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = ""])
-
-# Add hv2 to the ha chassis group
-ovn-nbctl --wait=hv ha-chassis-group-add-chassis hagrp1 hv2 20
-
-ovn-sbctl list ha_chassis_group
-ovn-sbctl list ha_chassis
-
-ovn-sbctl find port_binding logical_port=ls1-lp_ext1
-
-# The ls1-lp_ext1 should be bound to hv2
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = "$hv2_uuid"])
-
-# There should be OF flows for DHCP4/v6 for the ls1-lp_ext1 port in hv2
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | grep reg14=0x$ln_public_key | \
-wc -l], [0], [3
-])
-AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
-grep reg14=0x$ln_public_key | wc -l], [0], [1
-])
-
-# There should be no DHCPv4/v6 flows for ls1-lp_ext1 on hv1
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep "0a.00.00.06" | wc -l], [0], [0
-])
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=20 | \
-grep controller | grep tp_src=546 | grep \
-"ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | \
-grep reg14=0x$ln_public_key | wc -l], [0], [0
-])
-
-# Send DHCPDISCOVER again for hv1/ext1. The DHCP response should come from
-# hv2 ovn-controller.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-server_mac=ff1000000001
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
-$expected_dhcp_opts
-
-# NXT_RESUMEs should be 2 in hv1.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 1 in hv2.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
-cat ext1_v4.expected | cut -c -48 > expout
-AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat ext1_v4.expected | cut -c 53- > expout
-AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
-
-# ovs-ofctl also resumes the packets and this causes other ports to receive
-# the DHCP request packet. So reset the pcap files so that its easier to test.
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-rm -f ext1_v4.expected
-
-# Send DHCPv6 request again
-src_mac=f00000000003
-src_lla=fe80000000000000f20000fffe000003
-offer_ip=ae700000000000000000000000000006
-test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip 1
-
-# NXT_RESUMEs should be 2 in hv1.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
-sort > ext1_v6.packets
-cat ext1_v6.expected | cut -c -120 > expout
-AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
-# Skipping the UDP checksum
-cat ext1_v6.expected | cut -c 125- > expout
-AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
-
-rm -f ext1_v6.expected
-rm -f ext1_v6.packets
-
-as hv1
-ovs-vsctl show
-reset_pcap_file hv1-ext1 hv1/ext1
-reset_pcap_file br-phys_n1 hv1/br-phys_n1
-reset_pcap_file br-phys hv1/br-phys
-
-as hv2
-ovs-vsctl show
-reset_pcap_file hv2-ext2 hv2/ext2
-reset_pcap_file br-phys_n1 hv2/br-phys_n1
-reset_pcap_file br-phys hv2/br-phys
-
-# From  ls1-lp_ext1, send ARP request for the router ip. The ARP
-# response should come from the router pipeline of hv2.
-ext1_mac=f00000000003
-router_mac=a01000000001
-ext1_ip=`ip_to_hex 10 0 0 6`
-router_ip=`ip_to_hex 10 0 0 1`
-arp_request=ffffffffffff${ext1_mac}08060001080006040001${ext1_mac}${ext1_ip}000000000000${router_ip}
-
-as hv1 ovs-appctl netdev-dummy/receive hv1-ext1 $arp_request
-expected_response=${src_mac}${router_mac}08060001080006040002${router_mac}${router_ip}${ext1_mac}${ext1_ip}
-echo $expected_response > expout
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_arp_resp
-AT_CHECK([cat ext1_arp_resp], [0], [expout])
-
-# Verify that the response came from hv2
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap > ext1_arp_resp
-AT_CHECK([cat ext1_arp_resp], [0], [expout])
-
-# Now add 3 ha chassis to the ha chassis group
-ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv1 30
-ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv2 20
-ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 10
-
-# hv1 should be master and claim ls1-lp_ext1
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = "$hv1_uuid"])
-
-as hv1
-ovs-vsctl show
-reset_pcap_file hv1-ext1 hv1/ext1
-reset_pcap_file br-phys_n1 hv1/br-phys_n1
-reset_pcap_file br-phys hv1/br-phys
-
-as hv2
-ovs-vsctl show
-reset_pcap_file hv2-ext2 hv2/ext2
-reset_pcap_file br-phys_n1 hv2/br-phys_n1
-reset_pcap_file br-phys hv2/br-phys
-
-as hv3
-ovs-vsctl show
-reset_pcap_file hv3-ext3 hv3/ext3
-reset_pcap_file br-phys_n1 hv3/br-phys_n1
-reset_pcap_file br-phys hv3/br-phys
-
-# Send DHCPDISCOVER.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-server_mac=ff1000000001
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
-$expected_dhcp_opts
-
-# NXT_RESUMEs should be 3 in hv1.
-OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
-cat ext1_v4.expected | cut -c -48 > expout
-AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat ext1_v4.expected | cut -c 53- > expout
-AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
-
-# ovs-ofctl also resumes the packets and this causes other ports to receive
-# the DHCP request packet. So reset the pcap files so that its easier to test.
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-rm -f ext1_v4.expected
-rm -f ext1_v4.packets
-
-# Send DHCPv6 request
-src_mac=f00000000003
-src_lla=fe80000000000000f20000fffe000003
-offer_ip=ae700000000000000000000000000006
-test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
-
-# NXT_RESUMEs should be 4 in hv1.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
-sort > ext1_v6.packets
-cat ext1_v6.expected | cut -c -120 > expout
-AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
-# Skipping the UDP checksum
-cat ext1_v6.expected | cut -c 125- > expout
-AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
-
-rm -f ext1_v6.expected
-rm -f ext1_v6.packets
-as hv1 reset_pcap_file hv1-ext1 hv1/ext1
-
-# Now increase the priority of hv3 so it becomes master.
-ovn-nbctl ha-chassis-group-add-chassis hagrp1 hv3 50
-
-# hv3 should be master and claim ls1-lp_ext1
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = "$hv3_uuid"])
-
-as hv1
-ovs-vsctl show
-reset_pcap_file hv1-ext1 hv1/ext1
-reset_pcap_file br-phys_n1 hv1/br-phys_n1
-reset_pcap_file br-phys hv1/br-phys
-
-as hv2
-ovs-vsctl show
-reset_pcap_file hv2-ext2 hv2/ext2
-reset_pcap_file br-phys_n1 hv2/br-phys_n1
-reset_pcap_file br-phys hv2/br-phys
-
-as hv2
-ovs-vsctl show
-reset_pcap_file hv3-ext3 hv3/ext3
-reset_pcap_file br-phys_n1 hv3/br-phys_n1
-reset_pcap_file br-phys hv3/br-phys
-
-# Send DHCPDISCOVER.
-offer_ip=`ip_to_hex 10 0 0 6`
-server_ip=`ip_to_hex 10 0 0 1`
-server_mac=ff1000000001
-expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000003 01 $offer_ip 0 $server_mac $server_ip \
-$expected_dhcp_opts
-
-# NXT_RESUMEs should be 4 in hv1.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 1 in hv3.
-OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor0_hv3.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap > ext1_v4.packets
-cat ext1_v4.expected | cut -c -48 > expout
-AT_CHECK([cat ext1_v4.packets | cut -c -48], [0], [expout])
-# Skipping the IPv4 checksum.
-cat ext1_v4.expected | cut -c 53- > expout
-AT_CHECK([cat ext1_v4.packets | cut -c 53-], [0], [expout])
-
-# ovs-ofctl also resumes the packets and this causes other ports to receive
-# the DHCP request packet. So reset the pcap files so that its easier to test.
-as hv1
-reset_pcap_file hv1-ext1 hv1/ext1
-
-rm -f ext1_v4.expected
-rm -f ext1_v4.packets
-
-# Send DHCPv6 request
-src_mac=f00000000003
-src_lla=fe80000000000000f20000fffe000003
-offer_ip=ae700000000000000000000000000006
-test_dhcpv6 1 $src_mac $src_lla 01 $offer_ip
-
-# NXT_RESUMEs should be 4 in hv1.
-OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor0_hv1.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv2.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv2.log | grep -c NXT_RESUME`])
-
-# NXT_RESUMEs should be 2 in hv3.
-OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor0_hv3.log | grep -c NXT_RESUME`])
-
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/ext1-tx.pcap | \
-sort > ext1_v6.packets
-cat ext1_v6.expected | cut -c -120 > expout
-AT_CHECK([cat ext1_v6.packets | cut -c -120], [0], [expout])
-# Skipping the UDP checksum
-cat ext1_v6.expected | cut -c 125- > expout
-AT_CHECK([cat ext1_v6.packets | cut -c 125-], [0], [expout])
-
-# disconnect hv3 from the network, hv1 should take over
-as hv3
-port=${sandbox}_br-phys
-as main ovs-vsctl del-port n1 $port
-
-# hv1 should be master and claim ls1-lp_ext1
-OVS_WAIT_UNTIL(
-    [chassis=`ovn-sbctl --bare --columns chassis find port_binding \
-logical_port=ls1-lp_ext1`
-    test "$chassis" = "$hv1_uuid"])
-
-OVN_CLEANUP([hv1],[hv2],[hv3])
-AT_CLEANUP
-
-AT_SETUP([ovn -- Address Set Incremental Processing])
-AT_KEYWORDS([ovn_as_inc])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.10
-
-ovn-nbctl ls-add ls1
-for i in 1 2; do
-    ovn-nbctl lsp-add ls1 lp$i \
-        -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i"
-    as hv1 ovs-vsctl \
-        -- add-port br-int vif$i \
-        -- set Interface vif$i \
-            external-ids:iface-id=lp$i
-done
-
-for i in 1 2 3; do
-    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
-    as2_uuid=`ovn-nbctl --wait=hv create addr name=as2`
-    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
-            'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}' allow-related
-    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10"
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [0], [ignore])
-
-    # Update address set as1
-    ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"], [0], [ignore])
-
-    # Update address set as2
-    ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore])
-
-    # Add another ACL referencing as1
-    n_flows_before=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
-    ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \
-            'outport=="lp2" && ip4 && ip4.src == $as1' allow-related
-    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
-    AT_CHECK([test $(expr $n_flows_before \* 2) = $n_flows_after], [0], [ignore])
-
-    # Remove an ACL
-    ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \
-            'outport=="lp2" && ip4 && ip4.src == $as1'
-    n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
-    AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore])
-
-    # Remove as1 while it is still used by an ACL, the lflows should be reparsed and
-    # parsing should fail.
-    echo "before del as1"
-    ovn-nbctl list addr | grep as1
-    ovn-nbctl --wait=hv destroy addr $as1_uuid
-    echo "after del as1"
-    ovn-nbctl list addr | grep as1
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [1], [ignore])
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore])
-
-    # Recreate as1
-    as1_uuid=`ovn-nbctl --wait=hv create addr name=as1`
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore])
-
-    # Remove ACLs and address sets
-    ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr $as2_uuid
-    AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore])
-
-    ovn-nbctl --wait=hv acl-del ls1
-done
-
-# Gracefully terminate daemons
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ovn-controller restart])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One Logical Router: ro, with two logical switches sw1 and sw2.
-# sw1 is for subnet 10.0.0.0/8
-# sw2 is for subnet 20.0.0.0/8
-# sw1 has a single port bound on hv1
-# sw2 has a single port bound on hv2
-
-ovn-nbctl lr-add ro
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add sw2
-
-sw1_ro_mac=00:00:10:00:00:01
-sw1_ro_ip=10.0.0.1
-sw2_ro_mac=00:00:20:00:00:01
-sw2_ro_ip=20.0.0.1
-sw1_p1_mac=00:00:10:00:00:02
-sw1_p1_ip=10.0.0.2
-sw2_p1_mac=00:00:20:00:00:02
-sw2_p1_ip=20.0.0.2
-
-ovn-nbctl lrp-add ro ro-sw1 $sw1_ro_mac ${sw1_ro_ip}/8
-ovn-nbctl lrp-add ro ro-sw2 $sw2_ro_mac ${sw2_ro_ip}/8
-ovn-nbctl lsp-add sw1 sw1-ro -- set Logical_Switch_Port sw1-ro type=router \
-  options:router-port=ro-sw1 addresses=\"$sw1_ro_mac\"
-ovn-nbctl lsp-add sw2 sw2-ro -- set Logical_Switch_Port sw2-ro type=router \
-  options:router-port=ro-sw2 addresses=\"$sw2_ro_mac\"
-
-ovn-nbctl lsp-add sw1 sw1-p1 \
--- lsp-set-addresses sw1-p1 "$sw1_p1_mac $sw1_p1_ip"
-
-ovn-nbctl lsp-add sw2 sw2-p1 \
--- lsp-set-addresses sw2-p1 "$sw2_p1_mac $sw2_p1_ip"
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw1-p1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=sw2-p1 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-OVN_POPULATE_ARP
-
-sleep 1
-
-packet="inport==\"sw1-p1\" && eth.src==$sw1_p1_mac && eth.dst==$sw1_ro_mac &&
-       ip4 && ip.ttl==64 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-
-# Start by Sending the packet and make sure it makes it there as expected
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-# Expected packet has TTL decreased by 1
-expected="eth.src==$sw2_ro_mac && eth.dst==$sw2_p1_mac &&
-       ip4 && ip.ttl==63 && ip4.src==$sw1_p1_ip && ip4.dst==$sw2_p1_ip &&
-       udp && udp.src==53 && udp.dst==4369"
-echo $expected | ovstest test-ovn expr-to-packets > expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-# Stop ovn-controller on hv2 with --restart flag
-as hv2 ovs-appctl -t ovn-controller exit --restart
-
-# Now send the packet again. This time, it should still arrive
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-cat expected expected > expected2
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected2])
-
-# Start ovn-controller again just so OVN_CLEANUP doesn't complain
-as hv2 start_daemon ovn-controller
-
-OVN_CLEANUP([hv1],[hv2])
-
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- ovn-nbctl duplicate addresses])
-ovn_start
-
-# Set up a switch with some switch ports of varying address types
-ovn-nbctl ls-add sw1
-ovn-nbctl set logical_switch sw1 other_config:subnet=192.168.0.0/24
-
-ovn-nbctl lsp-add sw1 sw1-p1
-ovn-nbctl lsp-add sw1 sw1-p2
-ovn-nbctl lsp-add sw1 sw1-p3
-ovn-nbctl lsp-add sw1 sw1-p4
-
-ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2"
-ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic"
-ovn-nbctl lsp-set-addresses sw1-p3 "dynamic"
-ovn-nbctl lsp-set-addresses sw1-p4 "router"
-ovn-nbctl lsp-set-addresses sw1-p5 "unknown"
-
-ovn-nbctl list logical_switch_port
-
-# Now try to add duplicate addresses on a new port. These should all fail
-ovn-nbctl --wait=sb lsp-add sw1 sw1-p5
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.1"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1
-])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.2"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2
-])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::1"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1
-])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::2"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2
-])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.2"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2
-])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.3"], [1], [],
-[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3
-])
-
-# Now try re-setting sw1-p1. This should succeed
-AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1"])
-
-# Now create a new switch and try setting IP addresses the same as the
-# first switch. This should succeed.
-ovn-nbctl ls-add sw2
-ovn-nbctl lsp-add sw2 sw2-p1
-
-AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 10.0.0.1"])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.2"])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.3"])
-AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 aef0::1"])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- router - check packet length - icmp defrag])
-AT_KEYWORDS([check packet length])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-ovn-nbctl ls-add sw0
-ovn-nbctl lsp-add sw0 sw0-port1
-ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3"
-
-ovn-nbctl lr-add lr0
-ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
-ovn-nbctl lsp-add sw0 sw0-lr0
-ovn-nbctl lsp-set-type sw0-lr0 router
-ovn-nbctl lsp-set-addresses sw0-lr0 router
-ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
-
-ovn-nbctl ls-add public
-ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24
-ovn-nbctl lsp-add public public-lr0
-ovn-nbctl lsp-set-type public-lr0 router
-ovn-nbctl lsp-set-addresses public-lr0 router
-ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
-
-# localnet port
-ovn-nbctl lsp-add public ln-public
-ovn-nbctl lsp-set-type ln-public localnet
-ovn-nbctl lsp-set-addresses ln-public unknown
-ovn-nbctl lsp-set-options ln-public network_name=phys
-
-ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20
-ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw0-port1 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-reset_pcap_file() {
-     local iface=$1
-     local pcap_file=$2
-     ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
- options:rxq_pcap=dummy-rx.pcap
-     rm -f ${pcap_file}*.pcap
-     ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
- options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-ip_to_hex() {
-     printf "%02x%02x%02x%02x" "$@"
-}
-
-test_ip_packet_larger() {
-    local icmp_pmtu_reply_expected=$1
-
-    # Send ip packet from sw0-port1 to outside
-    src_mac="505400000001" # sw-port1 mac
-    dst_mac="00000000ff01" # sw0-lr0 mac (internal router leg)
-    src_ip=`ip_to_hex 10 0 0 3`
-    dst_ip=`ip_to_hex 172 168 0 3`
-    # Set the packet length to 100.
-    pkt_len=0064
-    packet=${dst_mac}${src_mac}08004500${pkt_len}0000000040010000
-    orig_packet_l3=${src_ip}${dst_ip}0304000000000000
-    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
-    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
-    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
-    orig_packet_l3=${orig_packet_l3}000000000000000000000000000000000000
-    packet=${packet}${orig_packet_l3}
-
-    gw_ip_garp=ffffffffffff00002020121308060001080006040001000020201213aca80064000000000000aca80064
-
-    # If icmp_pmtu_reply_expected is 0, it means the packet is lesser than
-    # the gateway mtu and should be delivered to the provider bridge via the
-    # localnet port.
-    # If icmp_pmtu_reply_expected is 1, it means the packet is larger than
-    # the gateway mtu and ovn-controller should drop the packet and instead
-    # generate ICMPv4  Destination Unreachable message with pmtu set to 42.
-    if test $icmp_pmtu_reply_expected = 0; then
-        # Packet to expect at br-phys.
-        src_mac="000020201213"
-        dst_mac="00000012af11"
-        src_ip=`ip_to_hex 10 0 0 3`
-        dst_ip=`ip_to_hex 172 168 0 3`
-        expected=${dst_mac}${src_mac}08004500${pkt_len}000000003f010100
-        expected=${expected}${src_ip}${dst_ip}0304000000000000
-        expected=${expected}000000000000000000000000000000000000
-        expected=${expected}000000000000000000000000000000000000
-        expected=${expected}000000000000000000000000000000000000
-        expected=${expected}000000000000000000000000000000000000
-        echo $expected > br_phys_n1.expected
-        echo $gw_ip_garp >> br_phys_n1.expected
-    else
-        # MTU would be 100 - 18 = 82 (hex 0052)
-        mtu=0052
-        src_ip=`ip_to_hex 10 0 0 1`
-        dst_ip=`ip_to_hex 10 0 0 3`
-        # pkt len should be 128 (28 (icmp packet) + 100 (orig ip + payload))
-        reply_pkt_len=0080
-        ip_csum=bd91
-        icmp_reply=${src_mac}${dst_mac}08004500${reply_pkt_len}00004000fe016879
-        icmp_reply=${icmp_reply}${src_ip}${dst_ip}0304${ip_csum}0000${mtu}
-        icmp_reply=${icmp_reply}4500${pkt_len}000000003f010100
-        icmp_reply=${icmp_reply}${orig_packet_l3}
-        echo $icmp_reply > hv1-vif1.expected
-    fi
-
-    as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1
-    as hv1 reset_pcap_file hv1-vif1 hv1/vif1
-
-    # Send packet from sw0-port1 to outside
-    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
-
-    if test $icmp_pmtu_reply_expected = 0; then
-        OVN_CHECK_PACKETS([hv1/br-phys_n1-tx.pcap], [br_phys_n1.expected])
-        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap  > pkts
-        # hv1/vif1-tx.pcap can receive the GARP packet generated by ovn-controller
-        # for the gateway router port. So ignore this packet.
-        cat pkts | grep -v $gw_ip_garp > packets
-        AT_CHECK([cat packets], [0], [])
-    else
-        OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected])
-        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys_n1-tx.pcap  > \
-        pkts
-        # hv1/br-phys_n1-tx.pcap can receive the GARP packet generated by ovn-controller
-        # for the gateway router port. So ignore this packet.
-        cat pkts | grep -v $gw_ip_garp > packets
-        AT_CHECK([cat packets], [0], [])
-    fi
-}
-
-ovn-nbctl show
-ovn-sbctl show
-
-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int  \
-| grep "check_pkt_larger" | wc -l], [0], [[0
-]])
-dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \
-awk '{print $3}')
-ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \
-logical_port=lr0-public mac="00\:00\:00\:12\:af\:11"
-
-# Set the gateway mtu to 100. If the packet length is > 100, ovn-controller
-# should send icmp host not reachable with pmtu set to 100.
-ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=100
-as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
-OVS_WAIT_UNTIL([
-    test `as hv1 ovs-ofctl dump-flows br-int | grep "check_pkt_larger(100)" | \
-    wc -l` -eq 1
-])
-
-icmp_reply_expected=1
-test_ip_packet_larger $icmp_reply_expected
-
-# Set the gateway mtu to 500.
-ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=500
-as hv3 ovs-appctl netdev-dummy/receive hv3-vif1 $arp_reply
-OVS_WAIT_UNTIL([
-    test `as hv1 ovs-ofctl dump-flows br-int | grep "check_pkt_larger(500)" | \
-    wc -l` -eq 1
-])
-
-# Now the packet should be sent via the localnet port to br-phys.
-icmp_reply_expected=0
-test_ip_packet_larger $icmp_reply_expected
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- IP packet buffering])
-AT_KEYWORDS([ip-buffering])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# One LR lr0 that has switches sw0 (192.168.1.0/24) and
-# sw1 (172.16.1.0/24) connected to it.
-#
-# Physical network:
-# Tw0 hypervisors hv[12].
-# hv1 hosts vif sw0-p0.
-# hv1 hosts vif sw1-p0.
-
-send_icmp_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5 ipv4_dst=$6 ip_chksum=$7 data=$8
-    shift 8
-
-    local ip_ttl=ff
-    local ip_len=001c
-    local packet=${eth_dst}${eth_src}08004500${ip_len}00004000${ip_ttl}01${ip_chksum}${ipv4_src}${ipv4_dst}${data}
-    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
-}
-
-send_icmp6_packet() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5 ipv6_dst=$6 ipv6_router=$7 exp_icmp_chksum=$8
-    shift 8
-
-    local ip6_hdr=6000000000083aff${ipv6_src}${ipv6_dst}
-    local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000dcb662f00001
-
-    as hv$hv ovs-appctl netdev-dummy/receive hv$hv-vif$inport $packet
-}
-
-get_arp_req() {
-    local eth_src=$1 spa=$2 tpa=$3
-    local request=ffffffffffff${eth_src}08060001080006040001${eth_src}${spa}000000000000${tpa}
-    echo $request
-}
-
-send_arp_reply() {
-    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
-    local request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa}
-    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
-}
-
-send_na() {
-    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 src_ip=$5 dst_ip=$6
-    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
-    local request=${eth_dst}${eth_src}86dd${ip6_hdr}8800d78440000000${src_ip}0201${eth_src}
-
-    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
-}
-
-get_nd() {
-    local eth_src=$1 src_ip=$2 dst_ip=$3 ta=$4
-    local ip6_hdr=6000000000203aff${src_ip}${dst_ip}
-    request=3333ff000010${eth_src}86dd${ip6_hdr}8700357600000000${ta}0101${eth_src}
-
-    echo $request
-}
-
-net_add n1
-
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw0-p0 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=sw1-p0 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-
-ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1
-ovn-nbctl ls-add sw0
-ovn-nbctl ls-add sw1
-
-ovn-nbctl lrp-add lr0 sw0 00:00:01:01:02:03 192.168.1.1/24 2001:0:0:0:0:0:0:1/64
-ovn-nbctl lsp-add sw0 rp-sw0 -- set Logical_Switch_Port rp-sw0 \
-    type=router options:router-port=sw0 \
-    -- lsp-set-addresses rp-sw0 router
-
-ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24 2002:0:0:0:0:0:0:1/64
-ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \
-    type=router options:router-port=sw1 \
-    -- lsp-set-addresses rp-sw1 router
-
-ovn-nbctl lsp-add sw0 sw0-p0 \
-    -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2 2001::2"
-
-ovn-nbctl lsp-add sw1 sw1-p0 \
-    -- lsp-set-addresses sw1-p0 unknown
-
-OVN_POPULATE_ARP
-ovn-nbctl --wait=hv sync
-
-ip_to_hex() {
-    printf "%02x%02x%02x%02x" "$@"
-}
-
-src_mac=f00000010203
-src_ip=$(ip_to_hex 192 168 1 2)
-src_ip6=20010000000000000000000000000002
-
-router_mac0=000001010203
-router_mac1=000002010203
-router_ip=$(ip_to_hex 172 16 1 1)
-router_ip6=20020000000000000000000000000001
-
-dst_mac=001122334455
-dst_ip=$(ip_to_hex 172 16 1 10)
-dst_ip6=20020000000000000000000000000010
-
-data=0800bee4391a0001
-
-send_icmp_packet 1 1 $src_mac $router_mac0 $src_ip $dst_ip 0000 $data
-send_arp_reply 2 1 $dst_mac $router_mac1 $dst_ip $router_ip
-echo $(get_arp_req $router_mac1 $router_ip $dst_ip) > expected
-echo "${dst_mac}${router_mac1}08004500001c00004000fe010100${src_ip}${dst_ip}${data}" >> expected
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-nd_ip=ff0200000000000000000001ff000010
-ip6_hdr=6000000000083afe${src_ip6}${dst_ip6}
-
-send_icmp6_packet 1 1 $src_mac $router_mac0 $src_ip6 $dst_ip6
-echo $(get_nd $router_mac1 $src_ip6 $nd_ip $dst_ip6) >> expected
-echo "${dst_mac}${router_mac1}86dd${ip6_hdr}8000dcb662f00001" >> expected
-send_na 2 1 $dst_mac $router_mac1 $dst_ip6 $router_ip6
-
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1],[hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- neighbor update on same HV])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# A public switch (pub) with a localnet port connected to two LRs (lr0 and lr1)
-# each with a distributed gateway port.
-# Two VMs: lp0 on sw0 connected to lr0
-#          lp1 on sw1 connected to lr1
-#
-# This test adds a floating IP to each VM so when they are bound to the same
-# hypervisor, it checks that the GARP sent by ovn-controller causes the
-# MAC_Binding entries to be updated properly on each logical router.
-# It will also capture packets on the physical interface to make sure that the
-# GARPs have been sent out to the external network as well.
-
-# Create logical switches
-ovn-nbctl ls-add sw0
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add pub
-
-# Created localnet port on public switch
-ovn-nbctl lsp-add pub ln-pub
-ovn-nbctl lsp-set-type ln-pub localnet
-ovn-nbctl lsp-set-addresses ln-pub unknown
-ovn-nbctl lsp-set-options ln-pub network_name=phys
-
-# Create logical routers and connect them to public switch
-ovn-nbctl create Logical_Router name=lr0
-ovn-nbctl create Logical_Router name=lr1
-
-ovn-nbctl lrp-add lr0 lr0-pub f0:00:00:00:00:01 172.24.4.220/24
-ovn-nbctl lsp-add pub pub-lr0 -- set Logical_Switch_Port pub-lr0 \
-    type=router options:router-port=lr0-pub options:nat-addresses="router" addresses="router"
-ovn-nbctl lrp-add lr1 lr1-pub f0:00:00:00:01:01 172.24.4.221/24
-ovn-nbctl lsp-add pub pub-lr1 -- set Logical_Switch_Port pub-lr1 \
-    type=router options:router-port=lr1-pub options:nat-addresses="router" addresses="router"
-
-ovn-nbctl lrp-set-gateway-chassis lr0-pub hv1 10
-ovn-nbctl lrp-set-gateway-chassis lr1-pub hv1 10
-
-# Connect sw0 and sw1 to lr0 and lr1
-ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
-ovn-nbctl lsp-add sw0 sw0-lr0 -- set Logical_Switch_Port sw0-lr0 type=router \
-    options:router-port=lr0-sw0 addresses="router"
-ovn-nbctl lrp-add lr1 lr1-sw1 00:00:00:00:ff:02 20.0.0.254/24
-ovn-nbctl lsp-add sw1 sw1-lr1 -- set Logical_Switch_Port sw1-lr1 type=router \
-    options:router-port=lr1-sw1 addresses="router"
-
-
-# Add SNAT rules
-ovn-nbctl lr-nat-add lr0 snat 172.24.4.220 10.0.0.0/24
-ovn-nbctl lr-nat-add lr1 snat 172.24.4.221 20.0.0.0/24
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 172.24.4.1
-ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-
-ovs-vsctl add-port br-int vif0 -- set Interface vif0 external-ids:iface-id=lp0
-ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lp1
-
-ovn-nbctl lsp-add sw0 lp0
-ovn-nbctl lsp-add sw1 lp1
-ovn-nbctl lsp-set-addresses lp0 "50:54:00:00:00:01 10.0.0.10"
-ovn-nbctl lsp-set-addresses lp1 "50:54:00:00:00:02 20.0.0.10"
-
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp0` = xup])
-OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp1` = xup])
-
-# Create two floating IPs, one for each VIF
-ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10
-ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10
-
-# Check that the MAC_Binding entries have been properly created
-OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr0-pub" ip="172.24.4.200" | wc -l` -gt 0])
-OVS_WAIT_UNTIL([test `ovn-sbctl find mac_binding logical_port="lr1-pub" ip="172.24.4.100" | wc -l` -gt 0])
-
-# Check that the GARPs went also to the external physical network
-# Wait until at least 4 packets have arrived and copy them to a separate file as
-# more GARPs are expected in the capture in order to avoid race conditions.
-OVS_WAIT_UNTIL([test `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | wc -l` -gt 4])
-$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/br-phys-tx.pcap | head -n4 > hv1/br-phys-tx4.pcap
-
-# GARP for lp0 172.24.4.100 on lr0-pub MAC (f0:00:00:00:00:01)
-echo "fffffffffffff0000000000108060001080006040001f00000000001ac180464000000000000ac180464" > expout
-# GARP for 172.24.4.220 on lr0-pub (f0:00:00:00:00:01)
-echo "fffffffffffff0000000000108060001080006040001f00000000001ac1804dc000000000000ac1804dc" >> expout
-# GARP for lp1 172.24.4.200 on lr1-pub MAC (f0:00:00:00:01:01)
-echo "fffffffffffff0000000010108060001080006040001f00000000101ac1804c8000000000000ac1804c8" >> expout
-# GARP for 172.24.4.221 on lr1-pub (f0:00:00:00:01:01)
-echo "fffffffffffff0000000010108060001080006040001f00000000101ac1804dd000000000000ac1804dd" >> expout
-AT_CHECK([sort hv1/br-phys-tx4.pcap], [0], [expout])
-#OVN_CHECK_PACKETS([hv1/br-phys-tx4.pcap], [br-phys.expected])
-
-OVN_CLEANUP([hv1])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ipam to non-ipam])
-ovn_start
-
-ovn-nbctl --wait=hv set NB_Global . options:mac_prefix="0a:00:00:00:00:00"
-ovn-nbctl ls-add sw0
-ovn-nbctl lsp-add sw0 p0 -- lsp-set-addresses p0 dynamic
-ovn-nbctl --wait=sb add Logical-Switch sw0 other_config subnet=192.168.1.0/24
-
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0],
-    ["0a:00:00:a8:01:03 192.168.1.2"
-])
-
-ovn-nbctl --wait=sb lsp-set-addresses p0 router
-
-ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses
-
-AT_CHECK([ovn-nbctl get Logical-Switch-Port p0 dynamic_addresses], [0], [[[]]
-])
-AT_CLEANUP
-
-AT_SETUP([ovn -- ipam router ports])
-ovn_start
-
-ovn-nbctl ls-add sw
-ovn-nbctl set logical_switch sw other-config:subnet=192.168.1.0/24
-
-for i in 2 3 4; do
-    ovn-nbctl lr-add ro$i
-    ovn-nbctl lsp-add sw swp$i
-    ovn-nbctl --wait=sb lsp-set-addresses swp$i "02:00:00:00:00:0$i dynamic"
-    cidr=$(ovn-nbctl get logical_switch_port swp$i dynamic_addresses |cut -f2 -d' '|cut -f1 -d\")
-    ovn-nbctl lrp-add ro$i rop$i 02:00:00:00:00:0$i $cidr/24 -- set logical_switch_port swp$i type=router options:router-port=rop$i addresses=router;
-    AT_CHECK_UNQUOTED([ovn-nbctl get logical_router_port rop$i networks], [0], [[["192.168.1.$i/24"]]
-])
-done
-
-ovn-nbctl list logical_switch_port
-ovn-nbctl list logical_router_port
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- test transport zones])
-ovn_start
-
-net_add n1
-for i in 1 2 3 4 5; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.$i.1
-done
-
-dnl Wait for the changes to be propagated
-ovn-nbctl --wait=sb --timeout=3 sync
-ovn-nbctl --wait=hv --timeout=3 sync
-
-dnl Assert that each Chassis has a tunnel formed to every other Chassis
-as hv1
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv2-0
-ovn-hv3-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv2
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv3-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv3
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv4
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv3-0
-ovn-hv5-0
-]])
-
-as hv5
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv3-0
-ovn-hv4-0
-]])
-
-dnl Let's now add some Chassis to different transport zones
-dnl * hv1: Will be part of two transport zones: tz1 and tz2 so it
-dnl   should have tunnels formed between the other two Chassis (hv2 and hv3)
-dnl
-dnl * hv2: Will be part of one transport zone: tz1. It should have a tunnel
-dnl   to hv1 but not to hv3
-dnl
-dnl * hv3: Will be part of one transport zone: tz2. It should have a tunnel
-dnl   to hv1 but not to hv2
-dnl
-dnl * hv4 and hv5: Will not have any TZ set so they will keep the tunnels
-dnl   between themselves and remove the tunnels to other Chassis which now
-dnl   belongs to some TZs
-dnl
-as hv1
-ovs-vsctl set open . external-ids:ovn-transport-zones=tz1,tz2
-
-as hv2
-ovs-vsctl set open . external-ids:ovn-transport-zones=tz1
-
-as hv3
-ovs-vsctl set open . external-ids:ovn-transport-zones=tz2
-
-dnl Wait for the changes to be propagated
-ovn-nbctl --wait=sb --timeout=3 sync
-ovn-nbctl --wait=hv --timeout=3 sync
-
-as hv1
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv2-0
-ovn-hv3-0
-]])
-
-as hv2
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-]])
-
-as hv3
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-]])
-
-as hv4
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv5-0
-]])
-
-as hv5
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv4-0
-]])
-
-dnl Removing the transport zones should make all Chassis to create
-dnl tunnels between every other Chassis again
-for i in 1 2 3; do
-    as hv$i
-    ovs-vsctl remove open . external-ids ovn-transport-zones
-done
-
-dnl Wait for the changes to be propagated
-ovn-nbctl --wait=sb --timeout=3 sync
-ovn-nbctl --wait=hv --timeout=3 sync
-
-as hv1
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv2-0
-ovn-hv3-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv2
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv3-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv3
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv4-0
-ovn-hv5-0
-]])
-
-as hv4
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv3-0
-ovn-hv5-0
-]])
-
-as hv5
-AT_CHECK([ovs-vsctl --bare --columns=name find interface type="geneve" | awk NF | sort], [0],
-[[ovn-hv1-0
-ovn-hv2-0
-ovn-hv3-0
-ovn-hv4-0
-]])
-
-OVN_CLEANUP([hv1], [hv2], [hv3])
-AT_CLEANUP
-
-AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac])
-ovn_start
-
-
-# In this test cases we create 2 switches, all connected to same
-# physical network (through br-phys on each HV). Each switch has
-# 1 VIF. Each HV has 1 VIF port. The first digit
-# of VIF port name indicates the hypervisor it is bound to, e.g.
-# lp23 means VIF 3 on hv2.
-#
-# Each switch's VLAN tag and their logical switch ports are:
-#   - ls1:
-#       - tagged with VLAN 101
-#       - ports: lp11
-#   - ls2:
-#       - tagged with VLAN 201
-#       - ports: lp22
-#
-# Note: a localnet port is created for each switch to connect to
-# physical network.
-
-for i in 1 2; do
-    ls_name=ls$i
-    ovn-nbctl ls-add $ls_name
-    ln_port_name=ln$i
-    if test $i -eq 1; then
-        ovn-nbctl lsp-add $ls_name $ln_port_name "" 101
-    elif test $i -eq 2; then
-        ovn-nbctl lsp-add $ls_name $ln_port_name "" 201
-    fi
-    ovn-nbctl lsp-set-addresses $ln_port_name unknown
-    ovn-nbctl lsp-set-type $ln_port_name localnet
-    ovn-nbctl lsp-set-options $ln_port_name network_name=phys
-done
-
-# lsp_to_ls LSP
-#
-# Prints the name of the logical switch that contains LSP.
-lsp_to_ls () {
-    case $1 in dnl (
-        lp?[[11]]) echo ls1 ;; dnl (
-        lp?[[12]]) echo ls2 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-vif_to_ls () {
-    case $1 in dnl (
-        vif?[[11]]) echo ls1 ;; dnl (
-        vif?[[12]]) echo ls2 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-hv_to_num () {
-    case $1 in dnl (
-        hv1) echo 1 ;; dnl (
-        hv2) echo 2 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-vif_to_num () {
-    case $1 in dnl (
-        vif22) echo 22 ;; dnl (
-        vif21) echo 21 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-vif_to_hv () {
-    case $1 in dnl (
-        vif[[1]]?) echo hv1 ;; dnl (
-        vif[[2]]?) echo hv2 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-vif_to_lrp () {
-    echo router-to-`vif_to_ls $1`
-}
-
-hv_to_chassis_mac () {
-     case $1 in dnl (
-        hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl (
-        hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl (
-        *) AT_FAIL_IF([:]) ;;
-    esac
-}
-
-ip_to_hex() {
-       printf "%02x%02x%02x%02x" "$@"
-}
-
-net_add n1
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
-    ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    ovs-vsctl add-port br-int vif$i$i -- \
-        set Interface vif$i$i external-ids:iface-id=lp$i$i \
-                              options:tx_pcap=hv$i/vif$i$i-tx.pcap \
-                              options:rxq_pcap=hv$i/vif$i$i-rx.pcap \
-                              ofport-request=$i$i
-
-    lsp_name=lp$i$i
-    ls_name=$(lsp_to_ls $lsp_name)
-
-    ovn-nbctl lsp-add $ls_name $lsp_name
-    ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i 192.168.$i.$i"
-    ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i
-
-    OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup])
-
-done
-
-ovn-nbctl lr-add router
-ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03 192.168.1.3/24
-ovn-nbctl lrp-add router router-to-ls2 00:00:01:01:02:05 192.168.2.3/24
-
-ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port ls1-to-router type=router options:router-port=router-to-ls1 -- lsp-set-addresses ls1-to-router router
-ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port ls2-to-router type=router options:router-port=router-to-ls2 -- lsp-set-addresses ls2-to-router router
-
-ovn-nbctl --wait=sb sync
-#ovn-sbctl dump-flows
-
-ovn-nbctl show
-ovn-sbctl show
-
-OVN_POPULATE_ARP
-
-test_ip() {
-    # This packet has bad checksums but logical L3 routing doesn't check.
-    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
-    local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000
-    shift; shift; shift; shift; shift
-    hv=`vif_to_hv $inport`
-    hv_num=`hv_to_num $hv`
-    chassis_mac=`hv_to_chassis_mac $hv`
-    as $hv ovs-appctl netdev-dummy/receive $inport $packet
-    #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
-    in_ls=`vif_to_ls $inport`
-    in_lrp=`vif_to_lrp $inport`
-    for outport; do
-        out_ls=`vif_to_ls $outport`
-        if test $in_ls = $out_ls; then
-            # Ports on the same logical switch receive exactly the same packet.
-            echo $packet
-        else
-            # Routing decrements TTL and updates source and dest MAC
-            # (and checksum).
-            outport_num=`vif_to_num $outport`
-            out_lrp=`vif_to_lrp $outport`
-            echo f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000
-        fi >> $outport.expected
-    done
-}
-
-# Dump a bunch of info helpful for debugging if there's a failure.
-
-echo "------ OVN dump ------"
-ovn-nbctl show
-ovn-sbctl show
-
-echo "------ hv1 dump ------"
-as hv1 ovs-vsctl show
-as hv1 ovs-vsctl list Open_Vswitch
-
-echo "------ hv2 dump ------"
-as hv2 ovs-vsctl show
-as hv2 ovs-vsctl list Open_Vswitch
-
-echo "Send traffic"
-sip=`ip_to_hex 192 168 1 1`
-dip=`ip_to_hex 192 168 2 2`
-test_ip vif11 f00000000011  000001010203 $sip $dip vif22
-
-echo "----------- Post Traffic hv1 dump -----------"
-as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
-as hv1 ovs-appctl fdb/show br-phys
-
-echo "----------- Post Traffic hv2 dump -----------"
-as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
-as hv2 ovs-appctl fdb/show br-phys
-
-OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
-
-OVN_CLEANUP([hv1],[hv2])
-
-AT_CLEANUP
-
-# Run ovn-nbctl in daemon mode, change to a backup database and verify that
-# an insert operation is not allowed.
-AT_SETUP([ovn -- can't write to a backup database server instance])
-ovn_start
-on_exit 'kill $(cat ovn-nbctl.pid)'
-export OVN_NB_DAEMON=$(ovn-nbctl --pidfile --detach)
-
-AT_CHECK([ovn-nbctl ls-add sw0])
-as ovn-nb
-AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status | grep active | wc -l], [0], [1
-])
-ovs-appctl -t ovsdb-server ovsdb-server/set-active-ovsdb-server tcp:192.0.2.2:6641
-ovs-appctl -t ovsdb-server ovsdb-server/connect-active-ovsdb-server
-AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/sync-status | grep -c backup], [0], [1
-])
-AT_CHECK([ovn-nbctl ls-add sw1], [1], [ignore],
-[ovn-nbctl: transaction error: {"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}
-])
-
-AT_CLEANUP
-
-AT_SETUP([ovn -- controller event])
-AT_KEYWORDS([ovn_controller_event])
-ovn_start
-
-# Create hypervisors hv[12].
-# Add vif1[12] to hv1, vif2[12] to hv2
-# Add all of the vifs to a single logical switch sw0.
-
-net_add n1
-ovn-nbctl ls-add sw0
-for i in 1 2; do
-    sim_add hv$i
-    as hv$i
-    ovs-vsctl add-br br-phys
-    ovn_attach n1 br-phys 192.168.0.$i
-
-    for j in 1 2; do
-        ovn-nbctl lsp-add sw0 sw0-p$i$j -- \
-                lsp-set-addresses sw0-p$i$j "00:00:00:00:00:$i$j 192.168.1.$i$j"
-
-        ovs-vsctl -- add-port br-int vif$i$j -- \
-                set interface vif$i$j \
-                external-ids:iface-id=sw0-p$i$j \
-                options:tx_pcap=hv$i/vif$i$j-tx.pcap \
-                options:rxq_pcap=hv$i/vif$i$j-rx.pcap \
-                ofport-request=$i$j
-    done
-done
-
-ovn-nbctl --wait=hv set NB_Global . options:controller_event=true
-ovn-nbctl lb-add lb0 192.168.1.100:80 ""
-ovn-nbctl ls-lb-add sw0 lb0
-uuid_lb=$(ovn-nbctl --bare --columns=_uuid find load_balancer name=lb0)
-
-OVN_POPULATE_ARP
-ovn-nbctl --timeout=3 --wait=hv sync
-ovn-sbctl lflow-list
-as hv1 ovs-ofctl dump-flows br-int
-
-packet="inport==\"sw0-p11\" && eth.src==00:00:00:00:00:11 && eth.dst==00:00:00:00:00:21 &&
-       ip4 && ip.ttl==64 && ip4.src==192.168.1.11 && ip4.dst==192.168.1.100 &&
-       tcp && tcp.src==10000 && tcp.dst==80"
-as hv1 ovs-appctl -t ovn-controller inject-pkt "$packet"
-
-ovn-sbctl list controller_event
-uuid=$(ovn-sbctl list controller_event | awk '/_uuid/{print $3}')
-AT_CHECK([ovn-sbctl get controller_event $uuid event_type], [0], [dnl
-empty_lb_backends
-])
-AT_CHECK([ovn-sbctl get controller_event $uuid event_info:vip], [0], [dnl
-"192.168.1.100:80"
-])
-AT_CHECK([ovn-sbctl get controller_event $uuid event_info:protocol], [0], [dnl
-tcp
-])
-AT_CHECK_UNQUOTED([ovn-sbctl get controller_event $uuid event_info:load_balancer], [0], [dnl
-"$uuid_lb"
-])
-AT_CHECK([ovn-sbctl get controller_event $uuid seq_num], [0], [dnl
-1
-])
-
-OVN_CLEANUP([hv1], [hv2])
-AT_CLEANUP
-
-AT_SETUP([ovn -- IGMP snoop/querier])
-AT_SKIP_IF([test $HAVE_PYTHON = no])
-ovn_start
-
-# Logical network:
-# Two independent logical switches (sw1 and sw2).
-# sw1:
-#   - subnet 10.0.0.0/8
-#   - 2 ports bound on hv1 (sw1-p11, sw1-p12)
-#   - 2 ports bound on hv2 (sw1-p21, sw1-p22)
-# sw2:
-#   - subnet 20.0.0.0/8
-#   - 1 port bound on hv1 (sw2-p1)
-#   - 1 port bound on hv2 (sw2-p2)
-#   - IGMP Querier from 20.0.0.254
-
-reset_pcap_file() {
-    local iface=$1
-    local pcap_file=$2
-    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
-options:rxq_pcap=dummy-rx.pcap
-    rm -f ${pcap_file}*.pcap
-    ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
-options:rxq_pcap=${pcap_file}-rx.pcap
-}
-
-ip_to_hex() {
-     printf "%02x%02x%02x%02x" "$@"
-}
-
-#
-# send_igmp_v3_report INPORT HV ETH_SRC IP_SRC IP_CSUM GROUP REC_TYPE
-#                     IGMP_CSUM OUTFILE
-#
-# This shell function causes an IGMPv3 report to be received on INPORT of HV.
-# The packet's content has Ethernet destination 01:00:5E:00:00:22 and source
-# ETH_SRC (exactly 12 hex digits). Ethernet type is set to IP.
-# GROUP is the IP multicast group to be joined/to leave (based on REC_TYPE).
-# REC_TYPE == 04: join GROUP
-# REC_TYPE == 03: leave GROUP
-# The packet hexdump is also stored in OUTFILE.
-#
-send_igmp_v3_report() {
-    local inport=$1 hv=$2 eth_src=$3 ip_src=$4 ip_chksum=$5 group=$6
-    local rec_type=$7 igmp_chksum=$8 outfile=$9
-
-    local eth_dst=01005e000016
-    local ip_dst=$(ip_to_hex 224 0 0 22)
-    local ip_ttl=01
-    local ip_ra_opt=94040000
-
-    local igmp_type=2200
-    local num_rec=00000001
-    local aux_dlen=00
-    local num_src=0000
-
-    local eth=${eth_dst}${eth_src}0800
-    local ip=46c0002800004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}${ip_ra_opt}
-    local igmp=${igmp_type}${igmp_chksum}${num_rec}${rec_type}${aux_dlen}${num_src}${group}
-    local packet=${eth}${ip}${igmp}
-
-    echo ${packet} >> ${outfile}
-    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
-}
-
-#
-# store_igmp_v3_query ETH_SRC IP_SRC IP_CSUM OUTFILE
-#
-# This shell function builds an IGMPv3 general query from ETH_SRC and IP_SRC
-# and stores the hexdump of the packet in OUTFILE.
-#
-store_igmp_v3_query() {
-    local eth_src=$1 ip_src=$2 ip_chksum=$3 outfile=$4
-
-    local eth_dst=01005e000001
-    local ip_dst=$(ip_to_hex 224 0 0 1)
-    local ip_ttl=01
-    local igmp_type=11
-    local max_resp=0a
-    local igmp_chksum=eeeb
-    local addr=00000000
-
-    local eth=${eth_dst}${eth_src}0800
-    local ip=4500002000004000${ip_ttl}02${ip_chksum}${ip_src}${ip_dst}
-    local igmp=${igmp_type}${max_resp}${igmp_chksum}${addr}000a0000
-    local packet=${eth}${ip}${igmp}
-
-    echo ${packet} >> ${outfile}
-}
-
-#
-# send_ip_multicast_pkt INPORT HV ETH_SRC ETH_DST IP_SRC IP_DST IP_LEN
-#    IP_PROTO DATA OUTFILE
-#
-# This shell function causes an IP multicast packet to be received on INPORT
-# of HV.
-# The hexdump of the packet is stored in OUTFILE.
-#
-send_ip_multicast_pkt() {
-    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ip_src=$5 ip_dst=$6
-    local ip_len=$7 ip_chksum=$8 proto=$9 data=${10} outfile=${11}
-
-    local ip_ttl=20
-
-    local eth=${eth_dst}${eth_src}0800
-    local ip=450000${ip_len}95f14000${ip_ttl}${proto}${ip_chksum}${ip_src}${ip_dst}
-    local packet=${eth}${ip}${data}
-
-    as $hv ovs-appctl netdev-dummy/receive ${inport} ${packet}
-    echo ${packet} >> ${outfile}
-}
-
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add sw2
-
-ovn-nbctl lsp-add sw1 sw1-p11
-ovn-nbctl lsp-add sw1 sw1-p12
-ovn-nbctl lsp-add sw1 sw1-p21
-ovn-nbctl lsp-add sw1 sw1-p22
-ovn-nbctl lsp-add sw2 sw2-p1
-ovn-nbctl lsp-add sw2 sw2-p2
-
-net_add n1
-sim_add hv1
-as hv1
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.1
-ovs-vsctl -- add-port br-int hv1-vif1 -- \
-    set interface hv1-vif1 external-ids:iface-id=sw1-p11 \
-    options:tx_pcap=hv1/vif1-tx.pcap \
-    options:rxq_pcap=hv1/vif1-rx.pcap \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
-    set interface hv1-vif2 external-ids:iface-id=sw1-p12 \
-    options:tx_pcap=hv1/vif2-tx.pcap \
-    options:rxq_pcap=hv1/vif2-rx.pcap \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv1-vif3 -- \
-    set interface hv1-vif3 external-ids:iface-id=sw2-p1 \
-    options:tx_pcap=hv1/vif3-tx.pcap \
-    options:rxq_pcap=hv1/vif3-rx.pcap \
-    ofport-request=1
-
-sim_add hv2
-as hv2
-ovs-vsctl add-br br-phys
-ovn_attach n1 br-phys 192.168.0.2
-ovs-vsctl -- add-port br-int hv2-vif1 -- \
-    set interface hv2-vif1 external-ids:iface-id=sw1-p21 \
-    options:tx_pcap=hv2/vif1-tx.pcap \
-    options:rxq_pcap=hv2/vif1-rx.pcap \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv2-vif2 -- \
-    set interface hv2-vif2 external-ids:iface-id=sw1-p22 \
-    options:tx_pcap=hv2/vif2-tx.pcap \
-    options:rxq_pcap=hv2/vif2-rx.pcap \
-    ofport-request=1
-ovs-vsctl -- add-port br-int hv2-vif3 -- \
-    set interface hv2-vif3 external-ids:iface-id=sw2-p2 \
-    options:tx_pcap=hv2/vif3-tx.pcap \
-    options:rxq_pcap=hv2/vif3-rx.pcap \
-    ofport-request=1
-
-OVN_POPULATE_ARP
-
-# Enable IGMP snooping on sw1.
-ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
-ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
-
-# No IGMP query should be generated by sw1 (mcast_querier="false").
-truncate -s 0 expected
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected])
-
-ovn-nbctl --wait=hv sync
-
-# Inject IGMP Join for 239.0.1.68 on sw1-p11.
-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 IGMP Join for 239.0.1.68 on sw1-p21.
-send_igmp_v3_report hv2-vif1 hv2 000000000002 $(ip_to_hex 10 0 0 2) f9f9 \
-    $(ip_to_hex 239 0 1 68) 04 e9b9 \
-    /dev/null
-
-# Check that the IGMP Group is learned on both hv.
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    test "${total_entries}" = "2"
-])
-
-# Send traffic and make sure it gets forwarded only on the two ports that
-# joined.
-truncate -s 0 expected
-truncate -s 0 expected_empty
-send_ip_multicast_pkt hv1-vif2 hv1 \
-    000000000001 01005e000144 \
-    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
-    e518e518000a3b3a0000 \
-    expected
-
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
-
-# Inject IGMP Leave for 239.0.1.68 on sw1-p11.
-send_igmp_v3_report hv1-vif1 hv1 \
-    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
-    $(ip_to_hex 239 0 1 68) 03 eab9 \
-    /dev/null
-
-# Check IGMP_Group table on both HV.
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    test "${total_entries}" = "1"
-])
-
-# Send traffic traffic and make sure it gets forwarded only on the port that
-# joined.
-as hv1 reset_pcap_file hv1-vif1 hv1/vif1
-as hv2 reset_pcap_file hv2-vif1 hv2/vif1
-truncate -s 0 expected
-truncate -s 0 expected_empty
-send_ip_multicast_pkt hv1-vif2 hv1 \
-    000000000001 01005e000144 \
-    $(ip_to_hex 10 0 0 42) $(ip_to_hex 239 0 1 68) 1e ca70 11 \
-    e518e518000a3b3a0000 \
-    expected
-
-OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected_empty])
-OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected_empty])
-
-# Flush IGMP groups.
-ovn-sbctl ip-multicast-flush sw1
-ovn-nbctl --wait=hv -t 3 sync
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    test "${total_entries}" = "0"
-])
-
-# Enable IGMP snooping and querier on sw2 and set query interval to minimum.
-ovn-nbctl set Logical_Switch sw2 \
-    other_config:mcast_snoop="true" \
-    other_config:mcast_querier="true" \
-    other_config:mcast_query_interval=1 \
-    other_config:mcast_eth_src="00:00:00:00:02:fe" \
-    other_config:mcast_ip4_src="20.0.0.254"
-
-# Wait for 1 query interval (1 sec) and check that two queries are generated.
-truncate -s 0 expected
-store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
-store_igmp_v3_query 0000000002fe $(ip_to_hex 20 0 0 254) 84dd expected
-
-sleep 1
-OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [expected])
-OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected])
-
-OVN_CLEANUP([hv1], [hv2])
-AT_CLEANUP
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
deleted file mode 100644
index f88ad31..0000000
--- a/tests/system-ovn.at
+++ /dev/null
@@ -1,1667 +0,0 @@ 
-AT_BANNER([system-ovn])
-
-AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, SNAT and DNAT])
-AT_KEYWORDS([ovnnat])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
-# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24) connected
-# to it.  R2 is a gateway router on which we add NAT rules.
-#
-#    foo -- R1 -- join - R2 -- alice
-#           |
-#    bar ----
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Static routes.
-ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
-"192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
-
-# Add a DNAT rule.
-ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
-    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
-
-# Add a SNAT rule
-ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
-    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
-
-# wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=30.0.0.1)'])
-
-# 'alice1' should be able to ping 'foo1' directly.
-NS_CHECK_EXEC([alice1], [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
-])
-
-# North-South DNAT: 'alice1' should also be able to ping 'foo1' via 30.0.0.2
-NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# Check conntrack entries.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
-# from 30.0.0.1
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# Add static routes to handle east-west NAT.
-ovn-nbctl lr-route-add R1 30.0.0.0/24 20.0.0.2
-
-# wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-
-# Flush conntrack entries for easier output parsing of next test.
-AT_CHECK([ovs-appctl dpctl/flush-conntrack])
-
-# East-west DNAT and SNAT: 'bar1' pings 30.0.0.2. 'foo1' receives it.
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# As we have a static route that sends all packets with destination
-# 30.0.0.2 to R2, it hits the DNAT rule and converts 30.0.0.2 to 192.168.1.2
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.2.2,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.2.2,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# As we have a SNAT rule that converts 192.168.2.2 to 30.0.0.1, the source is
-# SNATted and 'foo1' receives it.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.2.2,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, easy SNAT])
-AT_KEYWORDS([ovnnat])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) connected
-# to it.  R2 has alice (172.16.1.0/24) connected to it.
-# R2 is a gateway router on which we add NAT rules.
-#
-#    foo -- R1 -- join - R2 -- alice
-
-ovn-nbctl lr-add R1
-ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add join
-
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-
-# Connect foo to R1
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect alice to R2
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Static routes.
-ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Add a SNAT rule
-ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.1.2 \
-    external_ip=172.16.1.1 -- add logical_router R2 nat @nat
-
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
-
-# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives traffic
-# from 172.16.1.1
-NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- multiple gateway routers, SNAT and DNAT])
-AT_KEYWORDS([ovnnat])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
-# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24) connected
-# to it.  R3 has bob (172.16.1.0/24) connected to it. Note how both alice and
-# bob have the same subnet behind it.  We are trying to simulate external
-# network via those 2 switches. In real world the switch ports of these
-# switches will have addresses set as "unknown" to make them learning switches.
-# Or those switches will be "localnet" ones.
-#
-#    foo -- R1 -- join - R2 -- alice
-#           |          |
-#    bar ----          - R3 --- bob
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
-ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add bob
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect bob to R3
-ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
-ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
-    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Connect R3 to join
-ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
-ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
-    type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
-
-# Install static routes with source ip address as the policy for routing.
-# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via R3.
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
-
-# Static routes.
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
-
-# For gateway routers R2 and R3, set a force SNAT rule.
-ovn-nbctl set logical_router R2 options:dnat_force_snat_ip=20.0.0.2
-ovn-nbctl set logical_router R3 options:dnat_force_snat_ip=20.0.0.3
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24", "f0:00:00:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
-"192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
-
-# Logical port 'bob1' in switch 'bob'.
-ADD_NAMESPACES(bob1)
-ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24", "f0:00:00:01:02:06", \
-         "172.16.1.2")
-ovn-nbctl lsp-add bob bob1 \
--- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
-
-# Router R2
-# Add a DNAT rule.
-ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
-    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
-
-# Add a SNAT rule
-ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.1.2 \
-    external_ip=30.0.0.1 -- add logical_router R2 nat @nat
-
-# Router R3
-# Add a DNAT rule.
-ovn-nbctl -- --id=@nat create nat type="dnat" logical_ip=192.168.1.2 \
-    external_ip=30.0.0.3 -- add logical_router R3 nat @nat
-
-# Add a SNAT rule
-ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
-    external_ip=30.0.0.4 -- add logical_router R3 nat @nat
-
-# wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=30.0.0.4)'])
-
-# North-South DNAT: 'alice1' should be able to ping 'foo1' via 30.0.0.2
-NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# Check conntrack entries.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.3,dst=30.0.0.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# But foo1 should receive traffic from 20.0.0.2
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.3,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# North-South DNAT: 'bob1' should be able to ping 'foo1' via 30.0.0.3
-NS_CHECK_EXEC([bob1], [ping -q -c 3 -i 0.3 -w 2 30.0.0.3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# Check conntrack entries.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.4,dst=30.0.0.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# But foo1 should receive traffic from 20.0.0.3
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0.3) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.4,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=20.0.0.3,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# South-North SNAT: 'bar1' pings 'bob1'. But 'bob1' receives traffic
-# from 30.0.0.4
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.4) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.2.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=30.0.0.4,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# South-North SNAT: 'foo1' pings 'alice1'. But 'alice1' receives traffic
-# from 30.0.0.1
-NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=172.16.1.3,dst=30.0.0.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- load-balancing])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# 2 logical switches "foo" (192.168.1.0/24) and "bar" (172.16.1.0/24)
-# connected to a router R1.
-# foo has foo1 to act as a client.
-# bar has bar1, bar2, bar3 to act as servers.
-#
-# Loadbalancer VIPs in 30.0.0.0/24 network.
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 172.16.1.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Create logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Create logical ports 'bar1', 'bar2', 'bar3' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "172.16.1.2/24", "f0:00:0f:01:02:03", \
-         "172.16.1.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:0f:01:02:03 172.16.1.2"
-
-ADD_NAMESPACES(bar2)
-ADD_VETH(bar2, bar2, br-int, "172.16.1.3/24", "f0:00:0f:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add bar bar2 \
--- lsp-set-addresses bar2 "f0:00:0f:01:02:04 172.16.1.3"
-
-ADD_NAMESPACES(bar3)
-ADD_VETH(bar3, bar3, br-int, "172.16.1.4/24", "f0:00:0f:01:02:05", \
-         "172.16.1.1")
-ovn-nbctl lsp-add bar bar3 \
--- lsp-set-addresses bar3 "f0:00:0f:01:02:05 172.16.1.4"
-
-# Config OVN load-balancer with a VIP.
-uuid=`ovn-nbctl  create load_balancer vips:30.0.0.1="172.16.1.2,172.16.1.3,172.16.1.4"`
-ovn-nbctl set logical_switch foo load_balancer=$uuid
-
-# Create another load-balancer with another VIP.
-uuid=`ovn-nbctl create load_balancer vips:30.0.0.3="172.16.1.2,172.16.1.3,172.16.1.4"`
-ovn-nbctl add logical_switch foo load_balancer $uuid
-
-# Config OVN load-balancer with another VIP (this time with ports).
-ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"172.16.1.2:80,172.16.1.3:80,172.16.1.4:80"'
-
-# Wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
-grep 'nat(dst=172.16.1.4:80)'])
-
-# Start webservers in 'bar1', 'bar2' and 'bar3'.
-OVS_START_L7([bar1], [http])
-OVS_START_L7([bar2], [http])
-OVS_START_L7([bar3], [http])
-
-dnl Should work with the virtual IP 30.0.0.1 address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Should work with the virtual IP 30.0.0.3 address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([foo1], [wget 30.0.0.3 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.3,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Test load-balancing that includes L4 ports in NAT.
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.2,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=172.16.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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"])
-AT_CLEANUP
-
-AT_SETUP([ovn -- load-balancing - same subnet.])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# 1 logical switch "foo" (192.168.1.0/24) connected to router R1.
-# foo has foo1, foo2, foo3, foo4 as logical ports.
-#
-# Loadbalancer VIPs in 30.0.0.0/24 network. Router is needed for default
-# gateway. We will test load-balancing with foo1 as a client and foo2, foo3 and
-# foo4 as servers.
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl ls-add foo
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Create logical port 'foo1', 'foo2', 'foo3' and 'foo4' in switch 'foo'.
-ADD_NAMESPACES(foo1, foo2, foo3, foo4)
-for i in `seq 1 4`; do
-    j=`expr $i + 1`
-    ADD_VETH(foo$i, foo$i, br-int, "192.168.1.$j/24", "f0:00:00:01:02:0$j", \
-             "192.168.1.1")
-    ovn-nbctl lsp-add foo foo$i \
-        -- lsp-set-addresses foo$i "f0:00:00:01:02:0$j 192.168.1.$j"
-done
-
-# Config OVN load-balancer with a VIP.
-uuid=`ovn-nbctl  create load_balancer vips:30.0.0.1="192.168.1.3,192.168.1.4,192.168.1.5"`
-ovn-nbctl set logical_switch foo load_balancer=$uuid
-
-# Config OVN load-balancer with another VIP (this time with ports).
-ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.3:80,192.168.1.4:80,192.168.1.5:80"'
-
-# Wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
-grep 'nat(dst=192.168.1.5:80)'])
-
-# Start webservers in 'foo2', 'foo3' and 'foo4'.
-OVS_START_L7([foo2], [http])
-OVS_START_L7([foo3], [http])
-OVS_START_L7([foo4], [http])
-
-dnl Should work with the virtual IP address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([foo1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Test load-balancing that includes L4 ports in NAT.
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([foo1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.4,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=192.168.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.5,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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"])
-AT_CLEANUP
-
-AT_SETUP([ovn -- load balancing in gateway router])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Two LRs - R1 and R2 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
-# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24) connected
-# to it.  R2 is a gateway router on which we add load-balancing rules.
-#
-#    foo -- R1 -- join - R2 -- alice
-#           |
-#    bar ----
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Static routes.
-ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
-"192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
-
-# Config OVN load-balancer with a VIP.
-uuid=`ovn-nbctl  create load_balancer vips:30.0.0.1="192.168.1.2,192.168.2.2"`
-ovn-nbctl set logical_router R2 load_balancer=$uuid
-
-# Config OVN load-balancer with another VIP (this time with ports).
-ovn-nbctl set load_balancer $uuid vips:'"30.0.0.2:8000"'='"192.168.1.2:80,192.168.2.2:80"'
-
-# Add SNAT rule to make sure that Load-balancing still works with a SNAT rule.
-ovn-nbctl -- --id=@nat create nat type="snat" logical_ip=192.168.2.2 \
-    external_ip=30.0.0.2 -- add logical_router R2 nat @nat
-
-
-# Wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
-grep 'nat(dst=192.168.2.2:80)'])
-
-# Start webservers in 'foo1', 'bar1'.
-OVS_START_L7([foo1], [http])
-OVS_START_L7([bar1], [http])
-
-dnl Should work with the virtual IP address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Test load-balancing that includes L4 ports in NAT.
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([alice1], [wget 30.0.0.2:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- multiple gateway routers, load-balancing])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Three LRs - R1, R2 and R3 that are connected to each other via LS "join"
-# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) and
-# bar (192.168.2.0/24) connected to it. R2 has alice (172.16.1.0/24) connected
-# to it.  R3 has bob (172.16.1.0/24) connected to it. Note how both alice and
-# bob have the same subnet behind it.  We are trying to simulate external
-# network via those 2 switches. In real world the switch ports of these
-# switches will have addresses set as "unknown" to make them learning switches.
-# Or those switches will be "localnet" ones.
-#
-#    foo -- R1 -- join - R2 -- alice
-#           |          |
-#    bar ----          - R3 --- bob
-
-ovn-nbctl create Logical_Router name=R1
-ovn-nbctl create Logical_Router name=R2 options:chassis=hv1
-ovn-nbctl create Logical_Router name=R3 options:chassis=hv1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-ovn-nbctl ls-add bob
-ovn-nbctl ls-add join
-
-# Connect foo to R1
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
-
-# Connect bar to R1
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar addresses=\"00:00:01:01:02:04\"
-
-# Connect alice to R2
-ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
-
-# Connect bob to R3
-ovn-nbctl lrp-add R3 bob 00:00:03:01:02:03 172.16.1.2/24
-ovn-nbctl lsp-add bob rp-bob -- set Logical_Switch_Port rp-bob \
-    type=router options:router-port=bob addresses=\"00:00:03:01:02:03\"
-
-# Connect R1 to join
-ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
-ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
-    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"'
-
-# Connect R2 to join
-ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
-ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
-    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"'
-
-# Connect R3 to join
-ovn-nbctl lrp-add R3 R3_join 00:00:04:01:02:05 20.0.0.3/24
-ovn-nbctl lsp-add join r3-join -- set Logical_Switch_Port r3-join \
-    type=router options:router-port=R3_join addresses='"00:00:04:01:02:05"'
-
-# Install static routes with source ip address as the policy for routing.
-# We want traffic from 'foo' to go via R2 and traffic of 'bar' to go via R3.
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.1.0/24 20.0.0.2
-ovn-nbctl --policy="src-ip" lr-route-add R1 192.168.2.0/24 20.0.0.3
-
-# Static routes.
-ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
-ovn-nbctl lr-route-add R3 192.168.0.0/16 20.0.0.1
-
-# For gateway routers R2 and R3, set a force SNAT rule.
-ovn-nbctl set logical_router R2 options:lb_force_snat_ip=20.0.0.2
-ovn-nbctl set logical_router R3 options:lb_force_snat_ip=20.0.0.3
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.3/24", "f0:00:00:01:02:04", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.3"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:05", \
-"192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:05 192.168.2.2"
-
-# Logical port 'bob1' in switch 'bob'.
-ADD_NAMESPACES(bob1)
-ADD_VETH(bob1, bob1, br-int, "172.16.1.4/24", "f0:00:00:01:02:06", \
-         "172.16.1.2")
-ovn-nbctl lsp-add bob bob1 \
--- lsp-set-addresses bob1 "f0:00:00:01:02:06 172.16.1.4"
-
-# Config OVN load-balancer with a VIP.
-uuid=`ovn-nbctl  create load_balancer vips:30.0.0.1="192.168.1.2,192.168.2.2"`
-ovn-nbctl set logical_router R2 load_balancer=$uuid
-ovn-nbctl set logical_router R3 load_balancer=$uuid
-
-# Wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
-grep 'nat(dst=192.168.2.2)'])
-
-# Start webservers in 'foo1', 'bar1'.
-OVS_START_L7([foo1], [http])
-OVS_START_L7([bar1], [http])
-
-dnl Should work with the virtual IP address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([alice1], [wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=30.0.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.3,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Force SNAT should have worked.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(20.0.0) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.3,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.3,dst=192.168.2.2,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=20.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- load balancing in router with gateway router port])
-AT_KEYWORDS([ovnlb])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
-# and alice (172.16.1.0/24) connected to it.  The port between R1 and
-# alice is the router gateway port where the R1 LB rules are applied.
-#
-#    foo -- R1 -- bar
-#           |
-#    alice ----
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
-    -- set Logical_Router_Port alice options:redirect-chassis=hv1
-
-# Connect foo to R1
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect bar to R1
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar \
-    -- lsp-set-addresses rp-bar router
-
-# Connect alice to R1
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'foo2' in switch 'foo'.
-ADD_NAMESPACES(foo2)
-ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo2 \
--- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
-         "192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
-
-# Config OVN load-balancer with a VIP.
-uuid=`ovn-nbctl  create load_balancer vips:172.16.1.10="192.168.1.2,192.168.2.2"`
-ovn-nbctl set logical_router R1 load_balancer=$uuid
-
-# Config OVN load-balancer with another VIP (this time with ports).
-ovn-nbctl set load_balancer $uuid vips:'"172.16.1.11:8000"'='"192.168.1.2:80,192.168.2.2:80"'
-
-# Wait for ovn-controller to catch up.
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl -O OpenFlow13 dump-groups br-int | \
-grep 'nat(dst=192.168.2.2:80)'])
-
-# Start webservers in 'foo1', 'bar1'.
-OVS_START_L7([foo1], [http])
-OVS_START_L7([bar1], [http])
-
-dnl Should work with the virtual IP address through NAT
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([alice1], [wget 172.16.1.10 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.10) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=172.16.1.10,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-dnl Test load-balancing that includes L4 ports in NAT.
-for i in `seq 1 20`; do
-    echo Request $i
-    NS_CHECK_EXEC([alice1], [wget 172.16.1.11:8000 -t 5 -T 1 --retry-connrefused -v -o wget$i.log])
-done
-
-dnl Each server should have at least one connection.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.11) |
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-tcp,orig=(src=172.16.1.2,dst=172.16.1.11,sport=<cleared>,dport=<cleared>),reply=(src=192.168.2.2,dst=172.16.1.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,protoinfo=(state=<cleared>)
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- DNAT and SNAT on distributed router - N/S])
-AT_KEYWORDS([ovnnat])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
-# and alice (172.16.1.0/24) connected to it.  The port between R1 and
-# alice is the router gateway port where the R1 NAT rules are applied.
-#
-#    foo -- R1 -- alice
-#           |
-#    bar ----
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
-    -- set Logical_Router_Port alice options:redirect-chassis=hv1
-
-# Connect foo to R1
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect bar to R1
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar \
-    -- lsp-set-addresses rp-bar router
-
-# Connect alice to R1
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'foo2' in switch 'foo'.
-ADD_NAMESPACES(foo2)
-ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo2 \
--- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
-         "192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
-
-# Add DNAT rules
-AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2 foo1 00:00:02:02:03:04])
-AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.1.3 foo2 00:00:02:02:03:05])
-
-# Add a SNAT rule
-AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
-
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
-
-# North-South DNAT: 'alice1' pings 'foo1' using 172.16.1.3.
-NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that DNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.3) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.2,dst=172.16.1.3,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=172.16.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-# South-North SNAT: 'foo2' pings 'alice1'. But 'alice1' receives traffic
-# from 172.16.1.4
-NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.1.3,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-AT_CHECK([ovs-appctl dpctl/flush-conntrack])
-
-# South-North SNAT: 'bar1' pings 'alice1'. But 'alice1' receives traffic
-# from 172.16.1.1
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that SNAT indeed happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- DNAT and SNAT on distributed router - E/W])
-AT_KEYWORDS([ovnnat])
-
-CHECK_CONNTRACK()
-CHECK_CONNTRACK_NAT()
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24),
-# and alice (172.16.1.0/24) connected to it.  The port between R1 and
-# alice is the router gateway port where the R1 NAT rules are applied.
-#
-#    foo -- R1 -- alice
-#           |
-#    bar ----
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add foo
-ovn-nbctl ls-add bar
-ovn-nbctl ls-add alice
-
-ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lrp-add R1 bar 00:00:01:01:02:04 192.168.2.1/24
-ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
-    -- set Logical_Router_Port alice options:redirect-chassis=hv1
-
-# Connect foo to R1
-ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
-    type=router options:router-port=foo \
-    -- lsp-set-addresses rp-foo router
-
-# Connect bar to R1
-ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \
-    type=router options:router-port=bar \
-    -- lsp-set-addresses rp-bar router
-
-# Connect alice to R1
-ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
-    type=router options:router-port=alice \
-    -- lsp-set-addresses rp-alice router
-
-# Logical port 'foo1' in switch 'foo'.
-ADD_NAMESPACES(foo1)
-ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo1 \
--- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
-
-# Logical port 'foo2' in switch 'foo'.
-ADD_NAMESPACES(foo2)
-ADD_VETH(foo2, foo2, br-int, "192.168.1.3/24", "f0:00:00:01:02:06", \
-         "192.168.1.1")
-ovn-nbctl lsp-add foo foo2 \
--- lsp-set-addresses foo2 "f0:00:00:01:02:06 192.168.1.3"
-
-# Logical port 'bar1' in switch 'bar'.
-ADD_NAMESPACES(bar1)
-ADD_VETH(bar1, bar1, br-int, "192.168.2.2/24", "f0:00:00:01:02:04", \
-         "192.168.2.1")
-ovn-nbctl lsp-add bar bar1 \
--- lsp-set-addresses bar1 "f0:00:00:01:02:04 192.168.2.2"
-
-# Logical port 'alice1' in switch 'alice'.
-ADD_NAMESPACES(alice1)
-ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
-         "172.16.1.1")
-ovn-nbctl lsp-add alice alice1 \
--- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
-
-# Add DNAT rules
-AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2 foo1 00:00:02:02:03:04])
-AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.2.2 bar1 00:00:02:02:03:05])
-
-# Add a SNAT rule
-AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
-
-ovn-nbctl --wait=hv sync
-OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep 'nat(src=172.16.1.1)'])
-
-echo "------ hv dump ------"
-ovs-ofctl show br-int
-ovs-ofctl dump-flows br-int
-echo "---------------------"
-
-# East-West No NAT: 'foo1' pings 'bar1' using 192.168.2.2.
-NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that no NAT happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
-])
-
-# East-West No NAT: 'foo2' pings 'bar1' using 192.168.2.2.
-NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 192.168.2.2 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that no NAT happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
-])
-
-# East-West No NAT: 'bar1' pings 'foo2' using 192.168.1.3.
-NS_CHECK_EXEC([bar1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.3 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# We verify that no NAT happened via 'dump-conntrack' command.
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.2.2) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | wc -l], [0], [0
-])
-
-# East-West NAT: 'foo1' pings 'bar1' using 172.16.1.4.
-NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# Check conntrack entries.  First SNAT of 'foo1' address happens.
-# Then DNAT of 'bar1' address happens (listed first below).
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.4) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-icmp,orig=(src=192.168.1.2,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-AT_CHECK([ovs-appctl dpctl/flush-conntrack])
-
-# East-West NAT: 'foo2' pings 'bar1' using 172.16.1.4.
-NS_CHECK_EXEC([foo2], [ping -q -c 3 -i 0.3 -w 2 172.16.1.4 | FORMAT_PING], \
-[0], [dnl
-3 packets transmitted, 3 received, 0% packet loss, time 0ms
-])
-
-# Check conntrack entries.  First SNAT of 'foo2' address happens.
-# Then DNAT of 'bar1' address happens (listed first below).
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.1.1) | \
-sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
-icmp,orig=(src=172.16.1.1,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=192.168.2.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-icmp,orig=(src=192.168.1.3,dst=172.16.1.4,id=<cleared>,type=8,code=0),reply=(src=172.16.1.4,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
-
-AT_SETUP([ovn -- 2 LSs IGMP])
-AT_KEYWORDS([ovnigmp])
-
-ovn_start
-
-OVS_TRAFFIC_VSWITCHD_START()
-ADD_BR([br-int])
-
-# Set external-ids in br-int needed for ovn-controller
-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.0.0.1 \
-        -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
-
-# Start ovn-controller
-start_daemon ovn-controller
-
-# Logical network:
-# Two independent logical switches (sw1 and sw2).
-# sw1:
-#   - subnet 10.0.0.0/8
-#   - 2 ports (sw1-p1 - sw1-p2)
-# sw2:
-#   - subnet 20.0.0.0/8
-#   - 2 port (sw2-p1 - sw2-p2)
-#   - IGMP Querier from 20.0.0.254
-
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add sw2
-
-for i in `seq 1 2`
-do
-    ADD_NAMESPACES(sw1-p$i)
-    ADD_VETH(sw1-p$i, sw1-p$i, br-int, "10.0.0.$i/24", "00:00:00:00:01:0$i", \
-            "10.0.0.254")
-    ovn-nbctl lsp-add sw1 sw1-p$i \
-        -- lsp-set-addresses sw1-p$i "00:00:00:00:01:0$i 10.0.0.$i"
-done
-
-for i in `seq 1 2`
-do
-    ADD_NAMESPACES(sw2-p$i)
-    ADD_VETH(sw2-p$i, sw2-p$i, br-int, "20.0.0.$i/24", "00:00:00:00:02:0$i", \
-            "20.0.0.254")
-    ovn-nbctl lsp-add sw2 sw2-p$i \
-        -- lsp-set-addresses sw2-p$i "00:00:00:00:02:0$i 20.0.0.$i"
-done
-
-# Enable IGMP snooping on sw1.
-ovn-nbctl set Logical_Switch sw1 other_config:mcast_querier="false"
-ovn-nbctl set Logical_Switch sw1 other_config:mcast_snoop="true"
-
-# Inject IGMP Join for 239.0.1.68 on sw1-p1.
-NS_CHECK_EXEC([sw1-p1], [ip addr add dev sw1-p1 239.0.1.68/32 autojoin], [0])
-
-# Inject IGMP Join for 239.0.1.68 on sw1-p2
-NS_CHECK_EXEC([sw1-p2], [ip addr add dev sw1-p2 239.0.1.68/32 autojoin], [0])
-
-# Check that the IGMP Group is learned.
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d ":" | wc -w`
-    test "${total_entries}" = "1"
-    test "${ports}" = "2"
-])
-
-# Inject IGMP Leave for 239.0.1.68 on sw1-p2.
-NS_CHECK_EXEC([sw1-p2], [ip addr del dev sw1-p2 239.0.1.68/32], [0])
-
-# Check that only one port is left in the group.
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    ports=`ovn-sbctl find IGMP_Group | grep ports | cut -f 2 -d ":" | wc -w`
-    test "${total_entries}" = "1"
-    test "${ports}" = "1"
-])
-
-# Flush IGMP groups.
-ovn-sbctl ip-multicast-flush sw1
-ovn-nbctl --wait=hv -t 3 sync
-OVS_WAIT_UNTIL([
-    total_entries=`ovn-sbctl find IGMP_Group | grep "239.0.1.68" | wc -l`
-    test "${total_entries}" = "0"
-])
-
-# Enable IGMP snooping and querier on sw2 and set query interval to minimum.
-ovn-nbctl set Logical_Switch sw2 \
-    other_config:mcast_snoop="true" \
-    other_config:mcast_querier="true" \
-    other_config:mcast_query_interval=1 \
-    other_config:mcast_eth_src="00:00:00:00:02:fe" \
-    other_config:mcast_ip4_src="20.0.0.254"
-
-# Check that queries are generated.
-NS_CHECK_EXEC([sw2-p1], [tcpdump -n -c 2 -i sw2-p1 igmp > sw2-p1.pcap &])
-
-OVS_WAIT_UNTIL([
-    total_queries=`cat sw2-p1.pcap | grep "igmp query" | wc -l`
-    test "${total_queries}" = "2"
-])
-
-OVS_APP_EXIT_AND_WAIT([ovn-controller])
-
-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
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
deleted file mode 100644
index 0b9e824..0000000
--- a/tests/test-ovn.c
+++ /dev/null
@@ -1,1584 +0,0 @@ 
-/*
- * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-#include <errno.h>
-#include <getopt.h>
-#include <sys/wait.h>
-
-#include "command-line.h"
-#include "dp-packet.h"
-#include "fatal-signal.h"
-#include "flow.h"
-#include "openvswitch/dynamic-string.h"
-#include "openvswitch/match.h"
-#include "openvswitch/ofp-actions.h"
-#include "openvswitch/ofpbuf.h"
-#include "openvswitch/vlog.h"
-#include "ovn/actions.h"
-#include "ovn/expr.h"
-#include "ovn/lex.h"
-#include "ovn/logical-fields.h"
-#include "ovn/lib/ovn-l7.h"
-#include "ovn/lib/extend-table.h"
-#include "ovs-thread.h"
-#include "ovstest.h"
-#include "openvswitch/shash.h"
-#include "simap.h"
-#include "util.h"
-
-/* --relops: Bitmap of the relational operators to test, in exhaustive test. */
-static unsigned int test_relops;
-
-/* --nvars: Number of numeric variables to test, in exhaustive test. */
-static int test_nvars = 2;
-
-/* --svars: Number of string variables to test, in exhaustive test. */
-static int test_svars = 2;
-
-/* --bits: Number of bits per variable, in exhaustive test. */
-static int test_bits = 3;
-
-/* --operation: The operation to test, in exhaustive test. */
-static enum { OP_CONVERT, OP_SIMPLIFY, OP_NORMALIZE, OP_FLOW } operation
-    = OP_FLOW;
-
-/* --parallel: Number of parallel processes to use in test. */
-static int test_parallel = 1;
-
-/* -m, --more: Message verbosity */
-static int verbosity;
-
-static void
-compare_token(const struct lex_token *a, const struct lex_token *b)
-{
-    if (a->type != b->type) {
-        fprintf(stderr, "type differs: %d -> %d\n", a->type, b->type);
-        return;
-    }
-
-    if (!((a->s && b->s && !strcmp(a->s, b->s))
-          || (!a->s && !b->s))) {
-        fprintf(stderr, "string differs: %s -> %s\n",
-                a->s ? a->s : "(null)",
-                b->s ? b->s : "(null)");
-        return;
-    }
-
-    if (a->type == LEX_T_INTEGER || a->type == LEX_T_MASKED_INTEGER) {
-        if (memcmp(&a->value, &b->value, sizeof a->value)) {
-            fprintf(stderr, "value differs\n");
-            return;
-        }
-
-        if (a->type == LEX_T_MASKED_INTEGER
-            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
-            fprintf(stderr, "mask differs\n");
-            return;
-        }
-
-        if (a->format != b->format
-            && !(a->format == LEX_F_HEXADECIMAL
-                 && b->format == LEX_F_DECIMAL
-                 && a->value.integer == 0)) {
-            fprintf(stderr, "format differs: %d -> %d\n",
-                    a->format, b->format);
-        }
-    }
-}
-
-static void
-test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    struct ds input;
-    struct ds output;
-
-    ds_init(&input);
-    ds_init(&output);
-    while (!ds_get_test_line(&input, stdin)) {
-        struct lexer lexer;
-
-        lexer_init(&lexer, ds_cstr(&input));
-        ds_clear(&output);
-        while (lexer_get(&lexer) != LEX_T_END) {
-            size_t len = output.length;
-            lex_token_format(&lexer.token, &output);
-
-            /* Check that the formatted version can really be parsed back
-             * losslessly. */
-            if (lexer.token.type != LEX_T_ERROR) {
-                const char *s = ds_cstr(&output) + len;
-                struct lexer l2;
-
-                lexer_init(&l2, s);
-                lexer_get(&l2);
-                compare_token(&lexer.token, &l2.token);
-                lexer_destroy(&l2);
-            }
-            ds_put_char(&output, ' ');
-        }
-        lexer_destroy(&lexer);
-
-        ds_chomp(&output, ' ');
-        puts(ds_cstr(&output));
-    }
-    ds_destroy(&input);
-    ds_destroy(&output);
-}
-
-static void
-create_symtab(struct shash *symtab)
-{
-    ovn_init_symtab(symtab);
-
-    /* For negative testing. */
-    expr_symtab_add_field(symtab, "bad_prereq", MFF_XREG0, "xyzzy", false);
-    expr_symtab_add_field(symtab, "self_recurse", MFF_XREG0,
-                          "self_recurse != 0", false);
-    expr_symtab_add_field(symtab, "mutual_recurse_1", MFF_XREG0,
-                          "mutual_recurse_2 != 0", false);
-    expr_symtab_add_field(symtab, "mutual_recurse_2", MFF_XREG0,
-                          "mutual_recurse_1 != 0", false);
-    expr_symtab_add_string(symtab, "big_string", MFF_XREG0, NULL);
-}
-
-static void
-create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
-                struct hmap *nd_ra_opts,
-                struct controller_event_options *event_opts)
-{
-    hmap_init(dhcp_opts);
-    dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
-    dhcp_opt_add(dhcp_opts, "netmask", 1, "ipv4");
-    dhcp_opt_add(dhcp_opts, "router",  3, "ipv4");
-    dhcp_opt_add(dhcp_opts, "dns_server", 6, "ipv4");
-    dhcp_opt_add(dhcp_opts, "log_server", 7, "ipv4");
-    dhcp_opt_add(dhcp_opts, "lpr_server",  9, "ipv4");
-    dhcp_opt_add(dhcp_opts, "domain_name", 15, "str");
-    dhcp_opt_add(dhcp_opts, "swap_server", 16, "ipv4");
-    dhcp_opt_add(dhcp_opts, "policy_filter", 21, "ipv4");
-    dhcp_opt_add(dhcp_opts, "router_solicitation",  32, "ipv4");
-    dhcp_opt_add(dhcp_opts, "nis_server", 41, "ipv4");
-    dhcp_opt_add(dhcp_opts, "ntp_server", 42, "ipv4");
-    dhcp_opt_add(dhcp_opts, "server_id",  54, "ipv4");
-    dhcp_opt_add(dhcp_opts, "tftp_server", 66, "ipv4");
-    dhcp_opt_add(dhcp_opts, "classless_static_route", 121, "static_routes");
-    dhcp_opt_add(dhcp_opts, "ip_forward_enable",  19, "bool");
-    dhcp_opt_add(dhcp_opts, "router_discovery", 31, "bool");
-    dhcp_opt_add(dhcp_opts, "ethernet_encap", 36, "bool");
-    dhcp_opt_add(dhcp_opts, "default_ttl",  23, "uint8");
-    dhcp_opt_add(dhcp_opts, "tcp_ttl", 37, "uint8");
-    dhcp_opt_add(dhcp_opts, "mtu", 26, "uint16");
-    dhcp_opt_add(dhcp_opts, "lease_time",  51, "uint32");
-    dhcp_opt_add(dhcp_opts, "wpad", 252, "str");
-    dhcp_opt_add(dhcp_opts, "bootfile_name", 67, "str");
-    dhcp_opt_add(dhcp_opts, "path_prefix", 210, "str");
-    dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
-
-    /* DHCPv6 options. */
-    hmap_init(dhcpv6_opts);
-    dhcp_opt_add(dhcpv6_opts, "server_id",  2, "mac");
-    dhcp_opt_add(dhcpv6_opts, "ia_addr",  5, "ipv6");
-    dhcp_opt_add(dhcpv6_opts, "dns_server",  23, "ipv6");
-    dhcp_opt_add(dhcpv6_opts, "domain_search",  24, "str");
-
-    /* IPv6 ND RA options. */
-    hmap_init(nd_ra_opts);
-    nd_ra_opts_init(nd_ra_opts);
-
-    /* OVN controller events options. */
-    controller_event_opts_init(event_opts);
-}
-
-static void
-create_addr_sets(struct shash *addr_sets)
-{
-    shash_init(addr_sets);
-
-    static const char *const addrs1[] = {
-        "10.0.0.1", "10.0.0.2", "10.0.0.3",
-    };
-    static const char *const addrs2[] = {
-        "::1", "::2", "::3",
-    };
-    static const char *const addrs3[] = {
-        "00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03",
-    };
-    static const char *const addrs4[] = { NULL };
-
-    expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
-    expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
-    expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
-    expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
-}
-
-static void
-create_port_groups(struct shash *port_groups)
-{
-    shash_init(port_groups);
-
-    static const char *const pg1[] = {
-        "lsp1", "lsp2", "lsp3",
-    };
-    static const char *const pg2[] = { NULL };
-
-    expr_const_sets_add(port_groups, "pg1", pg1, 3, false);
-    expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false);
-}
-
-static bool
-lookup_port_cb(const void *ports_, const char *port_name, unsigned int *portp)
-{
-    const struct simap *ports = ports_;
-    const struct simap_node *node = simap_find(ports, port_name);
-    if (!node) {
-        return false;
-    }
-    *portp = node->data;
-    return true;
-}
-
-static bool
-is_chassis_resident_cb(const void *ports_, const char *port_name)
-{
-    const struct simap *ports = ports_;
-    const struct simap_node *node = simap_find(ports, port_name);
-    if (node) {
-        return true;
-    }
-    return false;
-}
-
-static void
-test_parse_expr__(int steps)
-{
-    struct shash symtab;
-    struct shash addr_sets;
-    struct shash port_groups;
-    struct simap ports;
-    struct ds input;
-
-    create_symtab(&symtab);
-    create_addr_sets(&addr_sets);
-    create_port_groups(&port_groups);
-
-    simap_init(&ports);
-    simap_put(&ports, "eth0", 5);
-    simap_put(&ports, "eth1", 6);
-    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
-    simap_put(&ports, "lsp1", 0x11);
-    simap_put(&ports, "lsp2", 0x12);
-    simap_put(&ports, "lsp3", 0x13);
-
-    ds_init(&input);
-    while (!ds_get_test_line(&input, stdin)) {
-        struct expr *expr;
-        char *error;
-
-        expr = expr_parse_string(ds_cstr(&input), &symtab, &addr_sets,
-                                 &port_groups, NULL, &error);
-        if (!error && steps > 0) {
-            expr = expr_annotate(expr, &symtab, &error);
-        }
-        if (!error) {
-            if (steps > 1) {
-                expr = expr_simplify(expr, is_chassis_resident_cb, &ports);
-            }
-            if (steps > 2) {
-                expr = expr_normalize(expr);
-                ovs_assert(expr_is_normalized(expr));
-            }
-        }
-        if (!error) {
-            if (steps > 3) {
-                struct hmap matches;
-
-                expr_to_matches(expr, lookup_port_cb, &ports, &matches);
-                expr_matches_print(&matches, stdout);
-                expr_matches_destroy(&matches);
-            } else {
-                struct ds output = DS_EMPTY_INITIALIZER;
-                expr_format(expr, &output);
-                puts(ds_cstr(&output));
-                ds_destroy(&output);
-            }
-        } else {
-            puts(error);
-            free(error);
-        }
-        expr_destroy(expr);
-    }
-    ds_destroy(&input);
-
-    simap_destroy(&ports);
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-    expr_const_sets_destroy(&addr_sets);
-    shash_destroy(&addr_sets);
-    expr_const_sets_destroy(&port_groups);
-    shash_destroy(&port_groups);
-}
-
-static void
-test_parse_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    test_parse_expr__(0);
-}
-
-static void
-test_annotate_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    test_parse_expr__(1);
-}
-
-static void
-test_simplify_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    test_parse_expr__(2);
-}
-
-static void
-test_normalize_expr(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    test_parse_expr__(3);
-}
-
-static void
-test_expr_to_flows(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    test_parse_expr__(4);
-}
-
-/* Print the symbol table. */
-
-static void
-test_dump_symtab(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    struct shash symtab;
-    create_symtab(&symtab);
-
-    const struct shash_node **nodes = shash_sort(&symtab);
-    for (size_t i = 0; i < shash_count(&symtab); i++) {
-        const struct expr_symbol *symbol = nodes[i]->data;
-        struct ds s = DS_EMPTY_INITIALIZER;
-        expr_symbol_format(symbol, &s);
-        puts(ds_cstr(&s));
-        ds_destroy(&s);
-    }
-
-    free(nodes);
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-}
-
-/* Evaluate an expression. */
-
-static bool
-lookup_atoi_cb(const void *aux OVS_UNUSED, const char *port_name,
-               unsigned int *portp)
-{
-    *portp = atoi(port_name);
-    return true;
-}
-
-static void
-test_evaluate_expr(struct ovs_cmdl_context *ctx)
-{
-    struct shash symtab;
-    struct ds input;
-
-    ovn_init_symtab(&symtab);
-
-    struct flow uflow;
-    char *error = expr_parse_microflow(ctx->argv[1], &symtab, NULL, NULL,
-                                       lookup_atoi_cb, NULL, &uflow);
-    if (error) {
-        ovs_fatal(0, "%s", error);
-    }
-
-    ds_init(&input);
-    while (!ds_get_test_line(&input, stdin)) {
-        struct expr *expr;
-
-        expr = expr_parse_string(ds_cstr(&input), &symtab, NULL, NULL, NULL,
-                                 &error);
-        if (!error) {
-            expr = expr_annotate(expr, &symtab, &error);
-        }
-        if (!error) {
-            printf("%d\n", expr_evaluate(expr, &uflow, lookup_atoi_cb, NULL));
-        } else {
-            puts(error);
-            free(error);
-        }
-        expr_destroy(expr);
-    }
-    ds_destroy(&input);
-
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-}
-
-/* Compositions.
- *
- * The "compositions" of a positive integer N are all of the ways that one can
- * add up positive integers to sum to N.  For example, the compositions of 3
- * are 3, 2+1, 1+2, and 1+1+1.
- *
- * We use compositions to find all the ways to break up N terms of a Boolean
- * expression into subexpressions.  Suppose we want to generate all expressions
- * with 3 terms.  The compositions of 3 (ignoring 3 itself) provide the
- * possibilities (x && x) || x, x || (x && x), and x || x || x.  (Of course one
- * can exchange && for || in each case.)  One must recursively compose the
- * sub-expressions whose values are 3 or greater; that is what the "tree shape"
- * concept later covers.
- *
- * To iterate through all compositions of, e.g., 5:
- *
- *     unsigned int state;
- *     int s[5];
- *     int n;
- *
- *     for (n = first_composition(ARRAY_SIZE(s), &state, s); n > 0;
- *          n = next_composition(&state, s, n)) {
- *          // Do something with composition 's' with 'n' elements.
- *     }
- *
- * Algorithm from D. E. Knuth, _The Art of Computer Programming, Vol. 4A:
- * Combinatorial Algorithms, Part 1_, section 7.2.1.1, answer to exercise
- * 12(a).
- */
-
-/* Begins iteration through the compositions of 'n'.  Initializes 's' to the
- * number of elements in the first composition of 'n' and returns that number
- * of elements.  The first composition in fact is always 'n' itself, so the
- * return value will be 1.
- *
- * Initializes '*state' to some internal state information.  The caller must
- * maintain this state (and 's') for use by next_composition().
- *
- * 's' must have room for at least 'n' elements. */
-static int
-first_composition(int n, unsigned int *state, int s[])
-{
-    *state = 0;
-    s[0] = n;
-    return 1;
-}
-
-/* Advances 's', with 'sn' elements, to the next composition and returns the
- * number of elements in this new composition, or 0 if no compositions are
- * left.  'state' is the same internal state passed to first_composition(). */
-static int
-next_composition(unsigned int *state, int s[], int sn)
-{
-    int j = sn - 1;
-    if (++*state & 1) {
-        if (s[j] > 1) {
-            s[j]--;
-            s[j + 1] = 1;
-            j++;
-        } else {
-            j--;
-            s[j]++;
-        }
-    } else {
-        if (s[j - 1] > 1) {
-            s[j - 1]--;
-            s[j + 1] = s[j];
-            s[j] = 1;
-            j++;
-        } else {
-            j--;
-            if (!j) {
-                return 0;
-            }
-            s[j] = s[j + 1];
-            s[j - 1]++;
-        }
-    }
-    return j + 1;
-}
-
-static void
-test_composition(struct ovs_cmdl_context *ctx)
-{
-    int n = atoi(ctx->argv[1]);
-    unsigned int state;
-    int s[50];
-
-    for (int sn = first_composition(n, &state, s); sn;
-         sn = next_composition(&state, s, sn)) {
-        for (int i = 0; i < sn; i++) {
-            printf("%d%c", s[i], i == sn - 1 ? '\n' : ' ');
-        }
-    }
-}
-
-/* Tree shapes.
- *
- * This code generates all possible Boolean expressions with a specified number
- * of terms N (equivalent to the number of external nodes in a tree).
- *
- * See test_tree_shape() for a simple example. */
-
-/* An array of these structures describes the shape of a tree.
- *
- * A single element of struct tree_shape describes a single node in the tree.
- * The node has 'sn' direct children.  From left to right, for i in 0...sn-1,
- * s[i] is 1 if the child is a leaf node, otherwise the child is a subtree and
- * s[i] is the number of leaf nodes within that subtree.  In the latter case,
- * the subtree is described by another struct tree_shape within the enclosing
- * array.  The tree_shapes are ordered in the array in in-order.
- */
-struct tree_shape {
-    unsigned int state;
-    int s[50];
-    int sn;
-};
-
-static int
-init_tree_shape__(struct tree_shape ts[], int n)
-{
-    if (n <= 2) {
-        return 0;
-    }
-
-    int n_tses = 1;
-    /* Skip the first composition intentionally. */
-    ts->sn = first_composition(n, &ts->state, ts->s);
-    ts->sn = next_composition(&ts->state, ts->s, ts->sn);
-    for (int i = 0; i < ts->sn; i++) {
-        n_tses += init_tree_shape__(&ts[n_tses], ts->s[i]);
-    }
-    return n_tses;
-}
-
-/* Initializes 'ts[]' as the first in the set of all of possible shapes of
- * trees with 'n' leaves.  Returns the number of "struct tree_shape"s in the
- * first tree shape. */
-static int
-init_tree_shape(struct tree_shape ts[], int n)
-{
-    switch (n) {
-    case 1:
-        ts->sn = 1;
-        ts->s[0] = 1;
-        return 1;
-    case 2:
-        ts->sn = 2;
-        ts->s[0] = 1;
-        ts->s[1] = 1;
-        return 1;
-    default:
-        return init_tree_shape__(ts, n);
-    }
-}
-
-/* Advances 'ts', which currently has 'n_tses' elements, to the next possible
- * tree shape with the number of leaves passed to init_tree_shape().  Returns
- * the number of "struct tree_shape"s in the next shape, or 0 if all tree
- * shapes have been visited. */
-static int
-next_tree_shape(struct tree_shape ts[], int n_tses)
-{
-    if (n_tses == 1 && ts->sn == 2 && ts->s[0] == 1 && ts->s[1] == 1) {
-        return 0;
-    }
-    while (n_tses > 0) {
-        struct tree_shape *p = &ts[n_tses - 1];
-        p->sn = p->sn > 1 ? next_composition(&p->state, p->s, p->sn) : 0;
-        if (p->sn) {
-            for (int i = 0; i < p->sn; i++) {
-                n_tses += init_tree_shape__(&ts[n_tses], p->s[i]);
-            }
-            break;
-        }
-        n_tses--;
-    }
-    return n_tses;
-}
-
-static void
-print_tree_shape(const struct tree_shape ts[], int n_tses)
-{
-    for (int i = 0; i < n_tses; i++) {
-        if (i) {
-            printf(", ");
-        }
-        for (int j = 0; j < ts[i].sn; j++) {
-            int k = ts[i].s[j];
-            if (k > 9) {
-                printf("(%d)", k);
-            } else {
-                printf("%d", k);
-            }
-        }
-    }
-}
-
-static void
-test_tree_shape(struct ovs_cmdl_context *ctx)
-{
-    int n = atoi(ctx->argv[1]);
-    struct tree_shape ts[50];
-    int n_tses;
-
-    for (n_tses = init_tree_shape(ts, n); n_tses;
-         n_tses = next_tree_shape(ts, n_tses)) {
-        print_tree_shape(ts, n_tses);
-        putchar('\n');
-    }
-}
-
-/* Iteration through all possible terminal expressions (e.g. EXPR_T_CMP and
- * EXPR_T_BOOLEAN expressions).
- *
- * Given a tree shape, this allows the code to try all possible ways to plug in
- * terms.
- *
- * Example use:
- *
- *     struct expr terminal;
- *     const struct expr_symbol *vars = ...;
- *     int n_vars = ...;
- *     int n_bits = ...;
- *
- *     init_terminal(&terminal, vars[0]);
- *     do {
- *         // Something with 'terminal'.
- *     } while (next_terminal(&terminal, vars, n_vars, n_bits));
- */
-
-/* Sets 'expr' to the first possible terminal expression.  'var' should be the
- * first variable in the ones to be tested. */
-static void
-init_terminal(struct expr *expr, int phase,
-              const struct expr_symbol *nvars[], int n_nvars,
-              const struct expr_symbol *svars[], int n_svars)
-{
-    if (phase < 1 && n_nvars) {
-        expr->type = EXPR_T_CMP;
-        expr->cmp.symbol = nvars[0];
-        expr->cmp.relop = rightmost_1bit_idx(test_relops);
-        memset(&expr->cmp.value, 0, sizeof expr->cmp.value);
-        memset(&expr->cmp.mask, 0, sizeof expr->cmp.mask);
-        expr->cmp.value.integer = htonll(0);
-        expr->cmp.mask.integer = htonll(0);
-        return;
-    }
-
-    if (phase < 2 && n_svars) {
-        expr->type = EXPR_T_CMP;
-        expr->cmp.symbol = svars[0];
-        expr->cmp.relop = EXPR_R_EQ;
-        expr->cmp.string = xstrdup("0");
-        return;
-    }
-
-    expr->type = EXPR_T_BOOLEAN;
-    expr->boolean = false;
-}
-
-/* Returns 'x' with the rightmost contiguous string of 1s changed to 0s,
- * e.g. 01011100 => 01000000.  See H. S. Warren, Jr., _Hacker's Delight_, 2nd
- * ed., section 2-1. */
-static unsigned int
-turn_off_rightmost_1s(unsigned int x)
-{
-    return ((x & -x) + x) & x;
-}
-
-static const struct expr_symbol *
-next_var(const struct expr_symbol *symbol,
-         const struct expr_symbol *vars[], int n_vars)
-{
-    for (int i = 0; i < n_vars; i++) {
-        if (symbol == vars[i]) {
-            return i + 1 >= n_vars ? NULL : vars[i + 1];
-        }
-    }
-    OVS_NOT_REACHED();
-}
-
-static enum expr_relop
-next_relop(enum expr_relop relop)
-{
-    unsigned int remaining_relops = test_relops & ~((1u << (relop + 1)) - 1);
-    return (remaining_relops
-            ? rightmost_1bit_idx(remaining_relops)
-            : rightmost_1bit_idx(test_relops));
-}
-
-/* Advances 'expr' to the next possible terminal expression within the 'n_vars'
- * variables of 'n_bits' bits each in 'vars[]'. */
-static bool
-next_terminal(struct expr *expr,
-              const struct expr_symbol *nvars[], int n_nvars, int n_bits,
-              const struct expr_symbol *svars[], int n_svars)
-{
-    if (expr->type == EXPR_T_BOOLEAN) {
-        if (expr->boolean) {
-            return false;
-        } else {
-            expr->boolean = true;
-            return true;
-        }
-    }
-
-    if (!expr->cmp.symbol->width) {
-        int next_value = atoi(expr->cmp.string) + 1;
-        free(expr->cmp.string);
-        if (next_value > 1) {
-            expr->cmp.symbol = next_var(expr->cmp.symbol, svars, n_svars);
-            if (!expr->cmp.symbol) {
-                init_terminal(expr, 2, nvars, n_nvars, svars, n_svars);
-                return true;
-            }
-            next_value = 0;
-        }
-        expr->cmp.string = xasprintf("%d", next_value);
-        return true;
-    }
-
-    unsigned int next;
-
-    next = (ntohll(expr->cmp.value.integer)
-            + (ntohll(expr->cmp.mask.integer) << n_bits));
-    for (;;) {
-        next++;
-        unsigned m = next >> n_bits;
-        unsigned v = next & ((1u << n_bits) - 1);
-        if (next >= (1u << (2 * n_bits))) {
-            enum expr_relop old_relop = expr->cmp.relop;
-            expr->cmp.relop = next_relop(old_relop);
-            if (expr->cmp.relop <= old_relop) {
-                expr->cmp.symbol = next_var(expr->cmp.symbol, nvars, n_nvars);
-                if (!expr->cmp.symbol) {
-                    init_terminal(expr, 1, nvars, n_nvars, svars, n_svars);
-                    return true;
-                }
-            }
-            next = UINT_MAX;
-        } else if (v & ~m) {
-            /* Skip: 1-bits in value correspond to 0-bits in mask. */
-        } else if ((!m || turn_off_rightmost_1s(m))
-                   && (expr->cmp.relop != EXPR_R_EQ &&
-                       expr->cmp.relop != EXPR_R_NE)) {
-            /* Skip: can't have discontiguous or all-0 mask for > >= < <=. */
-        } else {
-            expr->cmp.value.integer = htonll(v);
-            expr->cmp.mask.integer = htonll(m);
-            return true;
-        }
-    }
-}
-
-static struct expr *
-make_terminal(struct expr ***terminalp)
-{
-    struct expr *e = expr_create_boolean(true);
-    **terminalp = e;
-    (*terminalp)++;
-    return e;
-}
-
-static struct expr *
-build_simple_tree(enum expr_type type, int n, struct expr ***terminalp)
-{
-    if (n == 2) {
-        struct expr *e = expr_create_andor(type);
-        for (int i = 0; i < 2; i++) {
-            struct expr *sub = make_terminal(terminalp);
-            ovs_list_push_back(&e->andor, &sub->node);
-        }
-        return e;
-    } else if (n == 1) {
-        return make_terminal(terminalp);
-    } else {
-        OVS_NOT_REACHED();
-    }
-}
-
-static struct expr *
-build_tree_shape(enum expr_type type, const struct tree_shape **tsp,
-                 struct expr ***terminalp)
-{
-    const struct tree_shape *ts = *tsp;
-    (*tsp)++;
-
-    struct expr *e = expr_create_andor(type);
-    enum expr_type t = type == EXPR_T_AND ? EXPR_T_OR : EXPR_T_AND;
-    for (int i = 0; i < ts->sn; i++) {
-        struct expr *sub = (ts->s[i] > 2
-                            ? build_tree_shape(t, tsp, terminalp)
-                            : build_simple_tree(t, ts->s[i], terminalp));
-        ovs_list_push_back(&e->andor, &sub->node);
-    }
-    return e;
-}
-
-struct test_rule {
-    struct cls_rule cr;
-};
-
-static void
-free_rule(struct test_rule *test_rule)
-{
-    cls_rule_destroy(&test_rule->cr);
-    free(test_rule);
-}
-
-static bool
-tree_shape_is_chassis_resident_cb(const void *c_aux OVS_UNUSED,
-                                  const char *port_name OVS_UNUSED)
-{
-    return true;
-}
-
-static int
-test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab,
-                             struct expr *terminals[], int n_terminals,
-                             const struct expr_symbol *nvars[], int n_nvars,
-                             int n_bits,
-                             const struct expr_symbol *svars[], int n_svars)
-{
-    int n_tested = 0;
-
-    const unsigned int var_mask = (1u << n_bits) - 1;
-    for (int i = 0; i < n_terminals; i++) {
-        init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
-    }
-
-    struct ds s = DS_EMPTY_INITIALIZER;
-    struct flow f;
-    memset(&f, 0, sizeof f);
-    for (;;) {
-        for (int i = n_terminals - 1; ; i--) {
-            if (!i) {
-                ds_destroy(&s);
-                return n_tested;
-            }
-            if (next_terminal(terminals[i], nvars, n_nvars, n_bits,
-                              svars, n_svars)) {
-                break;
-            }
-            init_terminal(terminals[i], 0, nvars, n_nvars, svars, n_svars);
-        }
-        ovs_assert(expr_honors_invariants(expr));
-
-        n_tested++;
-
-        struct expr *modified;
-        if (operation == OP_CONVERT) {
-            ds_clear(&s);
-            expr_format(expr, &s);
-
-            char *error;
-            modified = expr_parse_string(ds_cstr(&s), symtab, NULL,
-                                         NULL, NULL, &error);
-            if (error) {
-                fprintf(stderr, "%s fails to parse (%s)\n",
-                        ds_cstr(&s), error);
-                exit(EXIT_FAILURE);
-            }
-        } else if (operation >= OP_SIMPLIFY) {
-            modified = expr_simplify(expr_clone(expr),
-                                     tree_shape_is_chassis_resident_cb,
-                                     NULL);
-            ovs_assert(expr_honors_invariants(modified));
-
-            if (operation >= OP_NORMALIZE) {
-                modified = expr_normalize(modified);
-                ovs_assert(expr_honors_invariants(modified));
-                ovs_assert(expr_is_normalized(modified));
-            }
-        }
-
-        struct hmap matches;
-        struct classifier cls;
-        if (operation >= OP_FLOW) {
-            struct expr_match *m;
-            struct test_rule *test_rule;
-
-            expr_to_matches(modified, lookup_atoi_cb, NULL, &matches);
-
-            classifier_init(&cls, NULL);
-            HMAP_FOR_EACH (m, hmap_node, &matches) {
-                test_rule = xmalloc(sizeof *test_rule);
-                cls_rule_init(&test_rule->cr, &m->match, 0);
-                classifier_insert(&cls, &test_rule->cr, OVS_VERSION_MIN,
-                                  m->conjunctions, m->n);
-            }
-        }
-        for (int subst = 0; subst < 1 << (n_bits * n_nvars + n_svars);
-             subst++) {
-            for (int i = 0; i < n_nvars; i++) {
-                f.regs[i] = (subst >> (i * n_bits)) & var_mask;
-            }
-            for (int i = 0; i < n_svars; i++) {
-                f.regs[n_nvars + i] = ((subst >> (n_nvars * n_bits + i))
-                                       & 1);
-            }
-
-            bool expected = expr_evaluate(expr, &f, lookup_atoi_cb, NULL);
-            bool actual = expr_evaluate(modified, &f, lookup_atoi_cb, NULL);
-            if (actual != expected) {
-                struct ds expr_s, modified_s;
-
-                ds_init(&expr_s);
-                expr_format(expr, &expr_s);
-
-                ds_init(&modified_s);
-                expr_format(modified, &modified_s);
-
-                fprintf(stderr,
-                        "%s evaluates to %d, but %s evaluates to %d, for",
-                        ds_cstr(&expr_s), expected,
-                        ds_cstr(&modified_s), actual);
-                for (int i = 0; i < n_nvars; i++) {
-                    if (i > 0) {
-                        fputs(",", stderr);
-                    }
-                    fprintf(stderr, " n%d = 0x%x", i,
-                            (subst >> (n_bits * i)) & var_mask);
-                }
-                for (int i = 0; i < n_svars; i++) {
-                    fprintf(stderr, ", s%d = \"%d\"", i,
-                            (subst >> (n_bits * n_nvars + i)) & 1);
-                }
-                putc('\n', stderr);
-                exit(EXIT_FAILURE);
-            }
-
-            if (operation >= OP_FLOW) {
-                bool found = classifier_lookup(&cls, OVS_VERSION_MIN,
-                                               &f, NULL) != NULL;
-                if (expected != found) {
-                    struct ds expr_s, modified_s;
-
-                    ds_init(&expr_s);
-                    expr_format(expr, &expr_s);
-
-                    ds_init(&modified_s);
-                    expr_format(modified, &modified_s);
-
-                    fprintf(stderr,
-                            "%s and %s evaluate to %d, for",
-                            ds_cstr(&expr_s), ds_cstr(&modified_s), expected);
-                    for (int i = 0; i < n_nvars; i++) {
-                        if (i > 0) {
-                            fputs(",", stderr);
-                        }
-                        fprintf(stderr, " n%d = 0x%x", i,
-                                (subst >> (n_bits * i)) & var_mask);
-                    }
-                    for (int i = 0; i < n_svars; i++) {
-                        fprintf(stderr, ", s%d = \"%d\"", i,
-                                (subst >> (n_bits * n_nvars + i)) & 1);
-                    }
-                    fputs(".\n", stderr);
-
-                    fprintf(stderr, "Converted to classifier:\n");
-                    expr_matches_print(&matches, stderr);
-                    fprintf(stderr,
-                            "However, %s flow was found in the classifier.\n",
-                            found ? "a" : "no");
-                    exit(EXIT_FAILURE);
-                }
-            }
-        }
-        if (operation >= OP_FLOW) {
-            struct test_rule *test_rule;
-
-            CLS_FOR_EACH (test_rule, cr, &cls) {
-                classifier_remove_assert(&cls, &test_rule->cr);
-                ovsrcu_postpone(free_rule, test_rule);
-            }
-            classifier_destroy(&cls);
-            ovsrcu_quiesce();
-
-            expr_matches_destroy(&matches);
-        }
-        expr_destroy(modified);
-    }
-}
-
-#ifndef _WIN32
-static void
-wait_pid(pid_t *pids, int *n)
-{
-    int status;
-    pid_t pid;
-
-    pid = waitpid(-1, &status, 0);
-    if (pid < 0) {
-        ovs_fatal(errno, "waitpid failed");
-    } else if (WIFEXITED(status)) {
-        if (WEXITSTATUS(status)) {
-            exit(WEXITSTATUS(status));
-        }
-    } else if (WIFSIGNALED(status)) {
-        raise(WTERMSIG(status));
-        exit(1);
-    } else {
-        OVS_NOT_REACHED();
-    }
-
-    for (int i = 0; i < *n; i++) {
-        if (pids[i] == pid) {
-            pids[i] = pids[--*n];
-            return;
-        }
-    }
-    ovs_fatal(0, "waitpid returned unknown child");
-}
-#endif
-
-static void
-test_exhaustive(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    int n_terminals = atoi(ctx->argv[1]);
-    struct tree_shape ts[50];
-    int n_tses;
-
-    struct shash symtab;
-    const struct expr_symbol *nvars[4];
-    const struct expr_symbol *svars[4];
-
-    ovs_assert(test_nvars <= ARRAY_SIZE(nvars));
-    ovs_assert(test_svars <= ARRAY_SIZE(svars));
-    ovs_assert(test_nvars + test_svars <= FLOW_N_REGS);
-
-    shash_init(&symtab);
-    for (int i = 0; i < test_nvars; i++) {
-        char *name = xasprintf("n%d", i);
-        nvars[i] = expr_symtab_add_field(&symtab, name, MFF_REG0 + i, NULL,
-                                         false);
-        free(name);
-    }
-    for (int i = 0; i < test_svars; i++) {
-        char *name = xasprintf("s%d", i);
-        svars[i] = expr_symtab_add_string(&symtab, name,
-                                          MFF_REG0 + test_nvars + i, NULL);
-        free(name);
-    }
-
-#ifndef _WIN32
-    pid_t *children = xmalloc(test_parallel * sizeof *children);
-    int n_children = 0;
-#endif
-
-    int n_tested = 0;
-    for (int i = 0; i < 2; i++) {
-        enum expr_type base_type = i ? EXPR_T_OR : EXPR_T_AND;
-
-        for (n_tses = init_tree_shape(ts, n_terminals); n_tses;
-             n_tses = next_tree_shape(ts, n_tses)) {
-            const struct tree_shape *tsp = ts;
-            struct expr *terminals[50];
-            struct expr **terminalp = terminals;
-            struct expr *expr = build_tree_shape(base_type, &tsp, &terminalp);
-            ovs_assert(terminalp == &terminals[n_terminals]);
-
-            if (verbosity > 0) {
-                print_tree_shape(ts, n_tses);
-                printf(": ");
-                struct ds s = DS_EMPTY_INITIALIZER;
-                expr_format(expr, &s);
-                puts(ds_cstr(&s));
-                ds_destroy(&s);
-            }
-
-#ifndef _WIN32
-            if (test_parallel > 1) {
-                pid_t pid = xfork();
-                if (!pid) {
-                    test_tree_shape_exhaustively(expr, &symtab,
-                                                 terminals, n_terminals,
-                                                 nvars, test_nvars, test_bits,
-                                                 svars, test_svars);
-                    expr_destroy(expr);
-                    exit(0);
-                } else {
-                    if (n_children >= test_parallel) {
-                        wait_pid(children, &n_children);
-                    }
-                    children[n_children++] = pid;
-                }
-            } else
-#endif
-            {
-                n_tested += test_tree_shape_exhaustively(
-                    expr, &symtab, terminals, n_terminals,
-                    nvars, test_nvars, test_bits,
-                    svars, test_svars);
-            }
-            expr_destroy(expr);
-        }
-    }
-#ifndef _WIN32
-    while (n_children > 0) {
-        wait_pid(children, &n_children);
-    }
-    free(children);
-#endif
-
-    printf("Tested ");
-    switch (operation) {
-    case OP_CONVERT:
-        printf("converting");
-        break;
-    case OP_SIMPLIFY:
-        printf("simplifying");
-        break;
-    case OP_NORMALIZE:
-        printf("normalizing");
-        break;
-    case OP_FLOW:
-        printf("converting to flows");
-        break;
-    }
-    if (n_tested) {
-        printf(" %d expressions of %d terminals", n_tested, n_terminals);
-    } else {
-        printf(" all %d-terminal expressions", n_terminals);
-    }
-    if (test_nvars || test_svars) {
-        printf(" with");
-        if (test_nvars) {
-            printf(" %d numeric vars (each %d bits) in terms of operators",
-                   test_nvars, test_bits);
-            for (unsigned int relops = test_relops; relops;
-                 relops = zero_rightmost_1bit(relops)) {
-                enum expr_relop r = rightmost_1bit_idx(relops);
-                printf(" %s", expr_relop_to_string(r));
-            }
-        }
-        if (test_nvars && test_svars) {
-            printf (" and");
-        }
-        if (test_svars) {
-            printf(" %d string vars", test_svars);
-        }
-    } else {
-        printf(" in terms of Boolean constants only");
-    }
-    printf(".\n");
-
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-}
-
-static void
-test_expr_to_packets(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    struct shash symtab;
-    struct ds input;
-
-    create_symtab(&symtab);
-
-    ds_init(&input);
-    while (!ds_get_test_line(&input, stdin)) {
-        struct flow uflow;
-        char *error = expr_parse_microflow(ds_cstr(&input), &symtab, NULL,
-                                           NULL, lookup_atoi_cb, NULL, &uflow);
-        if (error) {
-            puts(error);
-            free(error);
-            continue;
-        }
-
-        uint64_t packet_stub[128 / 8];
-        struct dp_packet packet;
-        dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
-        flow_compose(&packet, &uflow, NULL, 64);
-
-        struct ds output = DS_EMPTY_INITIALIZER;
-        const uint8_t *buf = dp_packet_data(&packet);
-        for (int i = 0; i < dp_packet_size(&packet); i++) {
-            uint8_t val = buf[i];
-            ds_put_format(&output, "%02"PRIx8, val);
-        }
-        puts(ds_cstr(&output));
-        ds_destroy(&output);
-
-        dp_packet_uninit(&packet);
-    }
-    ds_destroy(&input);
-
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-}
-
-/* Actions. */
-
-static void
-test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED)
-{
-    struct shash symtab;
-    struct hmap dhcp_opts;
-    struct hmap dhcpv6_opts;
-    struct hmap nd_ra_opts;
-    struct controller_event_options event_opts;
-    struct simap ports;
-    struct ds input;
-    bool ok = true;
-
-    create_symtab(&symtab);
-    create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts, &event_opts);
-
-    /* Initialize group ids. */
-    struct ovn_extend_table group_table;
-    ovn_extend_table_init(&group_table);
-
-    /* Initialize meter ids for QoS. */
-    struct ovn_extend_table meter_table;
-    ovn_extend_table_init(&meter_table);
-
-    simap_init(&ports);
-    simap_put(&ports, "eth0", 5);
-    simap_put(&ports, "eth1", 6);
-    simap_put(&ports, "LOCAL", ofp_to_u16(OFPP_LOCAL));
-
-    ds_init(&input);
-    while (!ds_get_test_line(&input, stdin)) {
-        struct ofpbuf ovnacts;
-        struct expr *prereqs;
-        char *error;
-
-        puts(ds_cstr(&input));
-
-        ofpbuf_init(&ovnacts, 0);
-
-        const struct ovnact_parse_params pp = {
-            .symtab = &symtab,
-            .dhcp_opts = &dhcp_opts,
-            .dhcpv6_opts = &dhcpv6_opts,
-            .nd_ra_opts = &nd_ra_opts,
-            .controller_event_opts = &event_opts,
-            .n_tables = 24,
-            .cur_ltable = 10,
-        };
-        error = ovnacts_parse_string(ds_cstr(&input), &pp, &ovnacts, &prereqs);
-        if (!error) {
-            /* Convert the parsed representation back to a string and print it,
-             * if it's different from the input. */
-            struct ds ovnacts_s = DS_EMPTY_INITIALIZER;
-            ovnacts_format(ovnacts.data, ovnacts.size, &ovnacts_s);
-            if (strcmp(ds_cstr(&input), ds_cstr(&ovnacts_s))) {
-                printf("    formats as %s\n", ds_cstr(&ovnacts_s));
-            }
-
-            /* Encode the actions into OpenFlow and print. */
-            const struct ovnact_encode_params ep = {
-                .lookup_port = lookup_port_cb,
-                .aux = &ports,
-                .is_switch = true,
-                .group_table = &group_table,
-                .meter_table = &meter_table,
-
-                .pipeline = OVNACT_P_INGRESS,
-                .ingress_ptable = 8,
-                .egress_ptable = 40,
-                .output_ptable = 64,
-                .mac_bind_ptable = 65,
-            };
-            struct ofpbuf ofpacts;
-            ofpbuf_init(&ofpacts, 0);
-            ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts);
-            struct ds ofpacts_s = DS_EMPTY_INITIALIZER;
-            struct ofpact_format_params fp = { .s = &ofpacts_s };
-            ofpacts_format(ofpacts.data, ofpacts.size, &fp);
-            printf("    encodes as %s\n", ds_cstr(&ofpacts_s));
-            ds_destroy(&ofpacts_s);
-            ofpbuf_uninit(&ofpacts);
-
-            /* Print prerequisites if any. */
-            if (prereqs) {
-                struct ds prereqs_s = DS_EMPTY_INITIALIZER;
-                expr_format(prereqs, &prereqs_s);
-                printf("    has prereqs %s\n", ds_cstr(&prereqs_s));
-                ds_destroy(&prereqs_s);
-            }
-
-            /* Now re-parse and re-format the string to verify that it's
-             * round-trippable. */
-            struct ofpbuf ovnacts2;
-            struct expr *prereqs2;
-            ofpbuf_init(&ovnacts2, 0);
-            error = ovnacts_parse_string(ds_cstr(&ovnacts_s), &pp, &ovnacts2,
-                                         &prereqs2);
-            if (!error) {
-                struct ds ovnacts2_s = DS_EMPTY_INITIALIZER;
-                ovnacts_format(ovnacts2.data, ovnacts2.size, &ovnacts2_s);
-                if (strcmp(ds_cstr(&ovnacts_s), ds_cstr(&ovnacts2_s))) {
-                    printf("    bad reformat: %s\n", ds_cstr(&ovnacts2_s));
-                    ok = false;
-                }
-                ds_destroy(&ovnacts2_s);
-            } else {
-                printf("    reparse error: %s\n", error);
-                free(error);
-                ok = false;
-            }
-            expr_destroy(prereqs2);
-
-            ovnacts_free(ovnacts2.data, ovnacts2.size);
-            ofpbuf_uninit(&ovnacts2);
-            ds_destroy(&ovnacts_s);
-        } else {
-            printf("    %s\n", error);
-            free(error);
-        }
-
-        expr_destroy(prereqs);
-        ovnacts_free(ovnacts.data, ovnacts.size);
-        ofpbuf_uninit(&ovnacts);
-    }
-    ds_destroy(&input);
-
-    simap_destroy(&ports);
-    expr_symtab_destroy(&symtab);
-    shash_destroy(&symtab);
-    dhcp_opts_destroy(&dhcp_opts);
-    dhcp_opts_destroy(&dhcpv6_opts);
-    nd_ra_opts_destroy(&nd_ra_opts);
-    controller_event_opts_destroy(&event_opts);
-    ovn_extend_table_destroy(&group_table);
-    ovn_extend_table_destroy(&meter_table);
-    exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-static unsigned int
-parse_relops(const char *s)
-{
-    unsigned int relops = 0;
-    struct lexer lexer;
-
-    lexer_init(&lexer, s);
-    lexer_get(&lexer);
-    do {
-        enum expr_relop relop;
-
-        if (expr_relop_from_token(lexer.token.type, &relop)) {
-            relops |= 1u << relop;
-            lexer_get(&lexer);
-        } else {
-            ovs_fatal(0, "%s: relational operator expected at `%.*s'",
-                      s, (int) (lexer.input - lexer.start), lexer.start);
-        }
-        lexer_match(&lexer, LEX_T_COMMA);
-    } while (lexer.token.type != LEX_T_END);
-    lexer_destroy(&lexer);
-
-    return relops;
-}
-
-static void
-usage(void)
-{
-    printf("\
-%s: OVN test utility\n\
-usage: test-ovn %s [OPTIONS] COMMAND [ARG...]\n\
-\n\
-lex\n\
-  Lexically analyzes OVN input from stdin and print them back on stdout.\n\
-\n\
-parse-expr\n\
-annotate-expr\n\
-simplify-expr\n\
-normalize-expr\n\
-expr-to-flows\n\
-  Parses OVN expressions from stdin and prints them back on stdout after\n\
-  differing degrees of analysis.  Available fields are based on packet\n\
-  headers.\n\
-\n\
-expr-to-packets\n\
-  Parses OVN expressions from stdin and prints out matching packets in\n\
-  hexadecimal on stdout.\n\
-\n\
-evaluate-expr MICROFLOW\n\
-  Parses OVN expressions from stdin and evaluates them against the flow\n\
-  specified in MICROFLOW, which must be an expression that constrains\n\
-  the packet, e.g. \"ip4 && tcp.src == 80\" for a TCP packet with source\n\
-  port 80, and prints the results on stdout, either 1 for true or 0 for\n\
-  false.  Use quoted integers, e.g. \"123\", for string fields.\n\
-\n\
-  Example: for MICROFLOW of \"ip4 && tcp.src == 80\", \"eth.type == 0x800\"\n\
-  evaluates to true, \"udp\" evaluates to false, and \"udp || tcp\"\n\
-  evaluates to true.\n\
-\n\
-composition N\n\
-  Prints all the compositions of N on stdout.\n\
-\n\
-tree-shape N\n\
-  Prints all the tree shapes with N terminals on stdout.\n\
-\n\
-exhaustive N\n\
-  Tests that all possible Boolean expressions with N terminals are properly\n\
-  simplified, normalized, and converted to flows.  Available options:\n\
-   Overall options:\n\
-    --operation=OPERATION  Operation to test, one of: convert, simplify,\n\
-        normalize, flow.  Default: flow.  'normalize' includes 'simplify',\n\
-        'flow' includes 'simplify' and 'normalize'.\n\
-    --parallel=N  Number of processes to use in parallel, default 1.\n\
-   Numeric vars:\n\
-    --nvars=N  Number of numeric vars to test, in range 0...4, default 2.\n\
-    --bits=N  Number of bits per variable, in range 1...3, default 3.\n\
-    --relops=OPERATORS   Test only the specified Boolean operators.\n\
-                         OPERATORS may include == != < <= > >=, space or\n\
-                         comma separated.  Default is all operators.\n\
-   String vars:\n\
-    --svars=N  Number of string vars to test, in range 0...4, default 2.\n\
-\n\
-parse-actions\n\
-  Parses OVN actions from stdin and prints the equivalent OpenFlow actions\n\
-  on stdout.\n\
-",
-           program_name, program_name);
-    exit(EXIT_SUCCESS);
-}
-
-static void
-test_ovn_main(int argc, char *argv[])
-{
-    enum {
-        OPT_RELOPS = UCHAR_MAX + 1,
-        OPT_NVARS,
-        OPT_SVARS,
-        OPT_BITS,
-        OPT_OPERATION,
-        OPT_PARALLEL
-    };
-    static const struct option long_options[] = {
-        {"relops", required_argument, NULL, OPT_RELOPS},
-        {"nvars", required_argument, NULL, OPT_NVARS},
-        {"svars", required_argument, NULL, OPT_SVARS},
-        {"bits", required_argument, NULL, OPT_BITS},
-        {"operation", required_argument, NULL, OPT_OPERATION},
-        {"parallel", required_argument, NULL, OPT_PARALLEL},
-        {"more", no_argument, NULL, 'm'},
-        {"help", no_argument, NULL, 'h'},
-        {NULL, 0, NULL, 0},
-    };
-    char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
-
-    set_program_name(argv[0]);
-
-    test_relops = parse_relops("== != < <= > >=");
-    for (;;) {
-        int option_index = 0;
-        int c = getopt_long (argc, argv, short_options, long_options,
-                             &option_index);
-
-        if (c == -1) {
-            break;
-        }
-        switch (c) {
-        case OPT_RELOPS:
-            test_relops = parse_relops(optarg);
-            break;
-
-        case OPT_NVARS:
-            test_nvars = atoi(optarg);
-            if (test_nvars < 0 || test_nvars > 4) {
-                ovs_fatal(0, "number of numeric variables must be "
-                          "between 0 and 4");
-            }
-            break;
-
-        case OPT_SVARS:
-            test_svars = atoi(optarg);
-            if (test_svars < 0 || test_svars > 4) {
-                ovs_fatal(0, "number of string variables must be "
-                          "between 0 and 4");
-            }
-            break;
-
-        case OPT_BITS:
-            test_bits = atoi(optarg);
-            if (test_bits < 1 || test_bits > 3) {
-                ovs_fatal(0, "number of bits must be between 1 and 3");
-            }
-            break;
-
-        case OPT_OPERATION:
-            if (!strcmp(optarg, "convert")) {
-                operation = OP_CONVERT;
-            } else if (!strcmp(optarg, "simplify")) {
-                operation = OP_SIMPLIFY;
-            } else if (!strcmp(optarg, "normalize")) {
-                operation = OP_NORMALIZE;
-            } else if (!strcmp(optarg, "flow")) {
-                operation = OP_FLOW;
-            } else {
-                ovs_fatal(0, "%s: unknown operation", optarg);
-            }
-            break;
-
-        case OPT_PARALLEL:
-            test_parallel = atoi(optarg);
-            break;
-
-        case 'm':
-            verbosity++;
-            break;
-
-        case 'h':
-            usage();
-            /* fall through */
-
-        case '?':
-            exit(1);
-
-        default:
-            abort();
-        }
-    }
-    free(short_options);
-
-    static const struct ovs_cmdl_command commands[] = {
-        /* Lexer. */
-        {"lex", NULL, 0, 0, test_lex, OVS_RO},
-
-        /* Symbol table. */
-        {"dump-symtab", NULL, 0, 0, test_dump_symtab, OVS_RO},
-
-        /* Expressions. */
-        {"parse-expr", NULL, 0, 0, test_parse_expr, OVS_RO},
-        {"annotate-expr", NULL, 0, 0, test_annotate_expr, OVS_RO},
-        {"simplify-expr", NULL, 0, 0, test_simplify_expr, OVS_RO},
-        {"normalize-expr", NULL, 0, 0, test_normalize_expr, OVS_RO},
-        {"expr-to-flows", NULL, 0, 0, test_expr_to_flows, OVS_RO},
-        {"evaluate-expr", NULL, 1, 1, test_evaluate_expr, OVS_RO},
-        {"composition", NULL, 1, 1, test_composition, OVS_RO},
-        {"tree-shape", NULL, 1, 1, test_tree_shape, OVS_RO},
-        {"exhaustive", NULL, 1, 1, test_exhaustive, OVS_RO},
-        {"expr-to-packets", NULL, 0, 0, test_expr_to_packets, OVS_RO},
-
-        /* Actions. */
-        {"parse-actions", NULL, 0, 0, test_parse_actions, OVS_RO},
-
-        {NULL, NULL, 0, 0, NULL, OVS_RO},
-    };
-    struct ovs_cmdl_context ctx;
-    ctx.argc = argc - optind;
-    ctx.argv = argv + optind;
-    ovs_cmdl_run_command(&ctx, commands);
-}
-
-OVSTEST_REGISTER("test-ovn", test_ovn_main);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 4d5e816..e759123 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -19,7 +19,6 @@  m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS])
 m4_include([tests/ovs-macros.at])
 m4_include([tests/ovsdb-macros.at])
 m4_include([tests/ofproto-macros.at])
-m4_include([tests/ovn-macros.at])
 
 m4_include([tests/completion.at])
 m4_include([tests/checkpatch.at])
@@ -74,13 +73,6 @@  m4_include([tests/rstp.at])
 m4_include([tests/vlog.at])
 m4_include([tests/vtep-ctl.at])
 m4_include([tests/auto-attach.at])
-m4_include([tests/ovn.at])
-m4_include([tests/ovn-northd.at])
-m4_include([tests/ovn-nbctl.at])
-m4_include([tests/ovn-sbctl.at])
-m4_include([tests/ovn-controller.at])
-m4_include([tests/ovn-controller-vtep.at])
 m4_include([tests/mcast-snooping.at])
 m4_include([tests/packet-type-aware.at])
 m4_include([tests/nsh.at])
-m4_include([tests/ovn-performance.at])