[ovs-dev,v4] Remove OVN.
diff mbox series

Message ID 20190729193857.8777-1-mmichels@redhat.com
State New
Headers show
Series
  • [ovs-dev,v4] Remove OVN.
Related show

Commit Message

Mark Michelson July 29, 2019, 7:38 p.m. UTC
OVN is separated into its own repo. This commit removes the OVN source,
OVN tests, and OVN documentation. It also removes mentions of OVN from
most documentation. The only place where OVN has been left is in
changelogs/NEWS, since we shouldn't mess with the history of the
project.

Signed-off-by: Mark Michelson <mmichels@redhat.com>
---
v3 -> v4 Fixed 0-day Robot problems with NEWS and documentation
v2 -> v3 Added NEWS entry for removal of OVN
v1 -> v2 Rebase
---
 Documentation/automake.mk                          |    12 -
 Documentation/faq/index.rst                        |     1 -
 Documentation/faq/ovn.rst                          |    90 -
 Documentation/howto/docker.rst                     |   326 -
 Documentation/howto/firewalld.rst                  |   107 -
 Documentation/howto/index.rst                      |     9 -
 Documentation/howto/openstack-containers.rst       |   135 -
 Documentation/index.rst                            |    20 +-
 Documentation/intro/install/fedora.rst             |    12 -
 Documentation/intro/install/index.rst              |     8 -
 Documentation/intro/install/ovn-upgrades.rst       |   115 -
 Documentation/ref/ovs-sim.1.rst                    |   100 -
 Documentation/topics/high-availability.rst         |   440 -
 Documentation/topics/index.rst                     |    18 +-
 Documentation/topics/ovn-news-2.8.rst              |   278 -
 Documentation/topics/role-based-access-control.rst |   101 -
 Documentation/tutorials/index.rst                  |     7 +-
 Documentation/tutorials/ovn-ipsec.rst              |   146 -
 Documentation/tutorials/ovn-openstack.rst          |  1922 ---
 Documentation/tutorials/ovn-rbac.rst               |   134 -
 Documentation/tutorials/ovn-sandbox.rst            |   177 -
 Makefile.am                                        |     1 -
 NEWS                                               |     5 +-
 configure.ac                                       |     3 -
 debian/.gitignore                                  |     5 -
 debian/automake.mk                                 |    22 -
 debian/control                                     |    78 -
 debian/ovn-central.dirs                            |     1 -
 debian/ovn-central.init                            |    60 -
 debian/ovn-central.install                         |     3 -
 debian/ovn-central.manpages                        |     1 -
 debian/ovn-central.postinst                        |    49 -
 debian/ovn-central.postrm                          |    48 -
 debian/ovn-central.template                        |     5 -
 debian/ovn-common.install                          |     7 -
 debian/ovn-common.manpages                         |     8 -
 debian/ovn-common.postinst                         |    24 -
 debian/ovn-common.postrm                           |    23 -
 debian/ovn-controller-vtep.init                    |    54 -
 debian/ovn-controller-vtep.install                 |     1 -
 debian/ovn-controller-vtep.manpages                |     1 -
 debian/ovn-docker.install                          |     2 -
 debian/ovn-host.dirs                               |     1 -
 debian/ovn-host.init                               |    54 -
 debian/ovn-host.install                            |     1 -
 debian/ovn-host.manpages                           |     1 -
 debian/ovn-host.postinst                           |    49 -
 debian/ovn-host.postrm                             |    44 -
 debian/ovn-host.template                           |     5 -
 debian/rules                                       |     6 -
 include/automake.mk                                |     1 -
 include/ovn/actions.h                              |   622 -
 include/ovn/automake.mk                            |     6 -
 include/ovn/expr.h                                 |   518 -
 include/ovn/lex.h                                  |   152 -
 include/ovn/logical-fields.h                       |   130 -
 lib/db-ctl-base.xml                                |    12 +-
 manpages.mk                                        |    28 -
 ovn/.gitignore                                     |     8 -
 ovn/TODO.rst                                       |   147 -
 ovn/automake.mk                                    |    92 -
 ovn/controller-vtep/.gitignore                     |     2 -
 ovn/controller-vtep/automake.mk                    |    14 -
 ovn/controller-vtep/binding.c                      |   274 -
 ovn/controller-vtep/binding.h                      |    27 -
 ovn/controller-vtep/gateway.c                      |   230 -
 ovn/controller-vtep/gateway.h                      |    26 -
 ovn/controller-vtep/ovn-controller-vtep.8.xml      |    80 -
 ovn/controller-vtep/ovn-controller-vtep.c          |   272 -
 ovn/controller-vtep/ovn-controller-vtep.h          |    51 -
 ovn/controller-vtep/vtep.c                         |   600 -
 ovn/controller-vtep/vtep.h                         |    27 -
 ovn/controller/.gitignore                          |     2 -
 ovn/controller/automake.mk                         |    32 -
 ovn/controller/bfd.c                               |   268 -
 ovn/controller/bfd.h                               |    41 -
 ovn/controller/binding.c                           |   764 -
 ovn/controller/binding.h                           |    57 -
 ovn/controller/chassis.c                           |   671 -
 ovn/controller/chassis.h                           |    46 -
 ovn/controller/encaps.c                            |   409 -
 ovn/controller/encaps.h                            |    48 -
 ovn/controller/ha-chassis.c                        |   203 -
 ovn/controller/ha-chassis.h                        |    50 -
 ovn/controller/ip-mcast.c                          |   164 -
 ovn/controller/ip-mcast.h                          |    52 -
 ovn/controller/lflow.c                             |   898 --
 ovn/controller/lflow.h                             |   184 -
 ovn/controller/lport.c                             |   102 -
 ovn/controller/lport.h                             |    52 -
 ovn/controller/ofctrl.c                            |  1393 --
 ovn/controller/ofctrl.h                            |    87 -
 ovn/controller/ovn-controller.8.xml                |   456 -
 ovn/controller/ovn-controller.c                    |  2366 ---
 ovn/controller/ovn-controller.h                    |    85 -
 ovn/controller/patch.c                             |   273 -
 ovn/controller/patch.h                             |    42 -
 ovn/controller/physical.c                          |  1459 --
 ovn/controller/physical.h                          |    74 -
 ovn/controller/pinctrl.c                           |  4343 ------
 ovn/controller/pinctrl.h                           |    51 -
 ovn/lib/.gitignore                                 |     7 -
 ovn/lib/acl-log.c                                  |   105 -
 ovn/lib/acl-log.h                                  |    54 -
 ovn/lib/actions.c                                  |  2902 ----
 ovn/lib/automake.mk                                |    57 -
 ovn/lib/chassis-index.c                            |    67 -
 ovn/lib/chassis-index.h                            |    30 -
 ovn/lib/expr.c                                     |  3450 -----
 ovn/lib/extend-table.c                             |   208 -
 ovn/lib/extend-table.h                             |    82 -
 ovn/lib/inc-proc-eng.c                             |   201 -
 ovn/lib/inc-proc-eng.h                             |   234 -
 ovn/lib/ip-mcast-index.c                           |    40 -
 ovn/lib/ip-mcast-index.h                           |    36 -
 ovn/lib/lex.c                                      |  1023 --
 ovn/lib/libovn.sym.in                              |     4 -
 ovn/lib/logical-fields.c                           |   261 -
 ovn/lib/mcast-group-index.c                        |    43 -
 ovn/lib/mcast-group-index.h                        |    32 -
 ovn/lib/ovn-l7.h                                   |   322 -
 ovn/lib/ovn-nb-idl.ann                             |     9 -
 ovn/lib/ovn-sb-idl.ann                             |    29 -
 ovn/lib/ovn-util.c                                 |   373 -
 ovn/lib/ovn-util.h                                 |    84 -
 ovn/northd/.gitignore                              |     2 -
 ovn/northd/automake.mk                             |    10 -
 ovn/northd/ovn-northd.8.xml                        |  2544 ----
 ovn/northd/ovn-northd.c                            |  9447 ------------
 ovn/ovn-architecture.7.xml                         |  2074 ---
 ovn/ovn-nb.ovsschema                               |   449 -
 ovn/ovn-nb.xml                                     |  2917 ----
 ovn/ovn-sb.ovsschema                               |   404 -
 ovn/ovn-sb.xml                                     |  3638 -----
 ovn/utilities/.gitignore                           |    11 -
 ovn/utilities/automake.mk                          |    57 -
 ovn/utilities/bugtool/automake.mk                  |     9 -
 ovn/utilities/bugtool/ovn-bugtool-nbctl-show       |    19 -
 ovn/utilities/bugtool/ovn-bugtool-sbctl-lflow-list |    19 -
 ovn/utilities/bugtool/ovn-bugtool-sbctl-show       |    19 -
 .../bugtool/plugins/network-status/ovn.xml         |    23 -
 ovn/utilities/ovn-ctl                              |   822 --
 ovn/utilities/ovn-ctl.8.xml                        |   215 -
 ovn/utilities/ovn-detrace.1.in                     |    38 -
 ovn/utilities/ovn-detrace.in                       |   215 -
 ovn/utilities/ovn-docker-overlay-driver.in         |   442 -
 ovn/utilities/ovn-docker-underlay-driver.in        |   677 -
 ovn/utilities/ovn-nbctl.8.xml                      |  1228 --
 ovn/utilities/ovn-nbctl.c                          |  6061 --------
 ovn/utilities/ovn-sbctl.8.in                       |   303 -
 ovn/utilities/ovn-sbctl.c                          |  1541 --
 ovn/utilities/ovn-trace.8.xml                      |   485 -
 ovn/utilities/ovn-trace.c                          |  2373 ---
 ovn/utilities/ovndb-servers.ocf                    |   642 -
 ovsdb/ovsdb-tool.1.in                              |    23 +-
 rhel/automake.mk                                   |    16 +-
 rhel/ovn-fedora.spec.in                            |   432 -
 ...walld_services_ovn-central-firewall-service.xml |     7 -
 ...irewalld_services_ovn-host-firewall-service.xml |     6 -
 ..._lib_systemd_system_ovn-controller-vtep.service |    50 -
 rhel/usr_lib_systemd_system_ovn-controller.service |    34 -
 rhel/usr_lib_systemd_system_ovn-northd.service     |    35 -
 tests/atlocal.in                                   |     4 -
 tests/automake.mk                                  |    46 +-
 tests/ofproto-macros.at                            |     2 +-
 tests/oss-fuzz/automake.mk                         |    10 -
 tests/oss-fuzz/config/expr.dict                    |   120 -
 tests/oss-fuzz/config/expr_parse_target.options    |     3 -
 tests/oss-fuzz/expr_parse_target.c                 |   464 -
 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/ovsdb-cluster-testsuite.at                   |    10 -
 tests/ovsdb-cluster.at                             |   450 -
 tests/system-kmod-testsuite.at                     |     2 -
 tests/system-ovn.at                                |  1663 ---
 tests/system-userspace-testsuite.at                |     2 -
 tests/test-ovn.c                                   |  1584 --
 tests/testsuite.at                                 |     8 -
 tutorial/automake.mk                               |     3 +-
 tutorial/ovn-setup.sh                              |    37 -
 tutorial/ovs-sandbox                               |   261 -
 utilities/bugtool/automake.mk                      |     9 +-
 utilities/ovs-sim.in                               |   237 +-
 xenserver/openvswitch-xen.spec.in                  |     7 -
 190 files changed, 43 insertions(+), 93307 deletions(-)
 delete mode 100644 Documentation/faq/ovn.rst
 delete mode 100644 Documentation/howto/docker.rst
 delete mode 100644 Documentation/howto/firewalld.rst
 delete mode 100644 Documentation/howto/openstack-containers.rst
 delete mode 100644 Documentation/intro/install/ovn-upgrades.rst
 delete mode 100644 Documentation/topics/high-availability.rst
 delete mode 100644 Documentation/topics/ovn-news-2.8.rst
 delete mode 100644 Documentation/topics/role-based-access-control.rst
 delete mode 100644 Documentation/tutorials/ovn-ipsec.rst
 delete mode 100644 Documentation/tutorials/ovn-openstack.rst
 delete mode 100644 Documentation/tutorials/ovn-rbac.rst
 delete mode 100644 Documentation/tutorials/ovn-sandbox.rst
 delete mode 100644 debian/ovn-central.dirs
 delete mode 100755 debian/ovn-central.init
 delete mode 100644 debian/ovn-central.install
 delete mode 100644 debian/ovn-central.manpages
 delete mode 100755 debian/ovn-central.postinst
 delete mode 100755 debian/ovn-central.postrm
 delete mode 100644 debian/ovn-central.template
 delete mode 100644 debian/ovn-common.install
 delete mode 100644 debian/ovn-common.manpages
 delete mode 100644 debian/ovn-common.postinst
 delete mode 100644 debian/ovn-common.postrm
 delete mode 100755 debian/ovn-controller-vtep.init
 delete mode 100644 debian/ovn-controller-vtep.install
 delete mode 100644 debian/ovn-controller-vtep.manpages
 delete mode 100644 debian/ovn-docker.install
 delete mode 100644 debian/ovn-host.dirs
 delete mode 100755 debian/ovn-host.init
 delete mode 100644 debian/ovn-host.install
 delete mode 100644 debian/ovn-host.manpages
 delete mode 100755 debian/ovn-host.postinst
 delete mode 100755 debian/ovn-host.postrm
 delete mode 100644 debian/ovn-host.template
 delete mode 100644 include/ovn/actions.h
 delete mode 100644 include/ovn/automake.mk
 delete mode 100644 include/ovn/expr.h
 delete mode 100644 include/ovn/lex.h
 delete mode 100644 include/ovn/logical-fields.h
 delete mode 100644 ovn/.gitignore
 delete mode 100644 ovn/TODO.rst
 delete mode 100644 ovn/automake.mk
 delete mode 100644 ovn/controller-vtep/.gitignore
 delete mode 100644 ovn/controller-vtep/automake.mk
 delete mode 100644 ovn/controller-vtep/binding.c
 delete mode 100644 ovn/controller-vtep/binding.h
 delete mode 100644 ovn/controller-vtep/gateway.c
 delete mode 100644 ovn/controller-vtep/gateway.h
 delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.8.xml
 delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.c
 delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.h
 delete mode 100644 ovn/controller-vtep/vtep.c
 delete mode 100644 ovn/controller-vtep/vtep.h
 delete mode 100644 ovn/controller/.gitignore
 delete mode 100644 ovn/controller/automake.mk
 delete mode 100644 ovn/controller/bfd.c
 delete mode 100644 ovn/controller/bfd.h
 delete mode 100644 ovn/controller/binding.c
 delete mode 100644 ovn/controller/binding.h
 delete mode 100644 ovn/controller/chassis.c
 delete mode 100644 ovn/controller/chassis.h
 delete mode 100644 ovn/controller/encaps.c
 delete mode 100644 ovn/controller/encaps.h
 delete mode 100644 ovn/controller/ha-chassis.c
 delete mode 100644 ovn/controller/ha-chassis.h
 delete mode 100644 ovn/controller/ip-mcast.c
 delete mode 100644 ovn/controller/ip-mcast.h
 delete mode 100644 ovn/controller/lflow.c
 delete mode 100644 ovn/controller/lflow.h
 delete mode 100644 ovn/controller/lport.c
 delete mode 100644 ovn/controller/lport.h
 delete mode 100644 ovn/controller/ofctrl.c
 delete mode 100644 ovn/controller/ofctrl.h
 delete mode 100644 ovn/controller/ovn-controller.8.xml
 delete mode 100644 ovn/controller/ovn-controller.c
 delete mode 100644 ovn/controller/ovn-controller.h
 delete mode 100644 ovn/controller/patch.c
 delete mode 100644 ovn/controller/patch.h
 delete mode 100644 ovn/controller/physical.c
 delete mode 100644 ovn/controller/physical.h
 delete mode 100644 ovn/controller/pinctrl.c
 delete mode 100644 ovn/controller/pinctrl.h
 delete mode 100644 ovn/lib/.gitignore
 delete mode 100644 ovn/lib/acl-log.c
 delete mode 100644 ovn/lib/acl-log.h
 delete mode 100644 ovn/lib/actions.c
 delete mode 100644 ovn/lib/automake.mk
 delete mode 100644 ovn/lib/chassis-index.c
 delete mode 100644 ovn/lib/chassis-index.h
 delete mode 100644 ovn/lib/expr.c
 delete mode 100644 ovn/lib/extend-table.c
 delete mode 100644 ovn/lib/extend-table.h
 delete mode 100644 ovn/lib/inc-proc-eng.c
 delete mode 100644 ovn/lib/inc-proc-eng.h
 delete mode 100644 ovn/lib/ip-mcast-index.c
 delete mode 100644 ovn/lib/ip-mcast-index.h
 delete mode 100644 ovn/lib/lex.c
 delete mode 100644 ovn/lib/libovn.sym.in
 delete mode 100644 ovn/lib/logical-fields.c
 delete mode 100644 ovn/lib/mcast-group-index.c
 delete mode 100644 ovn/lib/mcast-group-index.h
 delete mode 100644 ovn/lib/ovn-l7.h
 delete mode 100644 ovn/lib/ovn-nb-idl.ann
 delete mode 100644 ovn/lib/ovn-sb-idl.ann
 delete mode 100644 ovn/lib/ovn-util.c
 delete mode 100644 ovn/lib/ovn-util.h
 delete mode 100644 ovn/northd/.gitignore
 delete mode 100644 ovn/northd/automake.mk
 delete mode 100644 ovn/northd/ovn-northd.8.xml
 delete mode 100644 ovn/northd/ovn-northd.c
 delete mode 100644 ovn/ovn-architecture.7.xml
 delete mode 100644 ovn/ovn-nb.ovsschema
 delete mode 100644 ovn/ovn-nb.xml
 delete mode 100644 ovn/ovn-sb.ovsschema
 delete mode 100644 ovn/ovn-sb.xml
 delete mode 100644 ovn/utilities/.gitignore
 delete mode 100644 ovn/utilities/automake.mk
 delete mode 100644 ovn/utilities/bugtool/automake.mk
 delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-nbctl-show
 delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-sbctl-lflow-list
 delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-sbctl-show
 delete mode 100644 ovn/utilities/bugtool/plugins/network-status/ovn.xml
 delete mode 100755 ovn/utilities/ovn-ctl
 delete mode 100644 ovn/utilities/ovn-ctl.8.xml
 delete mode 100644 ovn/utilities/ovn-detrace.1.in
 delete mode 100755 ovn/utilities/ovn-detrace.in
 delete mode 100755 ovn/utilities/ovn-docker-overlay-driver.in
 delete mode 100755 ovn/utilities/ovn-docker-underlay-driver.in
 delete mode 100644 ovn/utilities/ovn-nbctl.8.xml
 delete mode 100644 ovn/utilities/ovn-nbctl.c
 delete mode 100644 ovn/utilities/ovn-sbctl.8.in
 delete mode 100644 ovn/utilities/ovn-sbctl.c
 delete mode 100644 ovn/utilities/ovn-trace.8.xml
 delete mode 100644 ovn/utilities/ovn-trace.c
 delete mode 100755 ovn/utilities/ovndb-servers.ocf
 delete mode 100644 rhel/ovn-fedora.spec.in
 delete mode 100644 rhel/usr_lib_firewalld_services_ovn-central-firewall-service.xml
 delete mode 100644 rhel/usr_lib_firewalld_services_ovn-host-firewall-service.xml
 delete mode 100644 rhel/usr_lib_systemd_system_ovn-controller-vtep.service
 delete mode 100644 rhel/usr_lib_systemd_system_ovn-controller.service
 delete mode 100644 rhel/usr_lib_systemd_system_ovn-northd.service
 delete mode 100644 tests/oss-fuzz/config/expr.dict
 delete mode 100644 tests/oss-fuzz/config/expr_parse_target.options
 delete mode 100644 tests/oss-fuzz/expr_parse_target.c
 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/ovsdb-cluster-testsuite.at
 delete mode 100644 tests/ovsdb-cluster.at
 delete mode 100644 tests/system-ovn.at
 delete mode 100644 tests/test-ovn.c
 delete mode 100755 tutorial/ovn-setup.sh

Comments

Numan Siddique Aug. 6, 2019, 2:33 p.m. UTC | #1
Tested-by: Numan Siddique <nusiddiq@redhat.com>
Acked-by: Numan Siddique <nusiddiq@redhat.com>

Numan


On Tue, Jul 30, 2019 at 1:13 AM Mark Michelson <mmichels@redhat.com> wrote:

> OVN is separated into its own repo. This commit removes the OVN source,
> OVN tests, and OVN documentation. It also removes mentions of OVN from
> most documentation. The only place where OVN has been left is in
> changelogs/NEWS, since we shouldn't mess with the history of the
> project.
>
> Signed-off-by: Mark Michelson <mmichels@redhat.com>
> ---
> v3 -> v4 Fixed 0-day Robot problems with NEWS and documentation
> v2 -> v3 Added NEWS entry for removal of OVN
> v1 -> v2 Rebase
> ---
>  Documentation/automake.mk                          |    12 -
>  Documentation/faq/index.rst                        |     1 -
>  Documentation/faq/ovn.rst                          |    90 -
>  Documentation/howto/docker.rst                     |   326 -
>  Documentation/howto/firewalld.rst                  |   107 -
>  Documentation/howto/index.rst                      |     9 -
>  Documentation/howto/openstack-containers.rst       |   135 -
>  Documentation/index.rst                            |    20 +-
>  Documentation/intro/install/fedora.rst             |    12 -
>  Documentation/intro/install/index.rst              |     8 -
>  Documentation/intro/install/ovn-upgrades.rst       |   115 -
>  Documentation/ref/ovs-sim.1.rst                    |   100 -
>  Documentation/topics/high-availability.rst         |   440 -
>  Documentation/topics/index.rst                     |    18 +-
>  Documentation/topics/ovn-news-2.8.rst              |   278 -
>  Documentation/topics/role-based-access-control.rst |   101 -
>  Documentation/tutorials/index.rst                  |     7 +-
>  Documentation/tutorials/ovn-ipsec.rst              |   146 -
>  Documentation/tutorials/ovn-openstack.rst          |  1922 ---
>  Documentation/tutorials/ovn-rbac.rst               |   134 -
>  Documentation/tutorials/ovn-sandbox.rst            |   177 -
>  Makefile.am                                        |     1 -
>  NEWS                                               |     5 +-
>  configure.ac                                       |     3 -
>  debian/.gitignore                                  |     5 -
>  debian/automake.mk                                 |    22 -
>  debian/control                                     |    78 -
>  debian/ovn-central.dirs                            |     1 -
>  debian/ovn-central.init                            |    60 -
>  debian/ovn-central.install                         |     3 -
>  debian/ovn-central.manpages                        |     1 -
>  debian/ovn-central.postinst                        |    49 -
>  debian/ovn-central.postrm                          |    48 -
>  debian/ovn-central.template                        |     5 -
>  debian/ovn-common.install                          |     7 -
>  debian/ovn-common.manpages                         |     8 -
>  debian/ovn-common.postinst                         |    24 -
>  debian/ovn-common.postrm                           |    23 -
>  debian/ovn-controller-vtep.init                    |    54 -
>  debian/ovn-controller-vtep.install                 |     1 -
>  debian/ovn-controller-vtep.manpages                |     1 -
>  debian/ovn-docker.install                          |     2 -
>  debian/ovn-host.dirs                               |     1 -
>  debian/ovn-host.init                               |    54 -
>  debian/ovn-host.install                            |     1 -
>  debian/ovn-host.manpages                           |     1 -
>  debian/ovn-host.postinst                           |    49 -
>  debian/ovn-host.postrm                             |    44 -
>  debian/ovn-host.template                           |     5 -
>  debian/rules                                       |     6 -
>  include/automake.mk                                |     1 -
>  include/ovn/actions.h                              |   622 -
>  include/ovn/automake.mk                            |     6 -
>  include/ovn/expr.h                                 |   518 -
>  include/ovn/lex.h                                  |   152 -
>  include/ovn/logical-fields.h                       |   130 -
>  lib/db-ctl-base.xml                                |    12 +-
>  manpages.mk                                        |    28 -
>  ovn/.gitignore                                     |     8 -
>  ovn/TODO.rst                                       |   147 -
>  ovn/automake.mk                                    |    92 -
>  ovn/controller-vtep/.gitignore                     |     2 -
>  ovn/controller-vtep/automake.mk                    |    14 -
>  ovn/controller-vtep/binding.c                      |   274 -
>  ovn/controller-vtep/binding.h                      |    27 -
>  ovn/controller-vtep/gateway.c                      |   230 -
>  ovn/controller-vtep/gateway.h                      |    26 -
>  ovn/controller-vtep/ovn-controller-vtep.8.xml      |    80 -
>  ovn/controller-vtep/ovn-controller-vtep.c          |   272 -
>  ovn/controller-vtep/ovn-controller-vtep.h          |    51 -
>  ovn/controller-vtep/vtep.c                         |   600 -
>  ovn/controller-vtep/vtep.h                         |    27 -
>  ovn/controller/.gitignore                          |     2 -
>  ovn/controller/automake.mk                         |    32 -
>  ovn/controller/bfd.c                               |   268 -
>  ovn/controller/bfd.h                               |    41 -
>  ovn/controller/binding.c                           |   764 -
>  ovn/controller/binding.h                           |    57 -
>  ovn/controller/chassis.c                           |   671 -
>  ovn/controller/chassis.h                           |    46 -
>  ovn/controller/encaps.c                            |   409 -
>  ovn/controller/encaps.h                            |    48 -
>  ovn/controller/ha-chassis.c                        |   203 -
>  ovn/controller/ha-chassis.h                        |    50 -
>  ovn/controller/ip-mcast.c                          |   164 -
>  ovn/controller/ip-mcast.h                          |    52 -
>  ovn/controller/lflow.c                             |   898 --
>  ovn/controller/lflow.h                             |   184 -
>  ovn/controller/lport.c                             |   102 -
>  ovn/controller/lport.h                             |    52 -
>  ovn/controller/ofctrl.c                            |  1393 --
>  ovn/controller/ofctrl.h                            |    87 -
>  ovn/controller/ovn-controller.8.xml                |   456 -
>  ovn/controller/ovn-controller.c                    |  2366 ---
>  ovn/controller/ovn-controller.h                    |    85 -
>  ovn/controller/patch.c                             |   273 -
>  ovn/controller/patch.h                             |    42 -
>  ovn/controller/physical.c                          |  1459 --
>  ovn/controller/physical.h                          |    74 -
>  ovn/controller/pinctrl.c                           |  4343 ------
>  ovn/controller/pinctrl.h                           |    51 -
>  ovn/lib/.gitignore                                 |     7 -
>  ovn/lib/acl-log.c                                  |   105 -
>  ovn/lib/acl-log.h                                  |    54 -
>  ovn/lib/actions.c                                  |  2902 ----
>  ovn/lib/automake.mk                                |    57 -
>  ovn/lib/chassis-index.c                            |    67 -
>  ovn/lib/chassis-index.h                            |    30 -
>  ovn/lib/expr.c                                     |  3450 -----
>  ovn/lib/extend-table.c                             |   208 -
>  ovn/lib/extend-table.h                             |    82 -
>  ovn/lib/inc-proc-eng.c                             |   201 -
>  ovn/lib/inc-proc-eng.h                             |   234 -
>  ovn/lib/ip-mcast-index.c                           |    40 -
>  ovn/lib/ip-mcast-index.h                           |    36 -
>  ovn/lib/lex.c                                      |  1023 --
>  ovn/lib/libovn.sym.in                              |     4 -
>  ovn/lib/logical-fields.c                           |   261 -
>  ovn/lib/mcast-group-index.c                        |    43 -
>  ovn/lib/mcast-group-index.h                        |    32 -
>  ovn/lib/ovn-l7.h                                   |   322 -
>  ovn/lib/ovn-nb-idl.ann                             |     9 -
>  ovn/lib/ovn-sb-idl.ann                             |    29 -
>  ovn/lib/ovn-util.c                                 |   373 -
>  ovn/lib/ovn-util.h                                 |    84 -
>  ovn/northd/.gitignore                              |     2 -
>  ovn/northd/automake.mk                             |    10 -
>  ovn/northd/ovn-northd.8.xml                        |  2544 ----
>  ovn/northd/ovn-northd.c                            |  9447 ------------
>  ovn/ovn-architecture.7.xml                         |  2074 ---
>  ovn/ovn-nb.ovsschema                               |   449 -
>  ovn/ovn-nb.xml                                     |  2917 ----
>  ovn/ovn-sb.ovsschema                               |   404 -
>  ovn/ovn-sb.xml                                     |  3638 -----
>  ovn/utilities/.gitignore                           |    11 -
>  ovn/utilities/automake.mk                          |    57 -
>  ovn/utilities/bugtool/automake.mk                  |     9 -
>  ovn/utilities/bugtool/ovn-bugtool-nbctl-show       |    19 -
>  ovn/utilities/bugtool/ovn-bugtool-sbctl-lflow-list |    19 -
>  ovn/utilities/bugtool/ovn-bugtool-sbctl-show       |    19 -
>  .../bugtool/plugins/network-status/ovn.xml         |    23 -
>  ovn/utilities/ovn-ctl                              |   822 --
>  ovn/utilities/ovn-ctl.8.xml                        |   215 -
>  ovn/utilities/ovn-detrace.1.in                     |    38 -
>  ovn/utilities/ovn-detrace.in                       |   215 -
>  ovn/utilities/ovn-docker-overlay-driver.in         |   442 -
>  ovn/utilities/ovn-docker-underlay-driver.in        |   677 -
>  ovn/utilities/ovn-nbctl.8.xml                      |  1228 --
>  ovn/utilities/ovn-nbctl.c                          |  6061 --------
>  ovn/utilities/ovn-sbctl.8.in                       |   303 -
>  ovn/utilities/ovn-sbctl.c                          |  1541 --
>  ovn/utilities/ovn-trace.8.xml                      |   485 -
>  ovn/utilities/ovn-trace.c                          |  2373 ---
>  ovn/utilities/ovndb-servers.ocf                    |   642 -
>  ovsdb/ovsdb-tool.1.in                              |    23 +-
>  rhel/automake.mk                                   |    16 +-
>  rhel/ovn-fedora.spec.in                            |   432 -
>  ...walld_services_ovn-central-firewall-service.xml |     7 -
>  ...irewalld_services_ovn-host-firewall-service.xml |     6 -
>  ..._lib_systemd_system_ovn-controller-vtep.service |    50 -
>  rhel/usr_lib_systemd_system_ovn-controller.service |    34 -
>  rhel/usr_lib_systemd_system_ovn-northd.service     |    35 -
>  tests/atlocal.in                                   |     4 -
>  tests/automake.mk                                  |    46 +-
>  tests/ofproto-macros.at                            |     2 +-
>  tests/oss-fuzz/automake.mk                         |    10 -
>  tests/oss-fuzz/config/expr.dict                    |   120 -
>  tests/oss-fuzz/config/expr_parse_target.options    |     3 -
>  tests/oss-fuzz/expr_parse_target.c                 |   464 -
>  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/ovsdb-cluster-testsuite.at                   |    10 -
>  tests/ovsdb-cluster.at                             |   450 -
>  tests/system-kmod-testsuite.at                     |     2 -
>  tests/system-ovn.at                                |  1663 ---
>  tests/system-userspace-testsuite.at                |     2 -
>  tests/test-ovn.c                                   |  1584 --
>  tests/testsuite.at                                 |     8 -
>  tutorial/automake.mk                               |     3 +-
>  tutorial/ovn-setup.sh                              |    37 -
>  tutorial/ovs-sandbox                               |   261 -
>  utilities/bugtool/automake.mk                      |     9 +-
>  utilities/ovs-sim.in                               |   237 +-
>  xenserver/openvswitch-xen.spec.in                  |     7 -
>  190 files changed, 43 insertions(+), 93307 deletions(-)
>  delete mode 100644 Documentation/faq/ovn.rst
>  delete mode 100644 Documentation/howto/docker.rst
>  delete mode 100644 Documentation/howto/firewalld.rst
>  delete mode 100644 Documentation/howto/openstack-containers.rst
>  delete mode 100644 Documentation/intro/install/ovn-upgrades.rst
>  delete mode 100644 Documentation/topics/high-availability.rst
>  delete mode 100644 Documentation/topics/ovn-news-2.8.rst
>  delete mode 100644 Documentation/topics/role-based-access-control.rst
>  delete mode 100644 Documentation/tutorials/ovn-ipsec.rst
>  delete mode 100644 Documentation/tutorials/ovn-openstack.rst
>  delete mode 100644 Documentation/tutorials/ovn-rbac.rst
>  delete mode 100644 Documentation/tutorials/ovn-sandbox.rst
>  delete mode 100644 debian/ovn-central.dirs
>  delete mode 100755 debian/ovn-central.init
>  delete mode 100644 debian/ovn-central.install
>  delete mode 100644 debian/ovn-central.manpages
>  delete mode 100755 debian/ovn-central.postinst
>  delete mode 100755 debian/ovn-central.postrm
>  delete mode 100644 debian/ovn-central.template
>  delete mode 100644 debian/ovn-common.install
>  delete mode 100644 debian/ovn-common.manpages
>  delete mode 100644 debian/ovn-common.postinst
>  delete mode 100644 debian/ovn-common.postrm
>  delete mode 100755 debian/ovn-controller-vtep.init
>  delete mode 100644 debian/ovn-controller-vtep.install
>  delete mode 100644 debian/ovn-controller-vtep.manpages
>  delete mode 100644 debian/ovn-docker.install
>  delete mode 100644 debian/ovn-host.dirs
>  delete mode 100755 debian/ovn-host.init
>  delete mode 100644 debian/ovn-host.install
>  delete mode 100644 debian/ovn-host.manpages
>  delete mode 100755 debian/ovn-host.postinst
>  delete mode 100755 debian/ovn-host.postrm
>  delete mode 100644 debian/ovn-host.template
>  delete mode 100644 include/ovn/actions.h
>  delete mode 100644 include/ovn/automake.mk
>  delete mode 100644 include/ovn/expr.h
>  delete mode 100644 include/ovn/lex.h
>  delete mode 100644 include/ovn/logical-fields.h
>  delete mode 100644 ovn/.gitignore
>  delete mode 100644 ovn/TODO.rst
>  delete mode 100644 ovn/automake.mk
>  delete mode 100644 ovn/controller-vtep/.gitignore
>  delete mode 100644 ovn/controller-vtep/automake.mk
>  delete mode 100644 ovn/controller-vtep/binding.c
>  delete mode 100644 ovn/controller-vtep/binding.h
>  delete mode 100644 ovn/controller-vtep/gateway.c
>  delete mode 100644 ovn/controller-vtep/gateway.h
>  delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.8.xml
>  delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.c
>  delete mode 100644 ovn/controller-vtep/ovn-controller-vtep.h
>  delete mode 100644 ovn/controller-vtep/vtep.c
>  delete mode 100644 ovn/controller-vtep/vtep.h
>  delete mode 100644 ovn/controller/.gitignore
>  delete mode 100644 ovn/controller/automake.mk
>  delete mode 100644 ovn/controller/bfd.c
>  delete mode 100644 ovn/controller/bfd.h
>  delete mode 100644 ovn/controller/binding.c
>  delete mode 100644 ovn/controller/binding.h
>  delete mode 100644 ovn/controller/chassis.c
>  delete mode 100644 ovn/controller/chassis.h
>  delete mode 100644 ovn/controller/encaps.c
>  delete mode 100644 ovn/controller/encaps.h
>  delete mode 100644 ovn/controller/ha-chassis.c
>  delete mode 100644 ovn/controller/ha-chassis.h
>  delete mode 100644 ovn/controller/ip-mcast.c
>  delete mode 100644 ovn/controller/ip-mcast.h
>  delete mode 100644 ovn/controller/lflow.c
>  delete mode 100644 ovn/controller/lflow.h
>  delete mode 100644 ovn/controller/lport.c
>  delete mode 100644 ovn/controller/lport.h
>  delete mode 100644 ovn/controller/ofctrl.c
>  delete mode 100644 ovn/controller/ofctrl.h
>  delete mode 100644 ovn/controller/ovn-controller.8.xml
>  delete mode 100644 ovn/controller/ovn-controller.c
>  delete mode 100644 ovn/controller/ovn-controller.h
>  delete mode 100644 ovn/controller/patch.c
>  delete mode 100644 ovn/controller/patch.h
>  delete mode 100644 ovn/controller/physical.c
>  delete mode 100644 ovn/controller/physical.h
>  delete mode 100644 ovn/controller/pinctrl.c
>  delete mode 100644 ovn/controller/pinctrl.h
>  delete mode 100644 ovn/lib/.gitignore
>  delete mode 100644 ovn/lib/acl-log.c
>  delete mode 100644 ovn/lib/acl-log.h
>  delete mode 100644 ovn/lib/actions.c
>  delete mode 100644 ovn/lib/automake.mk
>  delete mode 100644 ovn/lib/chassis-index.c
>  delete mode 100644 ovn/lib/chassis-index.h
>  delete mode 100644 ovn/lib/expr.c
>  delete mode 100644 ovn/lib/extend-table.c
>  delete mode 100644 ovn/lib/extend-table.h
>  delete mode 100644 ovn/lib/inc-proc-eng.c
>  delete mode 100644 ovn/lib/inc-proc-eng.h
>  delete mode 100644 ovn/lib/ip-mcast-index.c
>  delete mode 100644 ovn/lib/ip-mcast-index.h
>  delete mode 100644 ovn/lib/lex.c
>  delete mode 100644 ovn/lib/libovn.sym.in
>  delete mode 100644 ovn/lib/logical-fields.c
>  delete mode 100644 ovn/lib/mcast-group-index.c
>  delete mode 100644 ovn/lib/mcast-group-index.h
>  delete mode 100644 ovn/lib/ovn-l7.h
>  delete mode 100644 ovn/lib/ovn-nb-idl.ann
>  delete mode 100644 ovn/lib/ovn-sb-idl.ann
>  delete mode 100644 ovn/lib/ovn-util.c
>  delete mode 100644 ovn/lib/ovn-util.h
>  delete mode 100644 ovn/northd/.gitignore
>  delete mode 100644 ovn/northd/automake.mk
>  delete mode 100644 ovn/northd/ovn-northd.8.xml
>  delete mode 100644 ovn/northd/ovn-northd.c
>  delete mode 100644 ovn/ovn-architecture.7.xml
>  delete mode 100644 ovn/ovn-nb.ovsschema
>  delete mode 100644 ovn/ovn-nb.xml
>  delete mode 100644 ovn/ovn-sb.ovsschema
>  delete mode 100644 ovn/ovn-sb.xml
>  delete mode 100644 ovn/utilities/.gitignore
>  delete mode 100644 ovn/utilities/automake.mk
>  delete mode 100644 ovn/utilities/bugtool/automake.mk
>  delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-nbctl-show
>  delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-sbctl-lflow-list
>  delete mode 100644 ovn/utilities/bugtool/ovn-bugtool-sbctl-show
>  delete mode 100644 ovn/utilities/bugtool/plugins/network-status/ovn.xml
>  delete mode 100755 ovn/utilities/ovn-ctl
>  delete mode 100644 ovn/utilities/ovn-ctl.8.xml
>  delete mode 100644 ovn/utilities/ovn-detrace.1.in
>  delete mode 100755 ovn/utilities/ovn-detrace.in
>  delete mode 100755 ovn/utilities/ovn-docker-overlay-driver.in
>  delete mode 100755 ovn/utilities/ovn-docker-underlay-driver.in
>  delete mode 100644 ovn/utilities/ovn-nbctl.8.xml
>  delete mode 100644 ovn/utilities/ovn-nbctl.c
>  delete mode 100644 ovn/utilities/ovn-sbctl.8.in
>  delete mode 100644 ovn/utilities/ovn-sbctl.c
>  delete mode 100644 ovn/utilities/ovn-trace.8.xml
>  delete mode 100644 ovn/utilities/ovn-trace.c
>  delete mode 100755 ovn/utilities/ovndb-servers.ocf
>  delete mode 100644 rhel/ovn-fedora.spec.in
>  delete mode 100644
> rhel/usr_lib_firewalld_services_ovn-central-firewall-service.xml
>  delete mode 100644
> rhel/usr_lib_firewalld_services_ovn-host-firewall-service.xml
>  delete mode 100644 rhel/usr_lib_systemd_system_ovn-controller-vtep.service
>  delete mode 100644 rhel/usr_lib_systemd_system_ovn-controller.service
>  delete mode 100644 rhel/usr_lib_systemd_system_ovn-northd.service
>  delete mode 100644 tests/oss-fuzz/config/expr.dict
>  delete mode 100644 tests/oss-fuzz/config/expr_parse_target.options
>  delete mode 100644 tests/oss-fuzz/expr_parse_target.c
>  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/ovsdb-cluster-testsuite.at
>  delete mode 100644 tests/ovsdb-cluster.at
>  delete mode 100644 tests/system-ovn.at
>  delete mode 100644 tests/test-ovn.c
>  delete mode 100755 tutorial/ovn-setup.sh
>
> diff --git a/Documentation/automake.mk b/Documentation/automake.mk
> index 2a3214a3c..cd68f3b15 100644
> --- a/Documentation/automake.mk
> +++ b/Documentation/automake.mk
> @@ -18,7 +18,6 @@ DOC_SOURCE = \
>         Documentation/intro/install/fedora.rst \
>         Documentation/intro/install/general.rst \
>         Documentation/intro/install/netbsd.rst \
> -       Documentation/intro/install/ovn-upgrades.rst \
>         Documentation/intro/install/rhel.rst \
>         Documentation/intro/install/userspace.rst \
>         Documentation/intro/install/windows.rst \
> @@ -26,12 +25,8 @@ DOC_SOURCE = \
>         Documentation/tutorials/index.rst \
>         Documentation/tutorials/faucet.rst \
>         Documentation/tutorials/ovs-advanced.rst \
> -       Documentation/tutorials/ovn-openstack.rst \
> -       Documentation/tutorials/ovn-sandbox.rst \
>         Documentation/tutorials/ovs-conntrack.rst \
>         Documentation/tutorials/ipsec.rst \
> -       Documentation/tutorials/ovn-ipsec.rst \
> -       Documentation/tutorials/ovn-rbac.rst \
>         Documentation/topics/index.rst \
>         Documentation/topics/bonding.rst \
>         Documentation/topics/idl-compound-indexes.rst \
> @@ -54,28 +49,22 @@ DOC_SOURCE = \
>         Documentation/topics/fuzzing/ovs-fuzzers.rst \
>         Documentation/topics/fuzzing/security-analysis-of-ovs-fuzzers.rst \
>         Documentation/topics/testing.rst \
> -       Documentation/topics/high-availability.rst \
>         Documentation/topics/integration.rst \
>         Documentation/topics/language-bindings.rst \
>         Documentation/topics/networking-namespaces.rst \
>         Documentation/topics/openflow.rst \
> -       Documentation/topics/ovn-news-2.8.rst \
>         Documentation/topics/ovsdb-replication.rst \
>         Documentation/topics/porting.rst \
> -       Documentation/topics/role-based-access-control.rst \
>         Documentation/topics/tracing.rst \
>         Documentation/topics/windows.rst \
>         Documentation/howto/index.rst \
> -       Documentation/howto/docker.rst \
>         Documentation/howto/dpdk.rst \
> -       Documentation/howto/firewalld.rst \
>         Documentation/howto/ipsec.rst \
>         Documentation/howto/kvm.rst \
>         Documentation/howto/libvirt.rst \
>         Documentation/howto/selinux.rst \
>         Documentation/howto/ssl.rst \
>         Documentation/howto/lisp.rst \
> -       Documentation/howto/openstack-containers.rst \
>         Documentation/howto/qos.png \
>         Documentation/howto/qos.rst \
>         Documentation/howto/sflow.png \
> @@ -94,7 +83,6 @@ DOC_SOURCE = \
>         Documentation/faq/general.rst \
>         Documentation/faq/issues.rst \
>         Documentation/faq/openflow.rst \
> -       Documentation/faq/ovn.rst \
>         Documentation/faq/qos.rst \
>         Documentation/faq/releases.rst \
>         Documentation/faq/terminology.rst \
> diff --git a/Documentation/faq/index.rst b/Documentation/faq/index.rst
> index ad3cc2b6f..334b828b2 100644
> --- a/Documentation/faq/index.rst
> +++ b/Documentation/faq/index.rst
> @@ -41,4 +41,3 @@ Open vSwitch FAQ
>     terminology
>     vlan
>     vxlan
> -   ovn
> diff --git a/Documentation/faq/ovn.rst b/Documentation/faq/ovn.rst
> deleted file mode 100644
> index 4d96b4aa5..000000000
> --- a/Documentation/faq/ovn.rst
> +++ /dev/null
> @@ -1,90 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -===
> -OVN
> -===
> -
> -Q: Why does OVN use STT and Geneve instead of VLANs or VXLAN (or GRE)?
> -
> -    A: OVN implements a fairly sophisticated packet processing pipeline in
> -    "logical datapaths" that can implement switching or routing
> functionality.
> -    A logical datapath has an ingress pipeline and an egress pipeline,
> and each
> -    of these pipelines can include logic based on packet fields as well as
> -    packet metadata such as the logical ingress and egress ports (the
> latter
> -    only in the egress pipeline).
> -
> -    The processing for a logical datapath can be split across
> hypervisors.  In
> -    particular, when a logical ingress pipeline executes an "output"
> action,
> -    OVN passes the packet to the egress pipeline on the hypervisor (or,
> in the
> -    case of output to a logical multicast group, hypervisors) on which the
> -    logical egress port is located.  If this hypervisor is not the same
> as the
> -    ingress hypervisor, then the packet has to be transmitted across a
> physical
> -    network.
> -
> -    This situation is where tunneling comes in.  To send the packet to
> another
> -    hypervisor, OVN encapsulates it with a tunnel protocol and sends the
> -    encapsulated packet across the physical network.  When the remote
> -    hypervisor receives the tunnel packet, it decapsulates it and passes
> it
> -    through the logical egress pipeline.  To do so, it also needs the
> metadata,
> -    that is, the logical ingress and egress ports.
> -
> -    Thus, to implement OVN logical packet processing, at least the
> following
> -    metadata must pass across the physical network:
> -
> -    * Logical datapath ID, a 24-bit identifier.  In Geneve, OVN uses the
> VNI to
> -      hold the logical datapath ID; in STT, OVN uses 24 bits of STT's
> 64-bit
> -      context ID.
> -
> -    * Logical ingress port, a 15-bit identifier.  In Geneve, OVN uses an
> option
> -      to hold the logical ingress port; in STT, 15 bits of the context ID.
> -
> -    * Logical egress port, a 16-bit identifier.  In Geneve, OVN uses an
> option
> -      to hold the logical egress port; in STT, 16 bits of the context ID.
> -
> -    See ``ovn-architecture(7)``, under "Tunnel Encapsulations", for
> details.
> -
> -    Together, these metadata require 24 + 15 + 16 = 55 bits.  GRE
> provides 32
> -    bits, VXLAN provides 24, and VLAN only provides 12.  Most notably, if
> -    logical egress pipelines do not match on the logical ingress port,
> thereby
> -    restricting the class of ACLs available to users, then this
> eliminates 15
> -    bits, bringing the requirement down to 40 bits.  At this point, one
> can
> -    choose to limit the size of the OVN logical network in various ways,
> e.g.:
> -
> -    * 16 bits of logical datapaths + 16 bits of logical egress ports.
> This
> -      combination fits within a 32-bit GRE tunnel key.
> -
> -    * 12 bits of logical datapaths + 12 bits of logical egress ports.
> This
> -      combination fits within a 24-bit VXLAN VNI.
> -
> -    * It's difficult to identify an acceptable compromise for a VLAN-based
> -      deployment.
> -
> -    These compromises wouldn't suit every site, since some deployments
> -    may need to allocate more bits to the datapath or egress port
> -    identifiers.
> -
> -    As a side note, OVN does support VXLAN for use with ASIC-based top of
> rack
> -    switches, using ``ovn-controller-vtep(8)`` and the OVSDB VTEP schema
> -    described in ``vtep(5)``, but this limits the features available from
> OVN
> -    to the subset available from the VTEP schema.
> diff --git a/Documentation/howto/docker.rst
> b/Documentation/howto/docker.rst
> deleted file mode 100644
> index a68b02fdb..000000000
> --- a/Documentation/howto/docker.rst
> +++ /dev/null
> @@ -1,326 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -===================================
> -Open Virtual Networking With Docker
> -===================================
> -
> -This document describes how to use Open Virtual Networking with Docker
> 1.9.0
> -or later.
> -
> -.. important::
> -
> -  Requires Docker version 1.9.0 or later. Only Docker 1.9.0+ comes with
> support
> -  for multi-host networking. Consult www.docker.com for instructions on
> how to
> -  install Docker.
> -
> -.. note::
> -
> -  You must build and install Open vSwitch before proceeding with the below
> -  guide. Refer to :doc:`/intro/install/index` for more information.
> -
> -Setup
> ------
> -
> -For multi-host networking with OVN and Docker, Docker has to be started
> with a
> -distributed key-value store. For example, if you decide to use consul as
> your
> -distributed key-value store and your host IP address is ``$HOST_IP``,
> start
> -your Docker daemon with::
> -
> -    $ docker daemon --cluster-store=consul://127.0.0.1:8500 \
> -        --cluster-advertise=$HOST_IP:0
> -
> -OVN provides network virtualization to containers. OVN's integration with
> -Docker currently works in two modes - the "underlay" mode or the "overlay"
> -mode.
> -
> -In the "underlay" mode, OVN requires a OpenStack setup to provide
> container
> -networking. In this mode, one can create logical networks and can have
> -containers running inside VMs, standalone VMs (without having any
> containers
> -running inside them) and physical machines connected to the same logical
> -network. This is a multi-tenant, multi-host solution.
> -
> -In the "overlay" mode, OVN can create a logical network amongst containers
> -running on multiple hosts. This is a single-tenant (extendable to
> multi-tenants
> -depending on the security characteristics of the workloads), multi-host
> -solution. In this mode, you do not need a pre-created OpenStack setup.
> -
> -For both the modes to work, a user has to install and start Open vSwitch
> in
> -each VM/host that they plan to run their containers on.
> -
> -.. _docker-overlay:
> -
> -The "overlay" mode
> -------------------
> -
> -.. note::
> -
> -  OVN in "overlay" mode needs a minimum Open vSwitch version of 2.5.
> -
> -1. Start the central components.
> -
> -  OVN architecture has a central component which stores your networking
> intent
> -  in a database. On one of your machines, with an IP Address of
> -  ``$CENTRAL_IP``, where you have installed and started Open vSwitch, you
> will
> -  need to start some central components.
> -
> -  Start ovn-northd daemon. This daemon translates networking intent from
> Docker
> -  stored in the OVN\_Northbound database to logical flows in
> ``OVN_Southbound``
> -  database. For example::
> -
> -      $ /usr/share/openvswitch/scripts/ovn-ctl start_northd
> -
> -  With Open vSwitch version of 2.7 or greater, you need to run the
> following
> -  additional commands (Please read the manpages of ovn-nb for more control
> -  on the types of connection allowed.) ::
> -
> -      $ ovn-nbctl set-connection ptcp:6641
> -      $ ovn-sbctl set-connection ptcp:6642
> -
> -2. One time setup
> -
> -   On each host, where you plan to spawn your containers, you will need
> to run
> -   the below command once. You may need to run it again if your OVS
> database
> -   gets cleared. It is harmless to run it again in any case::
> -
> -       $ ovs-vsctl set Open_vSwitch . \
> -           external_ids:ovn-remote="tcp:$CENTRAL_IP:6642" \
> -           external_ids:ovn-nb="tcp:$CENTRAL_IP:6641" \
> -           external_ids:ovn-encap-ip=$LOCAL_IP \
> -           external_ids:ovn-encap-type="$ENCAP_TYPE"
> -
> -   where:
> -
> -   ``$LOCAL_IP``
> -     is the IP address via which other hosts can reach this host.  This
> acts as
> -     your local tunnel endpoint.
> -
> -   ``$ENCAP_TYPE``
> -     is the type of tunnel that you would like to use for overlay
> networking.
> -     The options are ``geneve`` or ``stt``. Your kernel must have support
> for
> -     your chosen ``$ENCAP_TYPE``. Both ``geneve`` and ``stt`` are part of
> the
> -     Open vSwitch kernel module that is compiled from this repo. If you
> use the
> -     Open vSwitch kernel module from upstream Linux, you will need a
> minimum
> -     kernel version of 3.18 for ``geneve``. There is no ``stt`` support in
> -     upstream Linux. You can verify whether you have the support in your
> kernel
> -     as follows::
> -
> -         $ lsmod | grep $ENCAP_TYPE
> -
> -   In addition, each Open vSwitch instance in an OVN deployment needs a
> unique,
> -   persistent identifier, called the ``system-id``.  If you install OVS
> from
> -   distribution packaging for Open vSwitch (e.g. .deb or .rpm packages),
> or if
> -   you use the ovs-ctl utility included with Open vSwitch, it
> automatically
> -   configures a system-id.  If you start Open vSwitch manually, you
> should set
> -   one up yourself. For example::
> -
> -       $ id_file=/etc/openvswitch/system-id.conf
> -       $ test -e $id_file || uuidgen > $id_file
> -       $ ovs-vsctl set Open_vSwitch . external_ids:system-id=$(cat
> $id_file)
> -
> -3. Start the ``ovn-controller``.
> -
> -   You need to run the below command on every boot::
> -
> -       $ /usr/share/openvswitch/scripts/ovn-ctl start_controller
> -
> -4. Start the Open vSwitch network driver.
> -
> -   By default Docker uses Linux bridge for networking. But it has support
> for
> -   external drivers. To use Open vSwitch instead of the Linux bridge, you
> will
> -   need to start the Open vSwitch driver.
> -
> -   The Open vSwitch driver uses the Python's flask module to listen to
> Docker's
> -   networking api calls. So, if your host does not have Python's flask
> module,
> -   install it::
> -
> -       $ sudo pip install Flask
> -
> -   Start the Open vSwitch driver on every host where you plan to create
> your
> -   containers. Refer to the note on ``$OVS_PYTHON_LIBS_PATH`` that is
> used below
> -   at the end of this document::
> -
> -       $ PYTHONPATH=$OVS_PYTHON_LIBS_PATH ovn-docker-overlay-driver
> --detach
> -
> -   .. note::
> -
> -     The ``$OVS_PYTHON_LIBS_PATH`` variable should point to the directory
> where
> -     Open vSwitch Python modules are installed. If you installed Open
> vSwitch
> -     Python modules via the Debian package of ``python-openvswitch`` or
> via pip
> -     by running ``pip install ovs``, you do not need to specify the PATH.
> If
> -     you installed it by following the instructions in
> -     :doc:`/intro/install/general`, then you should specify the PATH. In
> this
> -     case, the PATH depends on the options passed to ``./configure``. It
> is
> -     usually either ``/usr/share/openvswitch/python`` or
> -     ``/usr/local/share/openvswitch/python``
> -
> -Docker has inbuilt primitives that closely match OVN's logical switches
> and
> -logical port concepts. Consult Docker's documentation for all the possible
> -commands. Here are some examples.
> -
> -Create a logical switch
> -~~~~~~~~~~~~~~~~~~~~~~~
> -
> -To create a logical switch with name 'foo', on subnet '192.168.1.0/24',
> run::
> -
> -    $ NID=`docker network create -d openvswitch --subnet=192.168.1.0/24
> foo`
> -
> -List all logical switches
> -~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    $ docker network ls
> -
> -You can also look at this logical switch in OVN's northbound database by
> -running the following command::
> -
> -    $ ovn-nbctl --db=tcp:$CENTRAL_IP:6640 ls-list
> -
> -Delete a logical switch
> -~~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    $ docker network rm bar
> -
> -
> -Create a logical port
> -~~~~~~~~~~~~~~~~~~~~~
> -
> -Docker creates your logical port and attaches it to the logical network
> in a
> -single step. For example, to attach a logical port to network ``foo``
> inside
> -container busybox, run::
> -
> -    $ docker run -itd --net=foo --name=busybox busybox
> -
> -List all logical ports
> -~~~~~~~~~~~~~~~~~~~~~~
> -
> -Docker does not currently have a CLI command to list all logical ports
> but you
> -can look at them in the OVN database by running::
> -
> -    $ ovn-nbctl --db=tcp:$CENTRAL_IP:6640 lsp-list $NID
> -
> -Create and attach a logical port to a running container
> -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    $ docker network create -d openvswitch --subnet=192.168.2.0/24 bar
> -    $ docker network connect bar busybox
> -
> -Detach and delete a logical port from a running container
> -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -You can delete your logical port and detach it from a running container
> -by running:
> -
> -::
> -
> -    $ docker network disconnect bar busybox
> -
> -.. _docker-underlay:
> -
> -The "underlay" mode
> --------------------
> -
> -.. note::
> -
> -  This mode requires that you have a OpenStack setup pre-installed with
> -  OVN providing the underlay networking.
> -
> -1. One time setup
> -
> -   A OpenStack tenant creates a VM with a single network interface (or
> multiple)
> -   that belongs to management logical networks. The tenant needs to fetch
> the
> -   port-id associated with the interface via which he plans to send the
> container
> -   traffic inside the spawned VM. This can be obtained by running the
> below
> -   command to fetch the 'id' associated with the VM::
> -
> -       $ nova list
> -
> -   and then by running::
> -
> -       $ neutron port-list --device_id=$id
> -
> -   Inside the VM, download the OpenStack RC file that contains the tenant
> -   information (henceforth referred to as ``openrc.sh``). Edit the file
> and add the
> -   previously obtained port-id information to the file by appending the
> following
> -   line::
> -
> -       $ export OS_VIF_ID=$port_id
> -
> -   After this edit, the file will look something like::
> -
> -       #!/bin/bash
> -       export OS_AUTH_URL=http://10.33.75.122:5000/v2.0
> -       export OS_TENANT_ID=fab106b215d943c3bad519492278443d
> -       export OS_TENANT_NAME="demo"
> -       export OS_USERNAME="demo"
> -       export OS_VIF_ID=e798c371-85f4-4f2d-ad65-d09dd1d3c1c9
> -
> -2. Create the Open vSwitch bridge
> -
> -   If your VM has one ethernet interface (e.g.: 'eth0'), you will need to
> add
> -   that device as a port to an Open vSwitch bridge 'breth0' and move its
> IP
> -   address and route related information to that bridge. (If it has
> multiple
> -   network interfaces, you will need to create and attach an Open vSwitch
> -   bridge for the interface via which you plan to send your container
> -   traffic.)
> -
> -   If you use DHCP to obtain an IP address, then you should kill the DHCP
> -   client that was listening on the physical Ethernet interface (e.g.
> eth0) and
> -   start one listening on the Open vSwitch bridge (e.g. breth0).
> -
> -   Depending on your VM, you can make the above step persistent across
> reboots.
> -   For example, if your VM is Debian/Ubuntu-based, read
> -   `openvswitch-switch.README.Debian` found in `debian` folder. If your
> VM is
> -   RHEL-based, refer to :doc:`/intro/install/rhel`.
> -
> -3. Start the Open vSwitch network driver
> -
> -   The Open vSwitch driver uses the Python's flask module to listen to
> Docker's
> -   networking api calls. The driver also uses OpenStack's
> -   ``python-neutronclient`` libraries. If your host does not have Python's
> -   ``flask`` module or ``python-neutronclient`` you must install them. For
> -   example::
> -
> -       $ pip install python-neutronclient
> -       $ pip install Flask
> -
> -   Once installed, source the ``openrc`` file::
> -
> -       $ . ./openrc.sh
> -
> -   Start the network driver and provide your OpenStack tenant password
> when
> -   prompted::
> -
> -       $ PYTHONPATH=$OVS_PYTHON_LIBS_PATH ovn-docker-underlay-driver \
> -           --bridge breth0 --detach
> -
> -From here-on you can use the same Docker commands as described in
> -`docker-overlay`_.
> -
> -Refer to the ovs-architecture man pages (``man ovn-architecture``) to
> -understand OVN's architecture in detail.
> diff --git a/Documentation/howto/firewalld.rst
> b/Documentation/howto/firewalld.rst
> deleted file mode 100644
> index 0dc455ea8..000000000
> --- a/Documentation/howto/firewalld.rst
> +++ /dev/null
> @@ -1,107 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -===================================
> -Open Virtual Network With firewalld
> -===================================
> -
> -firewalld is a service that allows for easy administration of firewalls.
> OVN
> -ships with a set of service files that can be used with firewalld to allow
> -for remote connections to the northbound and southbound databases.
> -
> -This guide will describe how you can use these files with your existing
> -firewalld setup. Setup and administration of firewalld is outside the
> scope
> -of this document.
> -
> -Installation
> -------------
> -
> -If you have installed OVN from an RPM, then the service files for
> firewalld
> -will automatically be installed in ``/usr/lib/firewalld/services``.
> -Installation from RPM includes installation from the yum or dnf package
> -managers.
> -
> -If you have installed OVN from source, then from the top level source
> -directory, issue the following commands to copy the firewalld service
> files:
> -
> -::
> -
> -    $ cp rhel/usr_lib_firewalld_services_ovn-central-firewall-service.xml
> \
> -    /etc/firewalld/services/
> -    $ cp rhel/usr_lib_firewalld_services_ovn-host-firewall-service.xml \
> -    /etc/firewalld/services/
> -
> -
> -Activation
> -----------
> -
> -Assuming you are already running firewalld, you can issue the following
> -commands to enable the OVN services.
> -
> -On the central server (the one running ``ovn-northd``), issue the
> following::
> -
> -$ firewall-cmd --zone=public --add-service=ovn-central-firewall-service
> -
> -This will open TCP ports 6641 and 6642, allowing for remote connections
> to the
> -northbound and southbound databases.
> -
> -On the OVN hosts (the ones running ``ovn-controller``), issue the
> following::
> -
> -$ firewall-cmd --zone=public --add-service=ovn-host-firewall-service
> -
> -This will open UDP port 6081, allowing for geneve traffic to flow between
> the
> -controllers.
> -
> -Variations
> -----------
> -
> -When installing the XML service files, you have the choice of copying
> them to
> -``/etc/firewalld/services`` or ``/usr/lib/firewalld/services``. The
> former is
> -recommend since the latter can be overwritten if firewalld is upgraded.
> -
> -The above commands assumed your underlay network interfaces are in the
> -"public" firewalld zone. If your underlay network interfaces are in a
> separate
> -zone, then adjust the above commands accordingly.
> -
> -The ``--permanent`` option may be passed to the above firewall-cmd
> invocations
> -in order for the services to be permanently added to the firewalld
> -configuration. This way it is not necessary to re-issue the commands each
> -time the firewalld service restarts.
> -
> -The ovn-host-firewall-service only opens port 6081. This is because the
> -default protocol for OVN tunnels is geneve. If you are using a different
> -encapsulation protocol, you will need to modify the XML service file to
> open
> -the appropriate port(s). For VXLAN, open port 4789. For STT, open port
> 7471.
> -
> -Recommendations
> ----------------
> -
> -The firewalld service files included with the OVS repo are meant as a
> -convenience for firewalld users. All that the service files do is to open
> -the common ports used by OVN. No additional security is provided. To
> ensure a
> -more secure environment, it is a good idea to do the following
> -
> -* Use tools such as iptables or nftables to restrict access to known
> hosts.
> -* Use SSL for all remote connections to OVN databases.
> -* Use role-based access control for connections to the OVN southbound
> -  database.
> diff --git a/Documentation/howto/index.rst b/Documentation/howto/index.rst
> index 9a3487be3..60fb8a717 100644
> --- a/Documentation/howto/index.rst
> +++ b/Documentation/howto/index.rst
> @@ -50,12 +50,3 @@ OVS
>     sflow
>     dpdk
>
> -OVN
> ----
> -
> -.. toctree::
> -   :maxdepth: 1
> -
> -   docker
> -   openstack-containers
> -   firewalld
> diff --git a/Documentation/howto/openstack-containers.rst
> b/Documentation/howto/openstack-containers.rst
> deleted file mode 100644
> index 692fe25e5..000000000
> --- a/Documentation/howto/openstack-containers.rst
> +++ /dev/null
> @@ -1,135 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -================================================
> -Integration of Containers with OVN and OpenStack
> -================================================
> -
> -Isolation between containers is weaker than isolation between VMs, so some
> -environments deploy containers for different tenants in separate VMs as an
> -additional security measure.  This document describes creation of
> containers
> -inside VMs and how they can be made part of the logical networks
> securely.  The
> -created logical network can include VMs, containers and physical machines
> as
> -endpoints.  To better understand the proposed integration of containers
> with
> -OVN and OpenStack, this document describes the end to end workflow with an
> -example.
> -
> -* A OpenStack tenant creates a VM (say VM-A) with a single network
> interface
> -  that belongs to a management logical network.  The VM is meant to host
> -  containers.  OpenStack Nova chooses the hypervisor on which VM-A is
> created.
> -
> -* A Neutron port may have been created in advance and passed in to Nova
> with
> -  the request to create a new VM.  If not, Nova will issue a request to
> Neutron
> -  to create a new port.  The ID of the logical port from Neutron will
> also be
> -  used as the vif-id for the virtual network interface (VIF) of VM-A.
> -
> -* When VM-A is created on a hypervisor, its VIF gets added to the Open
> vSwitch
> -  integration bridge.  This creates a row in the Interface table of the
> -  ``Open_vSwitch`` database.  As explained in the :doc:`integration guide
> -  </topics/integration>`, the vif-id associated with the VM network
> interface
> -  gets added in the ``external_ids:iface-id`` column of the newly created
> row
> -  in the Interface table.
> -
> -* Since VM-A belongs to a logical network, it gets an IP address.  This IP
> -  address is used to spawn containers (either manually or through
> container
> -  orchestration systems) inside that VM and to monitor the health of the
> -  created containers.
> -
> -* The vif-id associated with the VM's network interface can be obtained by
> -  making a call to Neutron using tenant credentials.
> -
> -* This flow assumes a component called a "container network plugin".  If
> you
> -  take Docker as an example for containers, you could envision the plugin
> to be
> -  either a wrapper around Docker or a feature of Docker itself that
> understands
> -  how to perform part of this workflow to get a container connected to a
> -  logical network managed by Neutron.  The rest of the flow refers to this
> -  logical component that does not yet exist as the "container network
> plugin".
> -
> -* All the calls to Neutron will need tenant credentials.  These calls can
> -  either be made from inside the tenant VM as part of a container network
> -  plugin or from outside the tenant VM (if the tenant is not comfortable
> using
> -  temporary Keystone tokens from inside the tenant VMs).  For simplicity,
> this
> -  document explains the work flow using the former method.
> -
> -* The container hosting VM will need Open vSwitch installed in it.  The
> only
> -  work for Open vSwitch inside the VM is to tag network traffic coming
> from
> -  containers.
> -
> -* When a container needs to be created inside the VM with a container
> network
> -  interface that is expected to be attached to a particular logical
> switch, the
> -  network plugin in that VM chooses any unused VLAN (This VLAN tag only
> needs
> -  to be unique inside that VM.  This limits the number of container
> interfaces
> -  to 4096 inside a single VM).  This VLAN tag is stripped out in the
> hypervisor
> -  by OVN and is only useful as a context (or metadata) for OVN.
> -
> -* The container network plugin then makes a call to Neutron to create a
> logical
> -  port.  In addition to all the inputs that a call to create a port in
> Neutron
> -  that are currently needed, it sends the vif-id and the VLAN tag as
> inputs.
> -
> -* Neutron in turn will verify that the vif-id belongs to the tenant in
> question
> -  and then uses the OVN specific plugin to create a new row in the
> -  Logical_Switch_Port table of the OVN Northbound Database.  Neutron
> responds
> -  back with an IP address and MAC address for that network interface.  So
> -  Neutron becomes the IPAM system and provides unique IP and MAC addresses
> -  across VMs and containers in the same logical network.
> -
> -* The Neutron API call above to create a logical port for the container
> could
> -  add a relatively significant amount of time to container creation.
> However,
> -  an optimization is possible here.  Logical ports could be created in
> advance
> -  and reused by the container system doing container orchestration.
> Additional
> -  Neutron API calls would only be needed if the port needs to be attached
> to a
> -  different logical network.
> -
> -* When a container is eventually deleted, the network plugin in that VM
> may
> -  make a call to Neutron to delete that port.  Neutron in turn will
> delete the
> -  entry in the ``Logical_Switch_Port`` table of the OVN Northbound
> Database.
> -
> -As an example, consider Docker containers.  Since Docker currently does
> not
> -have a network plugin feature, this example uses a hypothetical wrapper
> around
> -Docker to make calls to Neutron.
> -
> -* Create a Logical switch::
> -
> -      $ ovn-docker --cred=cca86bd13a564ac2a63ddf14bf45d37f create network
> LS1
> -
> -  The above command will make a call to Neutron with the credentials to
> create
> -  a logical switch.  The above is optional if the logical switch has
> already
> -  been created from outside the VM.
> -
> -* List networks available to the tenant::
> -
> -      $ ovn-docker --cred=cca86bd13a564ac2a63ddf14bf45d37f list networks
> -
> -* Create a container and attach a interface to the previously created
> switch as
> -  a logical port::
> -
> -      $ ovn-docker --cred=cca86bd13a564ac2a63ddf14bf45d37f
> --vif-id=$VIF_ID \
> -          --network=LS1 run -d --net=none ubuntu:14.04 /bin/sh -c \
> -          "while true; do echo hello world; sleep 1; done"
> -
> -  The above command will make a call to Neutron with all the inputs it
> -  currently needs to create a logical port.  In addition, it passes the
> $VIF_ID
> -  and a unused VLAN.  Neutron will add that information in OVN and return
> back
> -  a MAC address and IP address for that interface.  ovn-docker will then
> create
> -  a veth pair, insert one end inside the container as 'eth0' and the
> other end
> -  as a port of a local OVS bridge as an access port of the chosen VLAN.
> diff --git a/Documentation/index.rst b/Documentation/index.rst
> index bace34dbf..f18f8df1c 100644
> --- a/Documentation/index.rst
> +++ b/Documentation/index.rst
> @@ -33,22 +33,20 @@ How the Documentation is Organised
>  The Open vSwitch documentation is organised into multiple sections:
>
>  - :doc:`Installation guides </intro/install/index>` guide you through
> -  installing Open vSwitch (OVS) and Open Virtual Network (OVN) on a
> variety of
> -  different platforms
> +  installing Open vSwitch (OVS) on a variety of different platforms
>  - :doc:`Tutorials </tutorials/index>` take you through a series of steps
> to
> -  configure OVS and OVN in sandboxed environments
> -- :doc:`Topic guides </topics/index>` provide a high level overview of
> OVS and
> -  OVN internals and operation
> -- :doc:`How-to guides </howto/index>` are recipes or use-cases for OVS
> and OVN.
> +  configure OVS in sandboxed environments
> +- :doc:`Topic guides </topics/index>` provide a high level overview of OVS
> +  internals and operation
> +- :doc:`How-to guides </howto/index>` are recipes or use-cases for OVS.
>    They are more advanced than the tutorials.
>  - :doc:`Frequently Asked Questions </faq/index>` provide general insight
> into
> -  a variety of topics related to configuration and operation of OVS and
> OVN.
> +  a variety of topics related to configuration and operation of OVS.
>
>  First Steps
>  -----------
>
> -Getting started with Open vSwitch (OVS) or Open Virtual Network (OVN) for
> Open
> -vSwitch? Start here.
> +Getting started with Open vSwitch (OVS)? Start here.
>
>  - **Overview:** :doc:`intro/what-is-ovs` |
>    :doc:`intro/why-ovs`
> @@ -64,12 +62,8 @@ vSwitch? Start here.
>
>  - **Tutorials:** :doc:`tutorials/faucet` |
>    :doc:`tutorials/ovs-advanced` |
> -  :doc:`tutorials/ovn-sandbox` |
> -  :doc:`tutorials/ovn-openstack` |
>    :doc:`tutorials/ovs-conntrack` |
>    :doc:`tutorials/ipsec` |
> -  :doc:`tutorials/ovn-ipsec` |
> -  :doc:`tutorials/ovn-rbac`
>
>  Deeper Dive
>  -----------
> diff --git a/Documentation/intro/install/fedora.rst
> b/Documentation/intro/install/fedora.rst
> index 4e1a99766..f11d05a01 100644
> --- a/Documentation/intro/install/fedora.rst
> +++ b/Documentation/intro/install/fedora.rst
> @@ -119,16 +119,6 @@ tests.  This can take several minutes.
>
>      $ make rpm-fedora RPMBUILD_OPT="--with check"
>
> -To build OVN RPMs, execute the following from the directory in which
> -`./configure` was executed:
> -
> -::
> -
> -    $ make rpm-fedora-ovn
> -
> -This will create the RPMs `ovn`, `ovn-common`, `ovn-central`, `ovn-host`,
> -`ovn-docker` and `ovn-vtep`.
> -
>
>  Kernel OVS Tree Datapath RPM
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> @@ -165,8 +155,6 @@ In most cases only the `openvswitch` RPM will need to
> be installed. The
>  `openvswitch-debuginfo` RPMs are optional unless required for a specific
>  purpose.
>
> -The `ovn-*` packages are only needed when using OVN.
> -
>  Refer to the `RHEL README`__ for additional usage and configuration
>  information.
>
> diff --git a/Documentation/intro/install/index.rst
> b/Documentation/intro/install/index.rst
> index c27a9c9d1..586ced95f 100644
> --- a/Documentation/intro/install/index.rst
> +++ b/Documentation/intro/install/index.rst
> @@ -62,14 +62,6 @@ provided below.
>     fedora
>     rhel
>
> -Upgrades
> ---------
> -
> -.. toctree::
> -   :maxdepth: 2
> -
> -   ovn-upgrades
> -
>  Others
>  ------
>
> diff --git a/Documentation/intro/install/ovn-upgrades.rst
> b/Documentation/intro/install/ovn-upgrades.rst
> deleted file mode 100644
> index 3e6cd984e..000000000
> --- a/Documentation/intro/install/ovn-upgrades.rst
> +++ /dev/null
> @@ -1,115 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -============
> -OVN Upgrades
> -============
> -
> -Since OVN is a distributed system, special consideration must be given to
> -the process used to upgrade OVN across a deployment.  This document
> discusses
> -the recommended upgrade process.
> -
> -Release Notes
> --------------
> -
> -You should always check the OVS and OVN release notes (NEWS file) for any
> -release specific notes on upgrades.
> -
> -OVS
> ----
> -
> -OVN depends on and is included with OVS.  It's expected that OVS and OVN
> are
> -upgraded together, partly for convenience.  OVN is included in OVS
> releases
> -so it's easiest to upgrade them together.  OVN may also make use of new
> -features of OVS only available in that release.
> -
> -Upgrade ovn-controller
> -----------------------
> -
> -You should start by upgrading ovn-controller on each host it's running on.
> -First, you upgrade the OVS and OVN packages.  Then, restart the
> -ovn-controller service.  You can restart with ovn-ctl::
> -
> -    $ sudo /usr/share/openvswitch/scripts/ovn-ctl restart_controller
> -
> -or with systemd::
> -
> -    $ sudo systemd restart ovn-controller
> -
> -Upgrade OVN Databases and ovn-northd
> -------------------------------------
> -
> -The OVN databases and ovn-northd should be upgraded next.  Since
> ovn-controller
> -has already been upgraded, it will be ready to operate on any new
> functionality
> -specified by the database or logical flows created by ovn-northd.
> -
> -Upgrading the OVN packages installs everything needed for an upgrade.
> The only
> -step required after upgrading the packages is to restart ovn-northd, which
> -automatically restarts the databases and upgrades the database schema, as
> well.
> -
> -You may perform this restart using the ovn-ctl script::
> -
> -    $ sudo /usr/share/openvswitch/scripts/ovn-ctl restart_northd
> -
> -or if you're using a Linux distribution with systemd::
> -
> -    $ sudo systemctl restart ovn-northd
> -
> -Schema Change
> -^^^^^^^^^^^^^
> -
> -During database upgrading, if there is schema change, the DB file will be
> -converted to the new schema automatically, if the schema change is
> backward
> -compatible.  OVN tries the best to keep the DB schemas backward
> compatible.
> -
> -However, there can be situations that an incompatible change is
> reasonble.  An
> -example of such case is to add constraints in the table to ensure
> correctness.
> -If there were already data that violates the new constraints got added
> somehow,
> -it will result in DB upgrade failures.  In this case, user should manually
> -correct data using ovn-nbctl (for north-bound DB) or ovn-sbctl (for south-
> -bound DB), and then upgrade again following previous steps.  Below is a
> list
> -of known impactible schema changes and how to fix when error encountered.
> -
> -#. Release 2.11: index [type, ip] added for Encap table of south-bound DB
> to
> -   prevent duplicated IPs being used for same tunnel type.  If there are
> -   duplicated data added already (e.g. due to improper chassis
> management),
> -   a convenient way to fix is to find the chassis that is using the IP
> -   with command::
> -
> -    $ ovn-sbctl show
> -
> -   Then delete the chassis with command::
> -
> -    $ ovn-sbctl chassis-del <chassis>
> -
> -
> -Upgrading OVN Integration
> --------------------------
> -
> -Lastly, you may also want to upgrade integration with OVN that you may be
> -using.  For example, this could be the OpenStack Neutron driver or
> -ovn-kubernetes.
> -
> -OVN's northbound database schema is a backwards compatible interface, so
> -you should be able to safely complete an OVN upgrade before upgrading
> -any integration in use.
> diff --git a/Documentation/ref/ovs-sim.1.rst
> b/Documentation/ref/ovs-sim.1.rst
> index 4382598e1..f59cd7af7 100644
> --- a/Documentation/ref/ovs-sim.1.rst
> +++ b/Documentation/ref/ovs-sim.1.rst
> @@ -142,103 +142,3 @@ with ``main`` directly.
>      must already have been created by a previous invocation of
>      ``net_add``. The default sandbox must not be ``main``.
>
> -OVN Commands
> -------------
> -
> -These commands interact with OVN, the Open Virtual Network.
> -
> -``ovn_start`` [*options*]
> -    Creates and initializes the central OVN databases (both
> -    ``ovn-sb(5)`` and ``ovn-nb(5)``) and starts an instance of
> -    ``ovsdb-server`` for each one.  Also starts an instance of
> -    ``ovn-northd``.
> -
> -    The following options are available:
> -
> -       ``--nbdb-model`` *model*
> -           Uses the given database model for the northbound database.
> -           The *model* may be ``standalone`` (the default), ``backup``,
> -           or ``clustered``.
> -
> -       ``--nbdb-servers`` *n*
> -           For a clustered northbound database, the number of servers in
> -           the cluster.  The default is 3.
> -
> -       ``--sbdb-model`` *model*
> -           Uses the given database model for the southbound database.
> -           The *model* may be ``standalone`` (the default), ``backup``,
> -           or ``clustered``.
> -
> -       ``--sbdb-servers`` *n*
> -           For a clustered southbound database, the number of servers in
> -           the cluster.  The default is 3.
> -
> -``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``.
> -
> -Examples
> -========
> -
> -The following creates a pair of Open vSwitch instances ``hv0`` and
> -``hv1``, adds a port named ``vif0`` or ``vif1``, respectively, to each
> -one, and then connects the two through an interconnection network
> -``n1``::
> -
> -    net_add n1
> -    for i in 0 1; do
> -        sim_add hv$i
> -        as hv$i ovs-vsctl add-br br0 -- add-port br0 vif$i
> -        as hv$i net_attach n1 br0
> -    done
> -
> -Here’s an extended version that also starts OVN::
> -
> -    ovn_start
> -    ovn-nbctl ls-add lsw0
> -    net_add n1
> -    for i in 0 1; do
> -        sim_add hv$i
> -        as hv$i
> -        ovs-vsctl add-br br-phys
> -        ovn_attach n1 br-phys 192.168.0.`expr $i + 1`
> -        ovs-vsctl add-port br-int vif$i -- set Interface vif$i
> external-ids:iface-id=lp$i
> -        ovn-nbctl lsp-add lsw0 lp$i
> -        ovn-nbctl lsp-set-addresses lp$i f0:00:00:00:00:0$i
> -    done
> -
> -Here’s a primitive OVN "scale test" (adjust the scale by changing
> -``n`` in the first line::
> -
> -    n=200; export n
> -    ovn_start --sbdb-model=clustered
> -    net_add n1
> -    ovn-nbctl ls-add br0
> -    for i in `seq $n`; do
> -        (sim_add hv$i
> -        as hv$i
> -        ovs-vsctl add-br br-phys
> -        y=$(expr $i / 256)
> -        x=$(expr $i % 256)
> -        ovn_attach n1 br-phys 192.168.$y.$x
> -        ovs-vsctl add-port br-int vif$i -- set Interface vif$i
> external-ids:iface-id=lp$i) &
> -        case $i in
> -            *50|*00) echo $i; wait ;;
> -        esac
> -    done
> -    wait
> -    for i in `seq $n`; do
> -        yy=$(printf %02x $(expr $i / 256))
> -        xx=$(printf $02x $(expr $i % 256))
> -        ovn-nbctl lsp-add br0 lp$i
> -        ovn-nbctl lsp-set-addresses lp$i f0:00:00:00:$yy:$xx
> -    done
> -
> -When the scale test has finished initializing, you can watch the
> -logical ports come up with a command like this::
> -
> -    watch 'for i in `seq $n`; do if test `ovn-nbctl lsp-get-up lp$i` !=
> up; then echo $i; fi; done'
> diff --git a/Documentation/topics/high-availability.rst
> b/Documentation/topics/high-availability.rst
> deleted file mode 100644
> index a5cb76383..000000000
> --- a/Documentation/topics/high-availability.rst
> +++ /dev/null
> @@ -1,440 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -==================================
> -OVN Gateway High Availability Plan
> -==================================
> -
> -::
> -
> -    OVN Gateway
> -
> -         +---------------------------+
> -         |                           |
> -         |     External Network      |
> -         |                           |
> -         +-------------^-------------+
> -                       |
> -                       |
> -                 +-----------+
> -                 |           |
> -                 |  Gateway  |
> -                 |           |
> -                 +-----------+
> -                       ^
> -                       |
> -                       |
> -         +-------------v-------------+
> -         |                           |
> -         |    OVN Virtual Network    |
> -         |                           |
> -         +---------------------------+
> -
> -The OVN gateway is responsible for shuffling traffic between the tunneled
> -overlay network (governed by ovn-northd), and the legacy physical
> network.  In
> -a naive implementation, the gateway is a single x86 server, or hardware
> VTEP.
> -For most deployments, a single system has enough forwarding capacity to
> service
> -the entire virtualized network, however, it introduces a single point of
> -failure.  If this system dies, the entire OVN deployment becomes
> unavailable.
> -To mitigate this risk, an HA solution is critical -- by spreading
> -responsibility across multiple systems, no single server failure can take
> down
> -the network.
> -
> -An HA solution is both critical to the manageability of the system, and
> -extremely difficult to get right.  The purpose of this document, is to
> propose
> -a plan for OVN Gateway High Availability which takes into account our past
> -experience building similar systems.  It should be considered a fluid
> changing
> -proposal, not a set-in-stone decree.
> -
> -.. note::
> -    This document describes a range of options OVN could take to provide
> -    high availability for gateways.  The current implementation provides
> L3
> -    gateway high availability by the "Router Specific Active/Backup"
> -    approach described in this document.
> -
> -Basic Architecture
> -------------------
> -
> -In an OVN deployment, the set of hypervisors and network elements
> operating
> -under the guidance of ovn-northd are in what's called "logical space".
> These
> -servers use VXLAN, STT, or Geneve to communicate, oblivious to the
> details of
> -the underlying physical network.  When these systems need to communicate
> with
> -legacy networks, traffic must be routed through a Gateway which
> translates from
> -OVN controlled tunnel traffic, to raw physical network traffic.
> -
> -Since the gateway is typically the only system with a connection to the
> -physical network all traffic between logical space and the WAN must travel
> -through it.  This makes it a critical single point of failure -- if the
> gateway
> -dies, communication with the WAN ceases for all systems in logical space.
> -
> -To mitigate this risk, multiple gateways should be run in a "High
> Availability
> -Cluster" or "HA Cluster".  The HA cluster will be responsible for
> performing
> -the duties of a gateways,  while being able to recover gracefully from
> -individual member failures.
> -
> -::
> -
> -    OVN Gateway HA Cluster
> -
> -             +---------------------------+
> -             |                           |
> -             |     External Network      |
> -             |                           |
> -             +-------------^-------------+
> -                           |
> -                           |
> -    +----------------------v----------------------+
> -    |                                             |
> -    |          High Availability Cluster          |
> -    |                                             |
> -    | +-----------+  +-----------+  +-----------+ |
> -    | |           |  |           |  |           | |
> -    | |  Gateway  |  |  Gateway  |  |  Gateway  | |
> -    | |           |  |           |  |           | |
> -    | +-----------+  +-----------+  +-----------+ |
> -    +----------------------^----------------------+
> -                           |
> -                           |
> -             +-------------v-------------+
> -             |                           |
> -             |    OVN Virtual Network    |
> -             |                           |
> -             +---------------------------+
> -
> -L2 vs L3 High Availability
> -~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -In order to achieve this goal, there are two broad approaches one can
> take.
> -The HA cluster can appear to the network like a giant Layer 2 Ethernet
> Switch,
> -or like a giant IP Router. These approaches are called L2HA, and L3HA
> -respectively.  L2HA allows ethernet broadcast domains to extend into
> logical
> -space, a significant advantage, but this comes at a cost.  The need to
> avoid
> -transient L2 loops during failover significantly complicates their
> design.  On
> -the other hand, L3HA works for most use cases, is simpler, and fails more
> -gracefully.  For these reasons, it is suggested that OVN supports an L3HA
> -model, leaving L2HA for future work (or third party VTEP providers).  Both
> -models are discussed further below.
> -
> -L3HA
> -----
> -
> -In this section, we'll work through a basic simple L3HA implementation,
> on top
> -of which we'll gradually build more sophisticated features explaining
> their
> -motivations and implementations as we go.
> -
> -Naive active-backup
> -~~~~~~~~~~~~~~~~~~~
> -
> -Let's assume that there are a collection of logical routers which a
> tenant has
> -asked for, our task is to schedule these logical routers on one of N
> gateways,
> -and gracefully redistribute the routers on gateways which have failed.
> The
> -absolute simplest way to achieve this is what we'll call
> "naive-active-backup".
> -
> -::
> -
> -    Naive Active Backup HA Implementation
> -
> -    +----------------+   +----------------+
> -    | Leader         |   | Backup         |
> -    |                |   |                |
> -    |      A B C     |   |                |
> -    |                |   |                |
> -    +----+-+-+-+----++   +-+--------------+
> -         ^ ^ ^ ^    |      |
> -         | | | |    |      |
> -         | | | |  +-+------+---+
> -         + + + +  | ovn-northd |
> -         Traffic  +------------+
> -
> -In a naive active-backup, one of the Gateways is chosen (arbitrarily) as a
> -leader.  All logical routers (A, B, C in the figure), are scheduled on
> this
> -leader gateway and all traffic flows through it.  ovn-northd monitors this
> -gateway via OpenFlow echo requests (or some equivalent), and if the
> gateway
> -dies, it recreates the routers on one of the backups.
> -
> -This approach basically works in most cases and should likely be the
> starting
> -point for OVN -- it's strictly better than no HA solution and is a good
> -foundation for more sophisticated solutions.  That said, it's not without
> it's
> -limitations. Specifically, this approach doesn't coordinate with the
> physical
> -network to minimize disruption during failures, and it tightly couples
> failover
> -to ovn-northd (we'll discuss why this is bad in a bit), and wastes
> resources by
> -leaving backup gateways completely unutilized.
> -
> -Router Failover
> -+++++++++++++++
> -
> -When ovn-northd notices the leader has died and decides to migrate
> routers to a
> -backup gateway, the physical network has to be notified to direct traffic
> to
> -the new gateway.  Otherwise, traffic could be blackholed for longer than
> -necessary making failovers worse than they need to be.
> -
> -For now, let's assume that OVN requires all gateways to be on the same IP
> -subnet on the physical network.  If this isn't the case, gateways would
> need to
> -participate in routing protocols to orchestrate failovers, something
> which is
> -difficult and out of scope of this document.
> -
> -Since all gateways are on the same IP subnet, we simply need to worry
> about
> -updating the MAC learning tables of the Ethernet switches on that subnet.
> -Presumably, they all have entries for each logical router pointing to the
> old
> -leader.  If these entries aren't updated, all traffic will be sent to the
> (now
> -defunct) old leader, instead of the new one.
> -
> -In order to mitigate this issue, it's recommended that the new gateway
> sends a
> -Reverse ARP (RARP) onto the physical network for each logical router it
> now
> -controls.  A Reverse ARP is a benign protocol used by many hypervisors
> when
> -virtual machines migrate to update L2 forwarding tables.  In this case,
> the
> -ethernet source address of the RARP is that of the logical router it
> -corresponds to, and its destination is the broadcast address.  This
> causes the
> -RARP to travel to every L2 switch in the broadcast domain, updating
> forwarding
> -tables accordingly.  This strategy is recommended in all failover
> mechanisms
> -discussed in this document -- when a router newly boots on a new leader,
> it
> -should RARP its MAC address.
> -
> -Controller Independent Active-backup
> -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    Controller Independent Active-Backup Implementation
> -
> -    +----------------+   +----------------+
> -    | Leader         |   | Backup         |
> -    |                |   |                |
> -    |      A B C     |   |                |
> -    |                |   |                |
> -    +----------------+   +----------------+
> -         ^ ^ ^ ^
> -         | | | |
> -         | | | |
> -         + + + +
> -         Traffic
> -
> -The fundamental problem with naive active-backup, is it tightly couples
> the
> -failover solution to ovn-northd.  This can significantly increase
> downtime in
> -the event of a failover as the (often already busy) ovn-northd controller
> has
> -to recompute state for the new leader. Worse, if ovn-northd goes down, we
> can't
> -perform gateway failover at all.  This violates the principle that control
> -plane outages should have no impact on dataplane functionality.
> -
> -In a controller independent active-backup configuration, ovn-northd is
> -responsible for initial configuration while the HA cluster is responsible
> for
> -monitoring the leader, and failing over to a backup if necessary.
> ovn-northd
> -sets HA policy, but doesn't actively participate when failovers occur.
> -
> -Of course, in this model, ovn-northd is not without some responsibility.
> Its
> -role is to pre-plan what should happen in the event of a failure, leaving
> it to
> -the individual switches to execute this plan.  It does this by assigning
> each
> -gateway a unique leadership priority.  Once assigned, it communicates this
> -priority to each node it controls.  Nodes use the leadership priority to
> -determine which gateway in the cluster is the active leader by using a
> simple
> -metric: the leader is the gateway that is healthy, with the highest
> priority.
> -If that gateway goes down, leadership falls to the next highest priority,
> and
> -conversely, if a new gateway comes up with a higher priority, it takes
> over
> -leadership.
> -
> -Thus, in this model, leadership of the HA cluster is determined simply by
> the
> -status of its members.  Therefore if we can communicate the status of each
> -gateway to each transport node, they can individually figure out which is
> the
> -leader, and direct traffic accordingly.
> -
> -Tunnel Monitoring
> -+++++++++++++++++
> -
> -Since in this model leadership is determined exclusively by the health
> status
> -of member gateways, a key problem is how do we communicate this
> information to
> -the relevant transport nodes.  Luckily, we can do this fairly cheaply
> using
> -tunnel monitoring protocols like BFD.
> -
> -The basic idea is pretty straightforward.  Each transport node maintains a
> -tunnel to every gateway in the HA cluster (not just the leader).  These
> tunnels
> -are monitored using the BFD protocol to see which are alive.  Given this
> -information, hypervisors can trivially compute the highest priority live
> -gateway, and thus the leader.
> -
> -In practice, this leadership computation can be performed trivially using
> the
> -bundle or group action.  Rather than using OpenFlow to simply output to
> the
> -leader, all gateways could be listed in an active-backup bundle action
> ordered
> -by their priority.  The bundle action will automatically take into
> account the
> -tunnel monitoring status to output the packet to the highest priority live
> -gateway.
> -
> -Inter-Gateway Monitoring
> -++++++++++++++++++++++++
> -
> -One somewhat subtle aspect of this model, is that failovers are not
> globally
> -atomic.  When a failover occurs, it will take some time for all
> hypervisors to
> -notice and adjust accordingly.  Similarly, if a new high priority Gateway
> comes
> -up, it may take some time for all hypervisors to switch over to the new
> leader.
> -In order to avoid confusing the physical network, under these
> circumstances
> -it's important for the backup gateways to drop traffic they've received
> -erroneously.  In order to do this, each Gateway must know whether or not
> it is,
> -in fact active.  This can be achieved by creating a mesh of tunnels
> between
> -gateways.  Each gateway monitors the other gateways its cluster to
> determine
> -which are alive, and therefore whether or not that gateway happens to be
> the
> -leader.  If leading, the gateway forwards traffic normally, otherwise it
> drops
> -all traffic.
> -
> -We should note that this method works well under the assumption that there
> -are no inter-gateway connectivity failures, in such case this method
> would fail
> -to elect a single master. The simplest example is two gateways which stop
> seeing
> -each other but can still reach the hypervisors. Protocols like VRRP or
> CARP
> -have the same issue. A mitigation for this type of failure mode could be
> -achieved by having all network elements (hypervisors and gateways)
> periodically
> -share their link status to other endpoints.
> -
> -Gateway Leadership Resignation
> -++++++++++++++++++++++++++++++
> -
> -Sometimes a gateway may be healthy, but still may not be suitable to lead
> the
> -HA cluster.  This could happen for several reasons including:
> -
> -* The physical network is unreachable
> -
> -* BFD (or ping) has detected the next hop router is unreachable
> -
> -* The Gateway recently booted and isn't fully configured
> -
> -In this case, the Gateway should resign leadership by holding its tunnels
> down
> -using the ``other_config:cpath_down`` flag.  This indicates to
> participating
> -hypervisors and Gateways that this gateway should be treated as if it's
> down,
> -even though its tunnels are still healthy.
> -
> -Router Specific Active-Backup
> -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    Router Specific Active-Backup
> -
> -    +----------------+ +----------------+
> -    |                | |                |
> -    |      A C       | |     B D E      |
> -    |                | |                |
> -    +----------------+ +----------------+
> -                  ^ ^   ^ ^
> -                  | |   | |
> -                  | |   | |
> -                  + +   + +
> -                   Traffic
> -
> -Controller independent active-backup is a great advance over naive
> -active-backup, but it still has one glaring problem -- it under-utilizes
> the
> -backup gateways.  In ideal scenario, all traffic would split evenly among
> the
> -live set of gateways.  Getting all the way there is somewhat tricky, but
> as a
> -step in the direction, one could use the "Router Specific Active-Backup"
> -algorithm.  This algorithm looks a lot like active-backup on a per logical
> -router basis, with one twist.  It chooses a different active Gateway for
> each
> -logical router.  Thus, in situations where there are several logical
> routers,
> -all with somewhat balanced load, this algorithm performs better.
> -
> -Implementation of this strategy is quite straightforward if built on top
> of
> -basic controller independent active-backup.  On a per logical router
> basis, the
> -algorithm is the same, leadership is determined by the liveness of the
> -gateways.  The key difference here is that the gateways must have a
> different
> -leadership priority for each logical router.  These leadership priorities
> can
> -be computed by ovn-northd just as they had been in the controller
> independent
> -active-backup model.
> -
> -Once we have these per logical router priorities, they simply need be
> -communicated to the members of the gateway cluster and the hypervisors.
> The
> -hypervisors in particular, need simply have an active-backup bundle
> action (or
> -group action) per logical router listing the gateways in priority order
> for
> -*that router*, rather than having a single bundle action shared for all
> the
> -routers.
> -
> -Additionally, the gateways need to be updated to take into account
> individual
> -router priorities.  Specifically, each gateway should drop traffic of
> backup
> -routers it's running, and forward traffic of active gateways, instead of
> simply
> -dropping or forwarding everything.  This should likely be done by having
> -ovn-controller recompute OpenFlow for the gateway, though other options
> exist.
> -
> -The final complication is that ovn-northd's logic must be updated to
> choose
> -these per logical router leadership priorities in a more sophisticated
> manner.
> -It doesn't matter much exactly what algorithm it chooses to do this,
> beyond
> -that it should provide good balancing in the common case.  I.E. each
> logical
> -routers priorities should be different enough that routers balance to
> different
> -gateways even when failures occur.
> -
> -Preemption
> -++++++++++
> -
> -In an active-backup setup, one issue that users will run into is that of
> -gateway leader preemption.  If a new Gateway is added to a cluster, or
> for some
> -reason an existing gateway is rebooted, we could end up in a situation
> where
> -the newly activated gateway has higher priority than any other in the HA
> -cluster.  In this case, as soon as that gateway appears, it will preempt
> -leadership from the currently active leader causing an unnecessary
> failover.
> -Since failover can be quite expensive, this preemption may be undesirable.
> -
> -The controller can optionally avoid preemption by cleverly tweaking the
> -leadership priorities.  For each router, new gateways should be assigned
> -priorities that put them second in line or later when they eventually
> come up.
> -Furthermore, if a gateway goes down for a significant period of time, its
> old
> -leadership priorities should be revoked and new ones should be assigned
> as if
> -it's a brand new gateway.  Note that this should only happen if a gateway
> has
> -been down for a while (several minutes), otherwise a flapping gateway
> could
> -have wide ranging, unpredictable, consequences.
> -
> -Note that preemption avoidance should be optional depending on the
> deployment.
> -One necessarily sacrifices optimal load balancing to satisfy these
> requirements
> -as new gateways will get no traffic on boot.  Thus, this feature
> represents a
> -trade-off which must be made on a per installation basis.
> -
> -Fully Active-Active HA
> -~~~~~~~~~~~~~~~~~~~~~~
> -
> -::
> -
> -    Fully Active-Active HA
> -
> -    +----------------+ +----------------+
> -    |                | |                |
> -    |   A B C D E    | |    A B C D E   |
> -    |                | |                |
> -    +----------------+ +----------------+
> -                  ^ ^   ^ ^
> -                  | |   | |
> -                  | |   | |
> -                  + +   + +
> -                   Traffic
> -
> -The final step in L3HA is to have true active-active HA.  In this
> scenario each
> -router has an instance on each Gateway, and a mechanism similar to ECMP
> is used
> -to distribute traffic evenly among all instances.  This mechanism would
> require
> -Gateways to participate in routing protocols with the physical network to
> -attract traffic and alert of failures.  It is out of scope of this
> document,
> -but may eventually be necessary.
> -
> -L2HA
> -----
> -
> -L2HA is very difficult to get right.  Unlike L3HA, where the consequences
> of
> -problems are minor, in L2HA if two gateways are both transiently active,
> an L2
> -loop triggers and a broadcast storm results.  In practice to get around
> this,
> -gateways end up implementing an overly conservative "when in doubt drop
> all
> -traffic" policy, or they implement something like MLAG.
> -
> -MLAG has multiple gateways work together to pretend to be a single L2
> switch
> -with a large LACP bond.  In principle, it's the right solution to the
> problem
> -as it solves the broadcast storm problem, and has been deployed
> successfully in
> -other contexts.  That said, it's difficult to get right and not
> recommended.
> diff --git a/Documentation/topics/index.rst
> b/Documentation/topics/index.rst
> index 057649dd7..fcb741637 100644
> --- a/Documentation/topics/index.rst
> +++ b/Documentation/topics/index.rst
> @@ -27,7 +27,7 @@
>  Deep Dive
>  =========
>
> -How Open vSwitch and OVN are implemented and, where necessary, why it was
> +How Open vSwitch is implemented and, where necessary, why it was
>  implemented that way.
>
>  OVS
> @@ -52,19 +52,3 @@ OVS
>     tracing
>     idl-compound-indexes
>
> -OVN
> ----
> -
> -.. toctree::
> -   :maxdepth: 2
> -
> -   high-availability
> -   role-based-access-control
> -   ovn-news-2.8
> -
> -.. list-table::
> -
> -   * - ovn-architecture(7)
> -     - `(pdf) <
> http://openvswitch.org/support/dist-docs/ovn-architecture.7.pdf>`__
> -     - `(html) <
> http://openvswitch.org/support/dist-docs/ovn-architecture.7.html>`__
> -     - `(plain text) <
> http://openvswitch.org/support/dist-docs/ovn-architecture.7.txt>`__
> diff --git a/Documentation/topics/ovn-news-2.8.rst
> b/Documentation/topics/ovn-news-2.8.rst
> deleted file mode 100644
> index fae0a4278..000000000
> --- a/Documentation/topics/ovn-news-2.8.rst
> +++ /dev/null
> @@ -1,278 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -===============================
> -What's New with OVS and OVN 2.8
> -===============================
> -
> -This document is about what was added in Open vSwitch 2.8, which was
> released
> -at the end of August 2017, concentrating on the new features in OVN.  It
> also
> -covers some of what is coming up in Open vSwitch and OVN 2.9, which is
> due to
> -be released in February 2018.  OVN has many features, and this document
> does
> -not cover every new or enhanced feature (but contributions are welcome).
> -
> -This document assumes a basic familiarity with Open vSwitch, OVN, and
> their
> -associated tools.  For more information, please refer to the Open vSwitch
> and
> -OVN documentation, such as the ``ovn-architecture``\(7) manpage.
> -
> -Debugging and Troubleshooting
> ------------------------------
> -
> -Before version 2.8, Open vSwitch command-line tools were far more painful
> to
> -use than they needed to be.  This section covers the improvements made to
> the
> -CLI in the 2.8 release.
> -
> -User-Hostile UUIDs
> -~~~~~~~~~~~~~~~~~~
> -
> -The OVN CLI, through ``ovn-nbctl``, ``ovn-nbctl``, and ``ovn-trace``, used
> -full-length UUIDs almost everywhere.  It didn't even provide any
> assistance
> -with completion, etc., which in practice meant always cutting and pasting
> UUIDs
> -from one command or window to another.  This problem wasn't limited to the
> -places where one would expect to have to see or use a UUID, either.  In
> many
> -places where one would expect to be able to use a network, router, or port
> -name, a UUID was required instead.  In many places where one would want
> to see
> -a name, the UUID was displayed instead.  More than anything else, these
> -shortcomings made the CLI user-hostile.
> -
> -There was an underlying problem that the southbound database didn't
> actually
> -contain all the information needed to provide a decent user interface.
> In some
> -cases, for example, the human-friendly names that one would want to use
> for
> -entities simply weren't part of the database.  These names weren't
> necessary
> -for correctness, only for usability.
> -
> -OVN 2.8 eased many of these problems.  Most parts of the CLI now allow
> the user
> -to abbreviate UUIDs, as long as the abbreviations are unique within the
> -database.  Some parts of the CLI where full-length UUIDs make output hard
> to
> -read now abbreviate them themselves.  Perhaps more importantly, in many
> places
> -the OVN CLI now displays and accepts human-friendly names for networks,
> -routers, ports, and other entities.  In the places where the names were
> not
> -previously available, OVN (through ``ovn-northd``) now copies the names
> into
> -the southbound database.
> -
> -The CLIs for layers below OVN, at the OpenFlow and datapath layers with
> -``ovs-ofctl`` and ``ovs-dpctl``, respectively, had some similar problems
> in
> -which numbers were used for entities that had human-friendly names.  Open
> -vSwitch 2.8 also solves some of those problems.  Other than that, the most
> -notable enhancement in this area was the ``--no-stats`` option to
> ``ovs-ofctl
> -dump-flows``, which made that command's output more readable for the cases
> -where per-flow statistics were not interesting to the reader.
> -
> -Connections Between Levels
> -~~~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -OVN and Open vSwitch work almost like a stack of compilers: the OVN
> Neutron
> -plugin translates Neutron configuration into OVN northbound configuration,
> -which ``ovn-northd`` translates into logical flows, which
> ``ovn-controller``
> -translates into OpenFlow flows, which ``ovs-vswitchd`` translates into
> datapath
> -flows.  For debugging and troubleshooting it is often necessary to
> understand
> -exactly how these translations work.  The relationship from a logical
> flow to
> -its OpenFlow flows, or in the other direction, from an OpenFlow flow back
> to
> -the logical flow that produced it, was often of particular interest, but
> OVN
> -didn't provide good tools for the job.
> -
> -OVN 2.8 added some new features that ease these jobs.  ``ovn-sbctl
> lflow-list``
> -has a new option ``--ovs`` that lists the OpenFlow flows on a particular
> -chassis that were generated from the logical flows that it lists.
> -``ovn-trace`` also added a similar ``--ovs`` option that applies to the
> logical
> -flows it traces.
> -
> -In the other direction, OVN 2.8 added a new utility ``ovn-detrace`` that,
> given
> -an Open vSwitch trace of OpenFlow flows, annotates it with the logical
> flows
> -that yielded those OpenFlow flows.
> -
> -Distributed Firewall
> -~~~~~~~~~~~~~~~~~~~~
> -
> -OVN supports a distributed firewall with stateful connection tracking to
> ensure
> -that only packets for established connections, or those that the
> configuration
> -explicitly allows, can ingress a given VM or container.  Neutron uses this
> -feature by default.  Most packets in an OpenStack environment pass
> through it
> -twice, once after egress from the packet's source VM and once before
> ingress
> -into its destination VM.  Before OVN 2.8, the ``ovn-trace`` program, which
> -shows the path of a packet through an OVN logical network, did not
> support the
> -logical firewall, which in practice made it almost useless for Neutron.
> -
> -In OVN 2.8, ``ovn-trace`` adds support for the logical firewall.  By
> default it
> -assumes that packets are part of an established connection, which is
> usually
> -what the user wants as part of the trace.  It also accepts command-line
> options
> -to override that assumption, which allows the user to discover the
> treatment of
> -packets that the firewall should drop.
> -
> -At the next level deeper, prior to Open vSwitch 2.8, the OpenFlow tracing
> -command ``ofproto/trace`` also supported neither the connection tracking
> -feature underlying the OVN distributed firewall nor the "recirculation"
> feature
> -that accompanied it.  This meant that, even if the user tried to look
> deeper
> -into the distributed firewall mechanism, he or she would encounter a
> further
> -roadblock.  Open vSwitch 2.8 added support for both of these features as
> well.
> -
> -Summary Display
> -~~~~~~~~~~~~~~~
> -
> -``ovn-nbctl show`` and ``ovn-sbctl show``, for showing an overview of the
> OVN
> -configuration, didn't show a lot of important information.  OVN adds some
> more
> -useful information here.
> -
> -DNS, and IPAM
> --------------
> -
> -OVN 2.8 adds a built-in DNS server designed for assigning names to VMs and
> -containers within an OVN logical network.  DNS names are assigned using
> records
> -in the OVN northbound database and, like other OVN features, translated
> into
> -logical flows at the OVN southbound layer.  DNS requests directed to the
> OVN
> -DNS server never leave the hypervisor from which the request is sent;
> instead,
> -OVN processes and replies to the request from its ``ovn-controller`` local
> -agent.  The OVN DNS server is not a general-purpose DNS server and cannot
> be
> -used for that purpose.
> -
> -OVN includes simple built-in support for IP address management (IPAM), in
> which
> -OVN assigns IP addresses to VMs or containers from a pool or pools of IP
> -addresses delegated to it by the administrator.  Before OVN 2.8, OVN IPAM
> only
> -supported IPv4 addresses; OVN 2.8 adds support for IPv6.  OVN 2.8 also
> enhances
> -the address pool support to allow specific addresses to be excluded.
> Neutron
> -assigns IP addresses itself and does not use OVN IPAM.
> -
> -High Availability
> ------------------
> -
> -As a distributed system, in OVN a lot can go wrong.  As OVN advances, it
> adds
> -redundancy in places where currently a single failure could disrupt the
> -functioning of the system as a whole.  OVN 2.8 adds two new kinds of high
> -availability.
> -
> -ovn-northd HA
> -~~~~~~~~~~~~~
> -
> -The ``ovn-northd`` program sits between the OVN northbound and southbound
> -databases and translates from a logical network configuration into logical
> -flows.  If ``ovn-northd`` itself or the host on which it runs fails, then
> -updates to the OVN northbound configuration will not propagate to the
> -hypervisors and the OVN configuration freezes in place until
> ``ovn-northd``
> -restarts.
> -
> -OVN 2.8 adds support for active-backup HA to ``ovn-northd``.  When more
> than
> -one ``ovn-northd`` instance runs, it uses an OVSDB locking feature to
> -automatically choose a single active instance.  When that instance dies or
> -becomes nonresponsive, the OVSDB server automatically choose one of the
> -remaining instance(s) to take over.
> -
> -L3 Gateway HA
> -~~~~~~~~~~~~~
> -
> -In OVN 2.8, multiple chassis may now be specified for L3 gateways.  When
> more
> -than one chassis is specified, OVN manages high availability for that
> gateway.
> -Each hypervisor uses the BFD protocol to keep track of the gateway nodes
> that
> -are currently up.  At any given time, a hypervisor uses the
> highest-priority
> -gateway node that is currently up.
> -
> -OVSDB
> ------
> -
> -The OVN architecture relies heavily on OVSDB, the Open vSwitch database,
> for
> -hosting the northbound and southbound databases.  OVSDB was originally
> selected
> -for this purpose because it was already used in Open vSwitch for
> configuring
> -OVS itself and, thus, it was well integrated with OVS and well supported
> in C
> -and Python, the two languages that are used in Open vSwitch.
> -
> -OVSDB was well designed for its original purpose of configuring Open
> vSwitch.
> -It supports ACID transactions, has a small, efficient server, a flexible
> schema
> -system, and good support for troubleshooting and debugging.  However, it
> lacked
> -several features that are important for OVN but not for Open vSwitch.  As
> OVN
> -advances, these missing features have become more and more of a problem.
> One
> -option would be to switch to a different database that already has many of
> -these features, but despite a careful search, no ideal existing database
> was
> -identified, so the project chose instead to improve OVSDB where necessary
> to
> -bring it up to speed.  The following sections talk more about recent and
> future
> -improvements.
> -
> -High Availability
> -~~~~~~~~~~~~~~~~~
> -
> -When ``ovsdb-server`` was only used for OVS configuration, high
> availability
> -was not important.  ``ovsdb-server`` was capable of restarting itself
> -automatically if it crashed, and if the whole system went down then Open
> -vSwitch itself was dead too, so the database server's failure was not
> -important.
> -
> -In contrast, the northbound and southbound databases are centralized
> components
> -of a distributed system, so it is important that they not be a single
> point of
> -failure for the system as a whole.  In released versions of OVN,
> -``ovsdb-server`` supports only "active-backup replication" across a pair
> of
> -servers.  This means that if one server goes down, the other can pick it
> back
> -up approximately where the other one left off.  The servers do not have
> -built-in support for deciding at any given time which is the active and
> which
> -the backup, so the administrator must configure an external agent to do
> this
> -management.
> -
> -Active-backup replication is not entirely satisfactory, for multiple
> reasons.
> -Replication is only approximate.  Configuring the external agent requires
> extra
> -work.  There is no benefit from the backup server except when the active
> server
> -fails.  At most two servers can be used.
> -
> -A new form of high availability for OVSDB is under development for the
> OVN 2.9
> -release, based on the Raft algorithm for distributed consensus.  Whereas
> -replication uses two servers, clustering using Raft requires three or more
> -(typically an odd number) and continues functioning as long as more than
> half
> -of the servers are up.  The clustering implementation is built into
> -``ovsdb-server`` and does not require an external agent.  Clustering
> preserves
> -the ACID properties of the database, so that a transaction that commits is
> -guaranteed to persist.  Finally, reads (which are the bulk of the OVN
> workload)
> -scale with the size of the cluster, so that adding more servers should
> improve
> -performance as the number of hypervisors in an OVN deployment increases.
> As of
> -this writing, OVSDB support for clustering is undergoing development and
> early
> -deployment testing.
> -
> -RBAC security
> -~~~~~~~~~~~~~
> -
> -Until Open vSwitch 2.8, ``ovsdb-server`` had little support for access
> control
> -within a database.  If an OVSDB client could modify the database at all,
> it
> -could make arbitrary changes.  This was sufficient for most uses case to
> that
> -point.
> -
> -Hypervisors in an OVN deployment need access to the OVN southbound
> database.
> -Most of their access is reads, to find out about the OVN configuration.
> -Hypervisors do need some write access to the southbound database,
> primarily to
> -let the other hypervisors know what VMs and containers they are running
> and how
> -to reach them.  Thus, OVN gives all of the hypervisors in the OVN
> deployment
> -write access to the OVN southbound database.  This is fine when all is
> well,
> -but if any of the hypervisors were compromised then they could disrupt the
> -entire OVN deployment by corrupting the database.
> -
> -The OVN developers considered a few ways to solve this problem.  One way
> would
> -be to introduce a new central service (perhaps in ``ovn-northd``) that
> provided
> -only the kinds of writes that the hypervisors legitimately need, and then
> grant
> -hypervisors direct access to the southbound database only for reads.  But
> -ultimately the developers decided to introduce a new form of more access
> -control for OVSDB, called the OVSDB RBAC (role-based access control)
> feature.
> -OVSDB RBAC allows for granular enough control over access that
> hypervisors can
> -be granted only the ability to add, modify, and delete the records that
> relate
> -to themselves, preventing them from corrupting the database as a whole.
> -
> -Further Directions
> -------------------
> -
> -For more information about new features in OVN and Open vSwitch, please
> refer
> -to the NEWS file distributed with the source tree.  If you have questions
> about
> -Open vSwitch or OVN features, please feel free to write to the Open
> vSwitch
> -discussion mailing list at ovs-discuss@openvswitch.org.
> diff --git a/Documentation/topics/role-based-access-control.rst
> b/Documentation/topics/role-based-access-control.rst
> deleted file mode 100644
> index 8f2a3a998..000000000
> --- a/Documentation/topics/role-based-access-control.rst
> +++ /dev/null
> @@ -1,101 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -=========================
> -Role Based Access Control
> -=========================
> -
> -Where SSL provides authentication when connecting to an OVS database, role
> -based access control (RBAC) provides authorization to operations performed
> -by clients connecting to an OVS database. RBAC allows for administrators
> to
> -restrict the database operations a client may perform and thus enhance the
> -security already provided by SSL.
> -
> -In theory, any OVS database could define RBAC roles and permissions, but
> at
> -present only the OVN southbound database has the appropriate tables
> defined to
> -facilitate RBAC.
> -
> -Mechanics
> ----------
> -RBAC is intended to supplement SSL. In order to enable RBAC, the
> connection to
> -the database must use SSL. Some permissions in RBAC are granted based on
> the
> -certificate common name (CN) of the connecting client.
> -
> -RBAC is controlled with two database tables, RBAC_Role and
> RBAC_Permission.
> -The RBAC_Permission table contains records that describe a set of
> permissions
> -for a given table in the database.
> -
> -The RBAC_Permission table contains the following columns:
> -
> -table
> -  The table in the database for which permissions are being described.
> -insert_delete
> -  Describes whether insertion and deletion of records is allowed.
> -update
> -  A list of columns that are allowed to be updated.
> -authorization
> -  A list of column names. One of the listed columns must match the SSL
> -  certificate CN in order for the attempted operation on the table to
> -  succeed. If a key-value pair is provided, then the key is the column
> name,
> -  and the value is the name of a key in that column. An empty string gives
> -  permission to all clients to perform operations.
> -
> -The RBAC_Role table contains the following columns:
> -
> -name
> -  The name of the role being defined
> -permissions
> -  A list of key-value pairs. The key is the name of a table in the
> database,
> -  and the value is a UUID of a record in the RBAC_Permission table that
> -  describes the permissions the role has for that table.
> -
> -.. note::
> -
> -   All tables not explicitly referenced in an RBAC_Role record are
> read-only
> -
> -In order to enable RBAC, specify the role name as an argument to the
> -set-connection command for the database. As an example, to enable the
> -"ovn-controller" role on the OVN southbound database, use the following
> -command:
> -
> -::
> -
> -   $ ovn-sbctl set-connection role=ovn-controller ssl:192.168.0.1:6642
> -
> -Pre-defined Roles
> ------------------
> -This section describes roles that have been defined internally by OVS/OVN.
> -
> -ovn-controller
> -~~~~~~~~~~~~~~
> -The ovn-controller role is specified in the OVN southbound database and is
> -intended for use by hypervisors running the ovn-controller daemon.
> -ovn-controller connects to the OVN southbound database mostly to read
> -information, but there are a few cases where ovn-controller also needs to
> -write. The ovn-controller role was designed to allow for ovn-controllers
> -to write to the southbound database only in places where it makes sense
> to do
> -so. This way, if an intruder were to take over a hypervisor running
> -ovn-controller, it is more difficult to compromise the entire overlay
> network.
> -
> -It is strongly recommended to set the ovn-controller role for the OVN
> -southbound database to enhance security.
> diff --git a/Documentation/tutorials/index.rst
> b/Documentation/tutorials/index.rst
> index 35340ee56..5ec62beab 100644
> --- a/Documentation/tutorials/index.rst
> +++ b/Documentation/tutorials/index.rst
> @@ -27,8 +27,7 @@
>  Tutorials
>  =========
>
> -Getting started with Open vSwitch (OVS) and Open Virtual Network (OVN)
> for Open
> -vSwitch.
> +Getting started with Open vSwitch (OVS).
>
>  .. TODO(stephenfin): We could really do with a few basic tutorials, along
> with
>     some more specialized ones (DPDK, XenServer, Windows). The latter could
> @@ -42,8 +41,4 @@ vSwitch.
>     faucet
>     ipsec
>     ovs-advanced
> -   ovn-sandbox
> -   ovn-openstack
> -   ovn-rbac
> -   ovn-ipsec
>     ovs-conntrack
> diff --git a/Documentation/tutorials/ovn-ipsec.rst
> b/Documentation/tutorials/ovn-ipsec.rst
> deleted file mode 100644
> index feb695ea3..000000000
> --- a/Documentation/tutorials/ovn-ipsec.rst
> +++ /dev/null
> @@ -1,146 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -==================
> -OVN IPsec Tutorial
> -==================
> -
> -This document provides a step-by-step guide for encrypting tunnel traffic
> with
> -IPsec in Open Virtual Network (OVN). OVN tunnel traffic is transported by
> -physical routers and switches. These physical devices could be untrusted
> -(devices in public network) or might be compromised.  Enabling IPsec
> encryption
> -for the tunnel traffic can prevent the traffic data from being monitored
> and
> -manipulated. More details about the OVN IPsec design can be found in
> -``ovn-architecture``\(7) manpage.
> -
> -This document assumes OVN is installed in your system and runs normally.
> Also,
> -you need to install OVS IPsec packages in each chassis (refer to
> -:ref:`install-ovs-ipsec`).
> -
> -Generating Certificates and Keys
> ---------------------------------
> -
> -OVN chassis uses CA-signed certificate to authenticate peer chassis for
> -building IPsec tunnel. If you have enabled Role-Based Access Control
> (RBAC) in
> -OVN, you can use the RBAC SSL certificates and keys to set up OVN IPsec.
> Or you
> -can generate separate certificates and keys with ``ovs-pki`` (refer to
> -:ref:`gen-certs-keys`).
> -
> -.. note::
> -
> -   OVN IPsec requires x.509 version 3 certificate with the subjectAltName
> DNS
> -   field setting the same string as the common name (CN) field. CN should
> be
> -   set as the chassis name.  ``ovs-pki`` in Open vSwitch 2.10.90 and later
> -   generates such certificates.  Please generate compatible certificates
> if you
> -   use another PKI tool, or an older version of ``ovs-pki``, to manage
> -   certificates.
> -
> -Configuring OVN IPsec
> ----------------------
> -
> -You need to install the CA certificate, chassis certificate and private
> key in
> -each chassis. Use the following command::
> -
> -    $ ovs-vsctl set Open_vSwitch . \
> -            other_config:certificate=/path/to/chassis-cert.pem \
> -            other_config:private_key=/path/to/chassis-privkey.pem \
> -            other_config:ca_cert=/path/to/cacert.pem
> -
> -Enabling OVN IPsec
> -------------------
> -
> -To enable OVN IPsec, set ``ipsec`` column in ``NB_Global`` table of the
> -northbound database to true::
> -
> -    $ ovn-nbctl set nb_global . ipsec=true
> -
> -With OVN IPsec enabled, all tunnel traffic in OVN will be encrypted with
> IPsec.
> -To disable it, set ``ipsec`` column in ``NB_Global`` table of the
> northbound
> -database to false::
> -
> -    $ ovn-nbctl set nb_global . ipsec=false
> -
> -Troubleshooting
> ----------------
> -
> -The ``ovs-monitor-ipsec`` daemon in each chassis manages and monitors the
> IPsec
> -tunnel state. Use the following ``ovs-appctl`` command to view
> -``ovs-monitor-ipsec`` internal representation of tunnel configuration::
> -
> -    $ ovs-appctl -t ovs-monitor-ipsec tunnels/show
> -
> -If there is a misconfiguration, then ``ovs-appctl`` should indicate why.
> -For example::
> -
> -   Interface name: ovn-host_2-0 v1 (CONFIGURED) <--- Should be set
> -                                             to CONFIGURED. Otherwise,
> -                                             error message will be
> -                                             provided
> -   Tunnel Type:    geneve
> -   Remote IP:      2.2.2.2
> -   SKB mark:       None
> -   Local cert:     /path/to/chassis-cert.pem
> -   Local name:     host_1
> -   Local key:      /path/to/chassis-privkey.pem
> -   Remote cert:    None
> -   Remote name:    host_2
> -   CA cert:        /path/to/cacert.pem
> -   PSK:            None
> -   Ofport:         2          <--- Whether ovs-vswitchd has assigned
> Ofport
> -                                   number to this Tunnel Port
> -   CFM state:      Disabled     <--- Whether CFM declared this tunnel
> healthy
> -   Kernel policies installed:
> -   ...                          <--- IPsec policies for this OVS tunnel in
> -                                     Linux Kernel installed by strongSwan
> -   Kernel security associations installed:
> -   ...                          <--- IPsec security associations for this
> OVS
> -                                     tunnel in Linux Kernel installed by
> -                                     strongswan
> -   IPsec connections that are active:
> -   ...                          <--- IPsec "connections" for this OVS
> -                                     tunnel
> -
> -If you don't see any active connections, try to run the following command
> to
> -refresh the ``ovs-monitor-ipsec`` daemon::
> -
> -    $ ovs-appctl -t ovs-monitor-ipsec refresh
> -
> -You can also check the logs of the ``ovs-monitor-ipsec`` daemon and the
> IKE
> -daemon to locate issues.  ``ovs-monitor-ipsec`` outputs log messages to
> -``/var/log/openvswitch/ovs-monitor-ipsec.log``.
> -
> -Bug Reporting
> --------------
> -
> -If you think you may have found a bug with security implications, like
> -
> -1. IPsec protected tunnel accepted packets that came unencrypted; OR
> -2. IPsec protected tunnel allowed packets to leave unencrypted;
> -
> -Then report such bugs according to :doc:`/internals/security`.
> -
> -If bug does not have security implications, then report it according to
> -instructions in :doc:`/internals/bugs`.
> -
> -If you have suggestions to improve this tutorial, please send a email to
> -ovs-discuss@openvswitch.org.
> diff --git a/Documentation/tutorials/ovn-openstack.rst
> b/Documentation/tutorials/ovn-openstack.rst
> deleted file mode 100644
> index c6dff5e55..000000000
> --- a/Documentation/tutorials/ovn-openstack.rst
> +++ /dev/null
> @@ -1,1922 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -======================
> -OVN OpenStack Tutorial
> -======================
> -
> -This tutorial demonstrates how OVN works in an OpenStack "DevStack"
> -environment.  It was tested with the "master" branches of DevStack and
> -Open vSwitch near the beginning of May 2017.  Anyone using an earlier
> -version is likely to encounter some differences.  In particular, we
> -noticed some shortcomings in OVN utilities while writing the tutorial
> -and pushed out some improvements, so it's best to use recent Open
> -vSwitch at least from that point of view.
> -
> -The goal of this tutorial is to demonstrate OVN in an end-to-end way,
> -that is, to show how it works from the cloud management system at the
> -top (in this case, OpenStack and specifically its Neutron networking
> -subsystem), through the OVN northbound and southbound databases, to
> -the bottom at the OVN local controller and Open vSwitch data plane.
> -We hope that this demonstration makes it easier for users and
> -potential users to understand how OVN works and how to debug and
> -troubleshoot it.
> -
> -In addition to new material, this tutorial incorporates content from
> -``testing.rst`` in OpenStack networking-ovn, by Russell Bryant and
> -others.  Without that example, this tutorial could not have been
> -written.
> -
> -We provide enough details in the tutorial that you should be able to
> -fully follow along, by creating a DevStack VM and cloning DevStack and
> -so on.  If you want to do this, start out from `Setting Up DevStack`_
> -below.
> -
> -Setting Up DevStack
> --------------------
> -
> -This section explains how to install DevStack, a kind of OpenStack
> -packaging for developers, in a way that allows you to follow along
> -with the tutorial in full.
> -
> -Unless you have a spare computer laying about, it's easiest to install
> -DevStacck in a virtual machine.  This tutorial was built using a VM
> -implemented by KVM and managed by virt-manager.  I recommend
> -configuring the VM configured for the x86-64 architecture, 4 GB RAM, 2
> -VCPUs, and a 20 GB virtual disk.
> -
> -.. note::
> -
> -   If you happen to run your Linux-based host with 32-bit userspace,
> -   then you will have some special issues, even if you use a 64-bit
> -   kernel:
> -
> -   * You may find that you can get 32-bit DevStack VMs to work to some
> -     extent, but I personally got tired of finding workarounds.  I
> -     recommend running your VMs in 64-bit mode.  To get this to work,
> -     I had to go to the CPUs tab for the VM configuration in
> -     virt-manager and change the CPU model from the one originally
> -     listed to "Hypervisor Default' (it is curious that this is not
> -     the default!).
> -
> -   * On a host with 32-bit userspace, KVM supports VMs with at most
> -     2047 MB RAM.  This is adequate, barely, to start DevStack, but it
> -     is not enough to run multiple (nested) VMs.  To prevent
> -     out-of-memory failures, set up extra swap space in the guest.
> -     For example, to add 2 GB swap::
> -
> -       $ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
> -       $ sudo mkswap /swapfile
> -       $ sudo swapon /swapfile
> -
> -     and then add a line like this to ``/etc/fstab`` to add the new
> -     swap automatically upon reboot::
> -
> -       /swapfile swap swap defaults 0 0
> -
> -Here are step-by-step instructions to get started:
> -
> -1. Install a VM.
> -
> -   I tested these instructions with Centos 7.3.  Download the "minimal
> -   install" ISO and booted it.  The install is straightforward.  Be
> -   sure to enable networking, and set a host name, such as
> -   "ovn-devstack-1".  Add a regular (non-root) user, and check the box
> -   "Make this user administrator".  Also, set your time zone.
> -
> -2. You can SSH into the DevStack VM, instead of running from a
> -   console.  I recommend it because it's easier to cut and paste
> -   commands into a terminal than a VM console.  You might also
> -   consider using a very wide terminal, perhaps 160 columns, to keep
> -   tables from wrapping.
> -
> -   To improve convenience further, you can make it easier to log in
> -   with the following steps, which are optional:
> -
> -   a. On your host, edit your ``~/.ssh/config``, adding lines like
> -      the following::
> -
> -        Host ovn-devstack-1
> -              Hostname VMIP
> -              User VMUSER
> -
> -      where VMIP is the VM's IP address and VMUSER is your username
> -      inside the VM.  (You can omit the ``User`` line if your
> -      username is the same in the host and the VM.)  After you do
> -      this, you can SSH to the VM by name, e.g. ``ssh
> -      ovn-devstack-1``, and if command-line completion is set up in
> -      your host shell, you can shorten that to something like ``ssh
> -      ovn`` followed by hitting the Tab key.
> -
> -   b. If you have SSH public key authentication set up, with an SSH
> -      agent, run on your host::
> -
> -        $ ssh-copy-id ovn-devstack-1
> -
> -      and type your password once.  Afterward, you can log in without
> -      typing your password again.
> -
> -      (If you don't already use SSH public key authentication and an
> -      agent, consider looking into it--it will save you time in the
> -      long run.)
> -
> -   c. Optionally, inside the VM, append the following to your
> -      ``~/.bash_profile``::
> -
> -        . $HOME/devstack/openrc admin
> -
> -      It will save you running it by hand each time you log in.  But
> -      it also prints garbage to the console, which can screw up
> -      services like ``ssh-copy-id``, so be careful.
> -
> -2. Boot into the installed system and log in as the regular user, then
> -   install Git::
> -
> -     $ sudo yum install git
> -
> -   .. note::
> -
> -      If you installed a 32-bit i386 guest (against the advice above),
> -      install a non-PAE kernel and reboot into it at this point::
> -
> -           $ sudo yum install kernel-core kernel-devel
> -           $ sudo reboot
> -
> -      Be sure to select the non-PAE kernel from the list at boot.
> -      Without this step, DevStack will fail to install properly later.
> -
> -3. Get copies of DevStack and OVN and set them up::
> -
> -     $ git clone http://git.openstack.org/openstack-dev/devstack.git
> -     $ git clone http://git.openstack.org/openstack/networking-ovn.git
> -     $ cd devstack
> -     $ cp ../networking-ovn/devstack/local.conf.sample local.conf
> -
> -   .. note::
> -
> -      If you installed a 32-bit i386 guest (against the advice above),
> -      at this point edit ``local.conf`` to add the following line::
> -
> -        CIRROS_ARCH=i386
> -
> -4. Initialize DevStack::
> -
> -     $ ./stack.sh
> -
> -   This will spew many screenfuls of text, and the first time you run
> -   it, it will download lots of software from the Internet.  The
> -   output should eventually end with something like this::
> -
> -     This is your host IP address: 172.16.189.6
> -     This is your host IPv6 address: ::1
> -     Horizon is now available at http://172.16.189.6/dashboard
> -     Keystone is serving at http://172.16.189.6/identity/
> -     The default users are: admin and demo
> -     The password: password
> -     2017-03-09 15:10:54.117 | stack.sh completed in 2110 seconds.
> -
> -   If there's some kind of failure, you can restart by running
> -   ``./stack.sh`` again.  It won't restart exactly where it left off,
> -   but steps up to the one where it failed will skip the download
> -   steps.  (Sometimes blindly restarting after a failure will allow it
> -   to succeed.)  If you reboot your VM, you need to rerun this
> -   command.  (If you run into trouble with ``stack.sh`` after
> -   rebooting your VM, try running ``./unstack.sh``.)
> -
> -   At this point you can navigate a web browser on your host to the
> -   Horizon dashboard URL.  Many OpenStack operations can be initiated
> -   from this UI.  Feel free to explore, but this tutorial focuses on
> -   the alternative command-line interfaces because they are easier to
> -   explain and to cut and paste.
> -
> -5. As of this writing, you need to run the following to fix a problem
> -   with using VM consoles from the OpenStack web instance::
> -
> -     $ (cd /opt/stack/noVNC && git checkout v0.6.0)
> -
> -   See
> -
> https://serenity-networks.com/how-to-fix-setkeycodes-00-and-unknown-key-pressed-console-errors-on-openstack/
> -   for more details.
> -
> -6. The firewall in the VM by default allows SSH access but not HTTP.
> -   You will probably want HTTP access to use the OpenStack web
> -   interface.  The following command enables that.  (It also enables
> -   every other kind of network access, so if you're concerned about
> -   security then you might want to find a more targeted approach.)
> -
> -   ::
> -
> -      $ sudo iptables -F
> -
> -   (You need to re-run this if you reboot the VM.)
> -
> -7. To use OpenStack command line utilities in the tutorial, run::
> -
> -     $ . ~/devstack/openrc admin
> -
> -   This needs to be re-run each time you log in (but see the following
> -   section).
> -
> -DevStack preliminaries
> -----------------------
> -
> -Before we really jump in, let's set up a couple of things in DevStack.
> -This is the first real test that DevStack is working, so if you get
> -errors from any of these commands, it's a sign that ``stack.sh``
> -didn't finish properly, or perhaps that you didn't run the ``openrc
> -admin`` command at the end of the previous instructions.
> -
> -If you stop and restart DevStack via ``unstack.sh`` followed by
> -``stack.sh``, you have to rerun these steps.
> -
> -1. For SSH access to the VMs we're going to create, we'll need a SSH
> -   keypair.  Later on, we'll get OpenStack to install this keypair
> -   into VMs.  Create one with::
> -
> -     $ openstack keypair create demo > ~/id_rsa_demo
> -     $ chmod 600 ~/id_rsa_demo
> -
> -2. By default, DevStack security groups drop incoming traffic, but to
> -   test networking in a reasonable way we need to enable it.  You only
> -   need to actually edit one particular security group, but DevStack
> -   creates multiple and it's somewhat difficult to figure out which
> -   one is important because all of them are named "default".  So, the
> -   following adds rules to allow SSH and ICMP traffic into **every**
> -   security group::
> -
> -     $ for group in $(openstack security group list -f value -c ID); do \
> -     openstack security group rule create --ingress --ethertype IPv4
> --dst-port 22 --protocol tcp $group; \
> -     openstack security group rule create --ingress --ethertype IPv4
> --protocol ICMP $group; \
> -     done
> -
> -3. Later on, we're going to create some VMs and we'll need an
> -   operating system image to install.  DevStack comes with a very
> -   simple image built-in, called "cirros", which works fine.  We need
> -   to get the UUID for this image.  Our later commands assume shell
> -   variable ``IMAGE_ID`` holds this UUID.  You can set this by hand,
> -   e.g.::
> -
> -     $ openstack image list
> -
>  +--------------------------------------+--------------------------+--------+
> -     | ID                                   | Name                     |
> Status |
> -
>  +--------------------------------------+--------------------------+--------+
> -     | 77f37d2c-3d6b-4e99-a01b-1fa5d78d1fa1 | cirros-0.3.5-x86_64-disk |
> active |
> -
>  +--------------------------------------+--------------------------+--------+
> -     $ IMAGE_ID=73ca34f3-63c4-4c10-a62f-4540afc24eaa
> -
> -   or by parsing CLI output::
> -
> -     $ IMAGE_ID=$(openstack image list -f value -c ID)
> -
> -   .. note::
> -
> -      Your image ID will differ from the one above, as will every UUID
> -      in this tutorial.  They will also change every time you run
> -      ``stack.sh``.  The UUIDs are generated randomly.
> -
> -Shortening UUIDs
> -----------------
> -
> -OpenStack, OVN, and Open vSwitch all really like UUIDs.  These are
> -great for uniqueness, but 36-character strings are terrible for
> -readability.  Statistically, just the first few characters are enough
> -for uniqueness in small environments, so let's define a helper to make
> -things more readable::
> -
> -  $ abbrev() { a='[0-9a-fA-F]' b=$a$a c=$b$b; sed
> "s/$b-$c-$c-$c-$c$c$c//g"; }
> -
> -You can use this as a filter to abbreviate UUIDs.  For example, use it
> -to abbreviate the above image list::
> -
> -  $ openstack image list -f yaml | abbrev
> -  - ID: 77f37d
> -    Name: cirros-0.3.5-x86_64-disk
> -    Status: active
> -
> -The command above also adds ``-f yaml`` to switch to YAML output
> -format, because abbreviating UUIDs screws up the default table-based
> -formatting and because YAML output doesn't produce wrap columns across
> -lines and therefore is easier to cut and paste.
> -
> -Overview
> ---------
> -
> -Now that DevStack is ready, with OVN set up as the networking
> -back-end, here's an overview of what we're going to do in the
> -remainder of the demo, all via OpenStack:
> -
> -1. Switching: Create an OpenStack network ``n1`` and VMs ``a`` and
> -   ``b`` attached to it.
> -
> -   An OpenStack network is a virtual switch; it corresponds to an OVN
> -   logical switch.
> -
> -2. Routing: Create a second OpenStack network ``n2`` and VM ``c``
> -   attached to it, then connect it to network ``n1`` by creating an
> -   OpenStack router and attaching ``n1`` and ``n2`` to it.
> -
> -3. Gateways: Make VMs ``a`` and ``b`` available via an external network.
> -
> -4. IPv6: Add IPv6 addresses to our VMs to demonstrate OVN support for
> -   IPv6 routing.
> -
> -5. ACLs: Add and modify OpenStack stateless and stateful rules in
> -   security groups.
> -
> -6. DHCP: How it works in OVN.
> -
> -7. Further directions: Adding more compute nodes.
> -
> -At each step, we will take a look at how the features in question work
> -from OpenStack's Neutron networking layer at the top to the data plane
> -layer at the bottom.  From the highest to lowest level, these layers
> -and the software components that connect them are:
> -
> -* OpenStack Neutron, which as the top level in the system is the
> -  authoritative source of the virtual network configuration.
> -
> -  We will use OpenStack's ``openstack`` utility to observe and modify
> -  Neutron and other OpenStack configuration.
> -
> -* networking-ovn, the Neutron driver that interfaces with OVN and
> -  translates the internal Neutron representation of the virtual
> -  network into OVN's representation and pushes that representation
> -  down the OVN northbound database.
> -
> -  In this tutorial it's rarely worth distinguishing Neutron from
> -  networking-ovn, so we usually don't break out this layer separately.
> -
> -* The OVN Northbound database, aka NB DB.  This is an instance of
> -  OVSDB, a simple general-purpose database that is used for multiple
> -  purposes in Open vSwitch and OVN.  The NB DB's schema is in terms of
> -  networking concepts such as switches and routers.  The NB DB serves
> -  the purpose that in other systems might be filled by some kind of
> -  API; for example, in place of calling an API to create or delete a
> -  logical switch, networking-ovn performs these operations by
> -  inserting or deleting a row in the NB DB's Logical_Switch table.
> -
> -  We will use OVN's ``ovn-nbctl`` utility to observe the NB DB.  (We
> -  won't directly modify data at this layer or below.  Because
> -  configuration trickles down from Neutron through the stack, the
> -  right way to make changes is to use the ``openstack`` utility or
> -  another OpenStack interface and then wait for them to percolate
> -  through to lower layers.)
> -
> -* The ovn-northd daemon, a program that runs centrally and translates
> -  the NB DB's network representation into the lower-level
> -  representation used by the OVN Southbound database in the next
> -  layer.  The details of this daemon are usually not of interest,
> -  although without it OVN will not work, so this tutorial does not
> -  often mention it.
> -
> -* The OVN Southbound database, aka SB DB, which is also an OVSDB
> -  database.  Its schema is very different from the NB DB.  Instead of
> -  familiar networking concepts, the SB DB defines the network in terms
> -  of collections of match-action rules called "logical flows", which
> -  while similar in concept to OpenFlow flows use logical concepts, such
> -  as virtual machine instances, in place of physical concepts like
> -  physical Ethernet ports.
> -
> -  We will use OVN's ``ovn-sbctl`` utility to observe the SB DB.
> -
> -* The ovn-controller daemon.  A copy of ovn-controller runs on each
> -  hypervisor.  It reads logical flows from the SB DB, translates them
> -  into OpenFlow flows, and sends them to Open vSwitch's ovs-vswitchd
> -  daemon.  Like ovn-northd, usually the details of what this daemon
> -  are not of interest, even though it's important to the operation of
> -  the system.
> -
> -* ovs-vswitchd.  This program runs on each hypervisor.  It is the core
> -  of Open vSwitch, which processes packets according to the OpenFlow
> -  flows set up by ovn-controller.
> -
> -* Open vSwitch datapath.  This is essentially a cache designed to
> -  accelerate packet processing.  Open vSwitch includes a few different
> -  datapaths but OVN installations typically use one based on the Open
> -  vSwitch Linux kernel module.
> -
> -Switching
> ----------
> -
> -Switching is the basis of networking in the real world and in virtual
> -networking as well.  OpenStack calls its concept of a virtual switch a
> -"network", and OVN calls its corresponding concept a "logical switch".
> -
> -In this step, we'll create an OpenStack network ``n1``, then create
> -VMs ``a`` and ``b`` and attach them to ``n1``.
> -
> -Creating network ``n1``
> -~~~~~~~~~~~~~~~~~~~~~~~
> -
> -Let's start by creating the network::
> -
> -  $ openstack network create --project admin --provider-network-type
> geneve n1
> -
> -OpenStack needs to know the subnets that a network serves.  We inform
> -it by creating subnet objects.  To keep it simple, let's give our
> -network a single subnet for the 10.1.1.0/24 network.  We have to give
> -it a name, in this case ``n1subnet``::
> -
> -  $ openstack subnet create --subnet-range 10.1.1.0/24 --network n1
> n1subnet
> -
> -If you ask Neutron to show us the available networks, we see ``n1`` as
> -well as the two networks that DevStack creates by default::
> -
> -  $ openstack network list -f yaml | abbrev
> -  - ID: 5b6baf
> -    Name: n1
> -    Subnets: 5e67e7
> -  - ID: c02c4d
> -    Name: private
> -    Subnets: d88a34, fd87f9
> -  - ID: d1ac28
> -    Name: public
> -    Subnets: 0b1e79, c87dc1
> -
> -Neutron pushes this network setup down to the OVN northbound
> -database.  We can use ``ovn-nbctl show`` to see an overview of what's
> -in the NB DB::
> -
> -  $ ovn-nbctl show | abbrev
> -  switch 5b3d5f (neutron-c02c4d) (aka private)
> -      port b256dd
> -          type: router
> -          router-port: lrp-b256dd
> -      port f264e7
> -          type: router
> -          router-port: lrp-f264e7
> -  switch 2579f4 (neutron-d1ac28) (aka public)
> -      port provnet-d1ac28
> -          type: localnet
> -          addresses: ["unknown"]
> -      port ae9b52
> -          type: router
> -          router-port: lrp-ae9b52
> -  switch 3eb263 (neutron-5b6baf) (aka n1)
> -  router c59ad2 (neutron-9b057f) (aka router1)
> -      port lrp-ae9b52
> -          mac: "fa:16:3e:b2:d2:67"
> -          networks: ["172.24.4.9/24", "2001:db8::b/64"]
> -      port lrp-b256dd
> -          mac: "fa:16:3e:35:33:db"
> -          networks: ["fdb0:5860:4ba8::1/64"]
> -      port lrp-f264e7
> -          mac: "fa:16:3e:fc:c8:da"
> -          networks: ["10.0.0.1/26"]
> -      nat 80914c
> -          external ip: "172.24.4.9"
> -          logical ip: "10.0.0.0/26"
> -          type: "snat"
> -
> -This output shows that OVN has three logical switches, each of which
> -corresponds to a Neutron network, and a logical router that
> -corresponds to the Neutron router that DevStack creates by default.
> -The logical switch that corresponds to our new network ``n1`` has no
> -ports yet, because we haven't added any.  The ``public`` and
> -``private`` networks that DevStack creates by default have router
> -ports that connect to the logical router.
> -
> -Using ovn-northd, OVN translates the NB DB's high-level switch and
> -router concepts into lower-level concepts of "logical datapaths" and
> -logical flows.  There's one logical datapath for each logical switch
> -or router::
> -
> -  $ ovn-sbctl list datapath_binding | abbrev
> -  _uuid               : 0ad69d
> -  external_ids        : {logical-switch="5b3d5f", name="neutron-c02c4d",
> "name2"=private}
> -  tunnel_key          : 1
> -
> -  _uuid               : a8a758
> -  external_ids        : {logical-switch="3eb263", name="neutron-5b6baf",
> "name2"="n1"}
> -  tunnel_key          : 4
> -
> -  _uuid               : 191256
> -  external_ids        : {logical-switch="2579f4", name="neutron-d1ac28",
> "name2"=public}
> -  tunnel_key          : 3
> -
> -  _uuid               : b87bec
> -  external_ids        : {logical-router="c59ad2", name="neutron-9b057f",
> "name2"="router1"}
> -  tunnel_key          : 2
> -
> -This output lists the NB DB UUIDs in external_ids:logical-switch and
> -Neutron UUIDs in externals_ids:uuid.  We can dive in deeper by viewing
> -the OVN logical flows that implement a logical switch.  Our new
> -logical switch is a simple and almost pathological example given that
> -it doesn't yet have any ports attached to it.  We'll look at the
> -details a bit later::
> -
> -  $ ovn-sbctl lflow-list n1 | abbrev
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: ingress
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]),
> action=(drop;)
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present),
> action=(drop;)
> -  ...
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: egress
> -    table=0 (ls_out_pre_lb      ), priority=0    , match=(1),
> action=(next;)
> -    table=1 (ls_out_pre_acl     ), priority=0    , match=(1),
> action=(next;)
> -  ...
> -
> -We have one hypervisor (aka "compute node", in OpenStack parlance),
> -which is the one where we're running all these commands.  On this
> -hypervisor, ovn-controller is translating OVN logical flows into
> -OpenFlow flows ("physical flows").  It makes sense to go deeper, to
> -see the OpenFlow flows that get generated from this datapath.  By
> -adding ``--ovs`` to the ``ovn-sbctl`` command, we can see OpenFlow
> -flows listed just below their logical flows.  We also need to use
> -``sudo`` because connecting to Open vSwitch is privileged.  Go ahead
> -and try it::
> -
> -  $ sudo ovn-sbctl --ovs lflow-list n1 | abbrev
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: ingress
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]),
> action=(drop;)
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present),
> action=(drop;)
> -  ...
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: egress
> -    table=0 (ls_out_pre_lb      ), priority=0    , match=(1),
> action=(next;)
> -    table=1 (ls_out_pre_acl     ), priority=0    , match=(1),
> action=(next;)
> -  ...
> -
> -You were probably disappointed: the output didn't change, and no
> -OpenFlow flows were printed.  That's because no OpenFlow flows are
> -installed for this logical datapath, which in turn is because there
> -are no VIFs for this logical datapath on the local hypervisor.  For a
> -better example, you can try ``ovn-sbctl --ovs`` on one of the other
> -logical datapaths.
> -
> -Attaching VMs
> -~~~~~~~~~~~~~
> -
> -A switch without any ports is not very interesting.  Let's create a
> -couple of VMs and attach them to the switch.  Run the following
> -commands, which create VMs named ``a`` and ``b`` and attaches them to
> -our network ``n1`` with IP addresses 10.1.1.5 and 10.1.1.6,
> -respectively.  It is not actually necessary to manually assign IP
> -address assignments, since OpenStack is perfectly happy to assign them
> -itself from the subnet's IP address range, but predictable addresses
> -are useful for our discussion::
> -
> -  $ openstack server create --nic net-id=n1,v4-fixed-ip=10.1.1.5 --flavor
> m1.nano --image $IMAGE_ID --key-name demo a
> -  $ openstack server create --nic net-id=n1,v4-fixed-ip=10.1.1.6 --flavor
> m1.nano --image $IMAGE_ID --key-name demo b
> -
> -These commands return before the VMs are really finished being built.
> -You can run ``openstack server list`` a few times until each of them
> -is shown in the state ACTIVE, which means that they're not just built
> -but already running on the local hypervisor.
> -
> -These operations had the side effect of creating separate "port"
> -objects, but without giving those ports any easy-to-read names.  It'll
> -be easier to deal with them later if we can refer to them by name, so
> -let's name ``a``'s port ``ap`` and ``b``'s port ``bp``::
> -
> -  $ openstack port set --name ap $(openstack port list --server a -f
> value -c ID)
> -  $ openstack port set --name bp $(openstack port list --server b -f
> value -c ID)
> -
> -We'll need to refer to these ports' MAC addresses a few times, so
> -let's put them in variables::
> -
> -  $ AP_MAC=$(openstack port show -f value -c mac_address ap)
> -  $ BP_MAC=$(openstack port show -f value -c mac_address bp)
> -
> -At this point you can log into the consoles of the VMs if you like.
> -You can do that from the OpenStack web interface or get a direct URL
> -to paste into a web browser using a command like::
> -
> -  $ openstack console url show -f yaml a
> -
> -(The option ``-f yaml`` keeps the URL in the output from being broken
> -into noncontiguous pieces on a 80-column console.)
> -
> -The VMs don't have many tools in them but ``ping`` and ``ssh`` from
> -one to the other should work fine.  The VMs do not have any external
> -network access or DNS configuration.
> -
> -Let's chase down what's changed in OVN.  Start with the NB DB at the
> -top of the system.  It's clear that our logical switch now has the two
> -logical ports attached to it::
> -
> -  $ ovn-nbctl show | abbrev
> -  ...
> -  switch 3eb263 (neutron-5b6baf) (aka n1)
> -      port c29d41 (aka bp)
> -          addresses: ["fa:16:3e:99:7a:17 10.1.1.6"]
> -      port 820c08 (aka ap)
> -          addresses: ["fa:16:3e:a9:4c:c7 10.1.1.5"]
> -  ...
> -
> -We can get some more details on each of these by looking at their NB
> -DB records in the Logical_Switch_Port table.  Each port has addressing
> -information, port security enabled, and a pointer to DHCP
> -configuration (which we'll look at much later in `DHCP`_)::
> -
> -  $ ovn-nbctl list logical_switch_port ap bp | abbrev
> -  _uuid               : ef17e5
> -  addresses           : ["fa:16:3e:a9:4c:c7 10.1.1.5"]
> -  dhcpv4_options      : 165974
> -  dhcpv6_options      : []
> -  dynamic_addresses   : []
> -  enabled             : true
> -  external_ids        : {"neutron:port_name"=ap}
> -  name                : "820c08"
> -  options             : {}
> -  parent_name         : []
> -  port_security       : ["fa:16:3e:a9:4c:c7 10.1.1.5"]
> -  tag                 : []
> -  tag_request         : []
> -  type                : ""
> -  up                  : true
> -
> -  _uuid               : e8af12
> -  addresses           : ["fa:16:3e:99:7a:17 10.1.1.6"]
> -  dhcpv4_options      : 165974
> -  dhcpv6_options      : []
> -  dynamic_addresses   : []
> -  enabled             : true
> -  external_ids        : {"neutron:port_name"=bp}
> -  name                : "c29d41"
> -  options             : {}
> -  parent_name         : []
> -  port_security       : ["fa:16:3e:99:7a:17 10.1.1.6"]
> -  tag                 : []
> -  tag_request         : []
> -  type                : ""
> -  up                  : true
> -
> -Now that the logical switch is less pathological, it's worth taking
> -another look at the SB DB logical flow table.  Try a command like
> -this::
> -
> -  $ ovn-sbctl lflow-list n1 | abbrev | less -S
> -
> -and then glance through the flows.  Packets that egress a VM into the
> -logical switch travel through the flow table's ingress pipeline
> -starting from table 0.  At each table, the switch finds the
> -highest-priority logical flow that matches and executes its actions,
> -or if there's no matching flow then the packet is dropped.  The
> -``ovn-sb``\(5) manpage gives all the details, but with a little
> -thought it's possible to guess a lot without reading the manpage.  For
> -example, consider the flows in ingress pipeline table 0, which are the
> -first flows encountered by a packet traversing the switch::
> -
> -  table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]),
> action=(drop;)
> -  table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present),
> action=(drop;)
> -  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport ==
> "820c08" && eth.src == {fa:16:3e:a9:4c:c7}), action=(next;)
> -  table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport ==
> "c29d41" && eth.src == {fa:16:3e:99:7a:17}), action=(next;)
> -
> -The first two flows, with priority 100, immediately drop two kinds of
> -invalid packets: those with a multicast or broadcast Ethernet source
> -address (since multicast is only for packet destinations) and those
> -with a VLAN tag (because OVN doesn't yet support VLAN tags inside
> -logical networks).  The next two flows implement L2 port security:
> -they advance to the next table for packets with the correct Ethernet
> -source addresses for their ingress ports.  A packet that does not
> -match any flow is implicitly dropped, so there's no need for flows to
> -deal with mismatches.
> -
> -The logical flow table includes many other flows, some of which we
> -will look at later.  For now, it's most worth looking at ingress table
> -13::
> -
> -  table=13(ls_in_l2_lkup      ), priority=100  , match=(eth.mcast),
> action=(outport = "_MC_flood"; output;)
> -  table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> fa:16:3e:99:7a:17), action=(outport = "c29d41"; output;)
> -  table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> fa:16:3e:a9:4c:c7), action=(outport = "820c08"; output;)
> -
> -The first flow in table 13 checks whether the packet is an Ethernet
> -multicast or broadcast and, if so, outputs it to a special port that
> -egresses to every logical port (other than the ingress port).
> -Otherwise the packet is output to the port corresponding to its
> -Ethernet destination address.  Packets addressed to any other Ethernet
> -destination are implicitly dropped.
> -
> -(It's common for an OVN logical switch to know all the MAC addresses
> -supported by its logical ports, like this one.  That's why there's no
> -logic here for MAC learning or flooding packets to unknown MAC
> -addresses.  OVN does support unknown MAC handling but that's not in
> -play in our example.)
> -
> -.. note::
> -
> -  If you're interested in the details for the multicast group, you can
> -  run a command like the following and then look at the row for the
> -  correct datapath::
> -
> -    $ ovn-sbctl find multicast_group name=_MC_flood | abbrev
> -
> -Now if you want to look at the OpenFlow flows, you can actually see
> -them.  For example, here's the beginning of the output that lists the
> -first four logical flows, which we already looked at above, and their
> -corresponding OpenFlow flows.  If you want to know more about the
> -syntax, the ``ovs-fields``\(7) manpage explains OpenFlow matches and
> -``ovs-ofctl``\(8) explains OpenFlow actions::
> -
> -  $ sudo ovn-sbctl --ovs lflow-list n1 | abbrev
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: ingress
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]),
> action=(drop;)
> -      table=8 metadata=0x4,dl_src=01:00:00:00:00:00/01:00:00:00:00:00
> actions=drop
> -    table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present),
> action=(drop;)
> -      table=8 metadata=0x4,vlan_tci=0x1000/0x1000 actions=drop
> -    table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport ==
> "820c08" && eth.src == {fa:16:3e:a9:4c:c7}), action=(next;)
> -      table=8 reg14=0x1,metadata=0x4,dl_src=fa:16:3e:a9:4c:c7
> actions=resubmit(,9)
> -    table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport ==
> "c29d41" && eth.src == {fa:16:3e:99:7a:17}), action=(next;)
> -      table=8 reg14=0x2,metadata=0x4,dl_src=fa:16:3e:99:7a:17
> actions=resubmit(,9)
> -  ...
> -
> -Logical Tracing
> -+++++++++++++++
> -
> -Let's go a level deeper.  So far, everything we've done has been
> -fairly general.  We can also look at something more specific: the path
> -that a particular packet would take through OVN, logically, and Open
> -vSwitch, physically.
> -
> -Let's use OVN's ovn-trace utility to see what happens to packets from
> -a logical point of view.  The ``ovn-trace``\(8) manpage has a lot of
> -detail on how to do that, but let's just start by building up from a
> -simple example.  You can start with a command that just specifies the
> -logical datapath, an input port, and nothing else; unspecified fields
> -default to all-zeros.  This doesn't do much::
> -
> -  $ ovn-trace n1 'inport == "ap"'
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2: no match (implicit drop)
> -
> -We see that the packet was dropped in logical table 0,
> -"ls_in_port_sec_l2", the L2 port security stage (as we discussed
> -earlier).  That's because we didn't use the right Ethernet source
> -address for ``a``.  Let's see what happens if we do::
> -
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src ==
> {fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
> -      next;
> -  13. ls_in_l2_lkup: no match (implicit drop)
> -
> -Now the packet passes through L2 port security and skips through
> -several other tables until it gets dropped in the L2 lookup stage
> -(because the destination is unknown).  Let's add the Ethernet
> -destination for ``b``::
> -
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC' && eth.dst ==
> '$BP_MAC
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src ==
> {fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:99:7a:17,
> priority 50, uuid 57a4c46f
> -      outport = "bp";
> -      output;
> -
> -  egress(dp="n1", inport="ap", outport="bp")
> -  ------------------------------------------
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "bp" && eth.dst
> == {fa:16:3e:99:7a:17}, priority 50, uuid 8aa6426d
> -      output;
> -      /* output to "bp", type "" */
> -
> -You can see that in this case the packet gets properly switched from
> -``a`` to ``b``.
> -
> -Physical Tracing for Hypothetical Packets
> -+++++++++++++++++++++++++++++++++++++++++
> -
> -ovn-trace showed us how a hypothetical packet would travel through the
> -system in a logical fashion, that is, without regard to how VMs are
> -distributed across the physical network.  This is a convenient
> -representation for understanding how OVN is **supposed** to work
> -abstractly, but sometimes we might want to know more about how it
> -actually works in the real systems where it is running.  For this, we
> -can use the tracing tool that Open vSwitch provides, which traces
> -a hypothetical packet through the OpenFlow tables.
> -
> -We can actually get two levels of detail.  Let's start with the
> -version that's easier to interpret, by physically tracing a packet
> -that looks like the one we logically traced before.  One obstacle is
> -that we need to know the OpenFlow port number of the input port.  One
> -way to do that is to look for a port whose "attached-mac" is the one
> -we expect and print its ofport number::
> -
> -  $ AP_PORT=$(ovs-vsctl --bare --columns=ofport find  interface
> external-ids:attached-mac=\"$AP_MAC\")
> -  $ echo $AP_PORT
> -  3
> -
> -(You could also just do a plain ``ovs-vsctl list interface`` and then
> -look through for the right row and pick its ``ofport`` value.)
> -
> -Now we can feed this input port number into ``ovs-appctl
> -ofproto/trace`` along with the correct Ethernet source and
> -destination addresses and get a physical trace::
> -
> -  $ sudo ovs-appctl ofproto/trace br-int
> in_port=$AP_PORT,dl_src=$AP_MAC,dl_dst=$BP_MAC
> -  Flow:
> in_port=3,vlan_tci=0x0000,dl_src=fa:16:3e:a9:4c:c7,dl_dst=fa:16:3e:99:7a:17,dl_type=0x0000
> -
> -  bridge("br-int")
> -  ----------------
> -   0. in_port=3, priority 100
> -      set_field:0x8->reg13
> -      set_field:0x9->reg11
> -      set_field:0xa->reg12
> -      set_field:0x4->metadata
> -      set_field:0x1->reg14
> -      resubmit(,8)
> -   8. reg14=0x1,metadata=0x4,dl_src=fa:16:3e:a9:4c:c7, priority 50,
> cookie 0x6dcc418a
> -      resubmit(,9)
> -   9. metadata=0x4, priority 0, cookie 0x8fe8689e
> -      resubmit(,10)
> -  10. metadata=0x4, priority 0, cookie 0x719549d1
> -      resubmit(,11)
> -  11. metadata=0x4, priority 0, cookie 0x39c99e6f
> -      resubmit(,12)
> -  12. metadata=0x4, priority 0, cookie 0x838152a3
> -      resubmit(,13)
> -  13. metadata=0x4, priority 0, cookie 0x918259e3
> -      resubmit(,14)
> -  14. metadata=0x4, priority 0, cookie 0xcad14db2
> -      resubmit(,15)
> -  15. metadata=0x4, priority 0, cookie 0x7834d912
> -      resubmit(,16)
> -  16. metadata=0x4, priority 0, cookie 0x87745210
> -      resubmit(,17)
> -  17. metadata=0x4, priority 0, cookie 0x34951929
> -      resubmit(,18)
> -  18. metadata=0x4, priority 0, cookie 0xd7a8c9fb
> -      resubmit(,19)
> -  19. metadata=0x4, priority 0, cookie 0xd02e9578
> -      resubmit(,20)
> -  20. metadata=0x4, priority 0, cookie 0x42d35507
> -      resubmit(,21)
> -  21. metadata=0x4,dl_dst=fa:16:3e:99:7a:17, priority 50, cookie
> 0x57a4c46f
> -      set_field:0x2->reg15
> -      resubmit(,32)
> -  32. priority 0
> -      resubmit(,33)
> -  33. reg15=0x2,metadata=0x4, priority 100
> -      set_field:0xb->reg13
> -      set_field:0x9->reg11
> -      set_field:0xa->reg12
> -      resubmit(,34)
> -  34. priority 0
> -      set_field:0->reg0
> -      set_field:0->reg1
> -      set_field:0->reg2
> -      set_field:0->reg3
> -      set_field:0->reg4
> -      set_field:0->reg5
> -      set_field:0->reg6
> -      set_field:0->reg7
> -      set_field:0->reg8
> -      set_field:0->reg9
> -      resubmit(,40)
> -  40. metadata=0x4, priority 0, cookie 0xde9f3899
> -      resubmit(,41)
> -  41. metadata=0x4, priority 0, cookie 0x74074eff
> -      resubmit(,42)
> -  42. metadata=0x4, priority 0, cookie 0x7789c8b1
> -      resubmit(,43)
> -  43. metadata=0x4, priority 0, cookie 0xa6b002c0
> -      resubmit(,44)
> -  44. metadata=0x4, priority 0, cookie 0xaeab2b45
> -      resubmit(,45)
> -  45. metadata=0x4, priority 0, cookie 0x290cc4d4
> -      resubmit(,46)
> -  46. metadata=0x4, priority 0, cookie 0xa3223b88
> -      resubmit(,47)
> -  47. metadata=0x4, priority 0, cookie 0x7ac2132e
> -      resubmit(,48)
> -  48. reg15=0x2,metadata=0x4,dl_dst=fa:16:3e:99:7a:17, priority 50,
> cookie 0x8aa6426d
> -      resubmit(,64)
> -  64. priority 0
> -      resubmit(,65)
> -  65. reg15=0x2,metadata=0x4, priority 100
> -      output:4
> -
> -  Final flow:
> reg11=0x9,reg12=0xa,reg13=0xb,reg14=0x1,reg15=0x2,metadata=0x4,in_port=3,vlan_tci=0x0000,dl_src=fa:16:3e:a9:4c:c7,dl_dst=fa:16:3e:99:7a:17,dl_type=0x0000
> -  Megaflow:
> recirc_id=0,ct_state=-new-est-rel-rpl-inv-trk,ct_label=0/0x1,in_port=3,vlan_tci=0x0000/0x1000,dl_src=fa:16:3e:a9:4c:c7,dl_dst=fa:16:3e:99:7a:17,dl_type=0x0000
> -  Datapath actions: 4
> -
> -There's a lot there, which you can read through if you like, but the
> -important part is::
> -
> -  65. reg15=0x2,metadata=0x4, priority 100
> -      output:4
> -
> -which means that the packet is ultimately being output to OpenFlow
> -port 4.  That's port ``b``, which you can confirm with::
> -
> -  $ sudo ovs-vsctl find interface ofport=4
> -  _uuid               : 840a5aca-ea8d-4c16-a11b-a94e0f408091
> -  admin_state         : up
> -  bfd                 : {}
> -  bfd_status          : {}
> -  cfm_fault           : []
> -  cfm_fault_status    : []
> -  cfm_flap_count      : []
> -  cfm_health          : []
> -  cfm_mpid            : []
> -  cfm_remote_mpids    : []
> -  cfm_remote_opstate  : []
> -  duplex              : full
> -  error               : []
> -  external_ids        : {attached-mac="fa:16:3e:99:7a:17",
> iface-id="c29d4120-20a4-4c44-bd83-8d91f5f447fd", iface-status=active,
> vm-id="2db969ca-ca2a-4d9a-b49e-f287d39c5645"}
> -  ifindex             : 9
> -  ingress_policing_burst: 0
> -  ingress_policing_rate: 0
> -  lacp_current        : []
> -  link_resets         : 1
> -  link_speed          : 10000000
> -  link_state          : up
> -  lldp                : {}
> -  mac                 : []
> -  mac_in_use          : "fe:16:3e:99:7a:17"
> -  mtu                 : 1500
> -  mtu_request         : []
> -  name                : "tapc29d4120-20"
> -  ofport              : 4
> -  ofport_request      : []
> -  options             : {}
> -  other_config        : {}
> -  statistics          : {collisions=0, rx_bytes=4254, rx_crc_err=0,
> rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=39,
> tx_bytes=4188, tx_dropped=0, tx_errors=0, tx_packets=39}
> -  status              : {driver_name=tun, driver_version="1.6",
> firmware_version=""}
> -  type                : ""
> -
> -or::
> -
> -  $ BP_PORT=$(ovs-vsctl --bare --columns=ofport find  interface
> external-ids:attached-mac=\"$BP_MAC\")
> -  $ echo $BP_PORT
> -  4
> -
> -Physical Tracing for Real Packets
> -+++++++++++++++++++++++++++++++++
> -
> -In the previous sections we traced a hypothetical L2 packet, one
> -that's honestly not very realistic: we didn't even supply an Ethernet
> -type, so it defaulted to zero, which isn't anything one would see on a
> -real network.  We could refine our packet so that it becomes a more
> -realistic TCP or UDP or ICMP, etc. packet, but let's try a different
> -approach: working from a real packet.
> -
> -Pull up a console for VM ``a`` and start ``ping 10.1.1.6``, then leave
> -it running for the rest of our experiment.
> -
> -Now go back to your DevStack session and run::
> -
> -  $ sudo watch ovs-dpctl dump-flows
> -
> -We're working with a new program.  ovn-dpctl is an interface to Open
> -vSwitch datapaths, in this case to the Linux kernel datapath.  Its
> -``dump-flows`` command displays the contents of the in-kernel flow
> -cache, and by running it under the ``watch`` program we see a new
> -snapshot of the flow table every 2 seconds.
> -
> -Look through the output for a flow that begins with ``recirc_id(0)``
> -and matches the Ethernet source address for ``a``.  There is one flow
> -per line, but the lines are very long, so it's easier to read if you
> -make the window very wide.  This flow's packet counter should be
> -increasing at a rate of 1 packet per second.  It looks something like
> -this::
> -
> -
> recirc_id(0),in_port(3),eth(src=fa:16:3e:f5:2a:90),eth_type(0x0800),ipv4(src=10.1.1.5,frag=no),
> packets:388, bytes:38024, used:0.977s, actions:ct(zone=8),recirc(0x18)
> -
> -We can hand the first part of this (everything up to the first space)
> -to ``ofproto/trace``, and it will tell us what happens::
> -
> -  $ sudo ovs-appctl ofproto/trace
> 'recirc_id(0),in_port(3),eth(src=fa:16:3e:a9:4c:c7),eth_type(0x0800),ipv4(src=10.1.1.5,dst=
> 10.1.0.0/255.255.0.0,frag=no)'
> -  Flow:
> ip,in_port=3,vlan_tci=0x0000,dl_src=fa:16:3e:a9:4c:c7,dl_dst=00:00:00:00:00:00,nw_src=10.1.1.5,nw_dst=10.1.0.0,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=0
> -
> -  bridge("br-int")
> -  ----------------
> -   0. in_port=3, priority 100
> -      set_field:0x8->reg13
> -      set_field:0x9->reg11
> -      set_field:0xa->reg12
> -      set_field:0x4->metadata
> -      set_field:0x1->reg14
> -      resubmit(,8)
> -   8. reg14=0x1,metadata=0x4,dl_src=fa:16:3e:a9:4c:c7, priority 50,
> cookie 0x6dcc418a
> -      resubmit(,9)
> -   9. ip,reg14=0x1,metadata=0x4,dl_src=fa:16:3e:a9:4c:c7,nw_src=10.1.1.5,
> priority 90, cookie 0x343af48c
> -      resubmit(,10)
> -  10. metadata=0x4, priority 0, cookie 0x719549d1
> -      resubmit(,11)
> -  11. ip,metadata=0x4, priority 100, cookie 0x46c089e6
> -      load:0x1->NXM_NX_XXREG0[96]
> -      resubmit(,12)
> -  12. metadata=0x4, priority 0, cookie 0x838152a3
> -      resubmit(,13)
> -  13. ip,reg0=0x1/0x1,metadata=0x4, priority 100, cookie 0xd1941634
> -      ct(table=22,zone=NXM_NX_REG13[0..15])
> -      drop
> -
> -  Final flow:
> ip,reg0=0x1,reg11=0x9,reg12=0xa,reg13=0x8,reg14=0x1,metadata=0x4,in_port=3,vlan_tci=0x0000,dl_src=fa:16:3e:a9:4c:c7,dl_dst=00:00:00:00:00:00,nw_src=10.1.1.5,nw_dst=10.1.0.0,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=0
> -  Megaflow:
> recirc_id=0,ip,in_port=3,vlan_tci=0x0000/0x1000,dl_src=fa:16:3e:a9:4c:c7,nw_src=10.1.1.5,nw_dst=
> 10.1.0.0/16,nw_frag=no
> -  Datapath actions: ct(zone=8),recirc(0xb)
> -
> -.. note::
> -   Be careful cutting and pasting ``ovs-dpctl dump-flows`` output into
> -   ``ofproto/trace`` because the latter has terrible error reporting.
> -   If you add an extra line break, etc., it will likely give you a
> -   useless error message.
> -
> -There's no ``output`` action in the output, but there are ``ct`` and
> -``recirc`` actions (which you can see in the ``Datapath actions`` at
> -the end).  The ``ct`` action tells the kernel to pass the packet
> -through the kernel connection tracking for firewalling purposes and
> -the ``recirc`` says to go back to the flow cache for another pass
> -based on the firewall results.  The ``0xb`` value inside the
> -``recirc`` gives us a hint to look at the kernel flows for a cached
> -flow with ``recirc_id(0xb)``.  Indeed, there is one::
> -
> -
> recirc_id(0xb),in_port(3),ct_state(-new+est-rel-rpl-inv+trk),ct_label(0/0x1),eth(src=fa:16:3e:a9:4c:c7,dst=fa:16:3e:99:7a:17),eth_type(0x0800),ipv4(dst=
> 10.1.1.4/255.255.255.252,frag=no), packets:171, bytes:16758, used:0.271s,
> actions:ct(zone=11),recirc(0xc)
> -
> -We can then repeat our command with the match part of this kernel
> -flow::
> -
> -  $ sudo ovs-appctl ofproto/trace
> 'recirc_id(0xb),in_port(3),ct_state(-new+est-rel-rpl-inv+trk),ct_label(0/0x1),eth(src=fa:16:3e:a9:4c:c7,dst=fa:16:3e:99:7a:17),eth_type(0x0800),ipv4(dst=
> 10.1.1.4/255.255.255.252,frag=no)'
> -  ...
> -  Datapath actions: ct(zone=11),recirc(0xc)
> -
> -In other words, the flow passes through the connection tracker a
> -second time.  The first time was for ``a``'s outgoing firewall; this
> -second time is for ``b``'s incoming firewall.  Again, we continue
> -tracing with ``recirc_id(0xc)``::
> -
> -  $ sudo ovs-appctl ofproto/trace
> 'recirc_id(0xc),in_port(3),ct_state(-new+est-rel-rpl-inv+trk),ct_label(0/0x1),eth(src=fa:16:3e:a9:4c:c7,dst=fa:16:3e:99:7a:17),eth_type(0x0800),ipv4(dst=10.1.1.6,proto=1,frag=no)'
> -  ...
> -  Datapath actions: 4
> -
> -It was took multiple hops, but we finally came to the end of the line
> -where the packet was output to ``b`` after passing through both
> -firewalls.  The port number here is a datapath port number, which is
> -usually different from an OpenFlow port number.  To check that it is
> -``b``'s port, we first list the datapath ports to get the name
> -corresponding to the port number::
> -
> -  $ sudo ovs-dpctl show
> -  system@ovs-system:
> -          lookups: hit:1994 missed:56 lost:0
> -          flows: 6
> -          masks: hit:2340 total:4 hit/pkt:1.14
> -          port 0: ovs-system (internal)
> -          port 1: br-int (internal)
> -          port 2: br-ex (internal)
> -          port 3: tap820c0888-13
> -          port 4: tapc29d4120-20
> -
> -and then confirm that this is the port we think it is with a command
> -like this::
> -
> -  $ ovs-vsctl --columns=external-ids list interface tapc29d4120-20
> -  external_ids        : {attached-mac="fa:16:3e:99:7a:17",
> iface-id="c29d4120-20a4-4c44-bd83-8d91f5f447fd", iface-status=active,
> vm-id="2db969ca-ca2a-4d9a-b49e-f287d39c5645"}
> -
> -Finally, we can relate the OpenFlow flows from our traces back to OVN
> -logical flows.  For individual flows, cut and paste a "cookie" value
> -from ``ofproto/trace`` output into ``ovn-sbctl lflow-list``, e.g.::
> -
> -  $ ovn-sbctl lflow-list 0x6dcc418a|abbrev
> -  Datapath: "neutron-5b6baf" aka "n1" (a8a758)  Pipeline: ingress
> -    table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport ==
> "820c08" && eth.src == {fa:16:3e:a9:4c:c7}), action=(next;)
> -
> -Or, you can pipe ``ofproto/trace`` output through ``ovn-detrace`` to
> -annotate every flow::
> -
> -  $ sudo ovs-appctl ofproto/trace
> 'recirc_id(0xc),in_port(3),ct_state(-new+est-rel-rpl-inv+trk),ct_label(0/0x1),eth(src=fa:16:3e:a9:4c:c7,dst=fa:16:3e:99:7a:17),eth_type(0x0800),ipv4(dst=10.1.1.6,proto=1,frag=no)'
> | ovn-detrace
> -  ...
> -
> -Routing
> --------
> -
> -Previously we set up a pair of VMs ``a`` and ``b`` on a network ``n1``
> -and demonstrated how packets make their way between them.  In this
> -step, we'll set up a second network ``n2`` with a new VM ``c``,
> -connect a router ``r`` to both networks, and demonstrate how routing
> -works in OVN.
> -
> -There's nothing really new for the network and the VM so let's just go
> -ahead and create them::
> -
> -  $ openstack network create --project admin --provider-network-type
> geneve n2
> -  $ openstack subnet create --subnet-range 10.1.2.0/24 --network n2
> n2subnet
> -  $ openstack server create --nic net-id=n2,v4-fixed-ip=10.1.2.7 --flavor
> m1.nano --image $IMAGE_ID --key-name demo c
> -  $ openstack port set --name cp $(openstack port list --server c -f
> value -c ID)
> -  $ CP_MAC=$(openstack port show -f value -c mac_address cp)
> -
> -The new network ``n2`` is not yet connected to ``n1`` in any way.  You
> -can try tracing a broadcast packet from ``a`` to see, for example,
> -that it doesn't make it to ``c``::
> -
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC' && eth.dst ==
> '$CP_MAC
> -  ...
> -
> -Now create an OpenStack router and connect it to ``n1`` and ``n2``::
> -
> -  $ openstack router create r
> -  $ openstack router add subnet r n1subnet
> -  $ openstack router add subnet r n2subnet
> -
> -Now ``a``, ``b``, and ``c`` should all be able to reach other.  You
> -can get some verification that routing is taking place by running you
> -``ping`` between ``c`` and one of the other VMs: the reported TTL
> -should be one less than between ``a`` and ``b`` (63 instead of 64).
> -
> -Observe via ``ovn-nbctl`` the new OVN logical switch and router and
> -then ports that connect them together::
> -
> -  $ ovn-nbctl show|abbrev
> -  ...
> -  switch f51234 (neutron-332346) (aka n2)
> -      port 82b983
> -          type: router
> -          router-port: lrp-82b983
> -      port 2e585f (aka cp)
> -          addresses: ["fa:16:3e:89:f2:36 10.1.2.7"]
> -  switch 3eb263 (neutron-5b6baf) (aka n1)
> -      port c29d41 (aka bp)
> -          addresses: ["fa:16:3e:99:7a:17 10.1.1.6"]
> -      port 820c08 (aka ap)
> -          addresses: ["fa:16:3e:a9:4c:c7 10.1.1.5"]
> -      port 17d870
> -          type: router
> -          router-port: lrp-17d870
> -  ...
> -  router dde06c (neutron-f88ebc) (aka r)
> -      port lrp-82b983
> -          mac: "fa:16:3e:19:9f:46"
> -          networks: ["10.1.2.1/24"]
> -      port lrp-17d870
> -          mac: "fa:16:3e:f6:e2:8f"
> -          networks: ["10.1.1.1/24"]
> -
> -We have not yet looked at the logical flows for an OVN logical router.
> -You might find it of interest to look at them on your own::
> -
> -  $ ovn-sbctl lflow-list r | abbrev | less -S
> -  ...
> -
> -Let's grab the ``n1subnet`` router porter MAC address to simplify
> -later commands::
> -
> -  $ N1SUBNET_MAC=$(ovn-nbctl --bare --columns=mac find
> logical_router_port networks=10.1.1.1/24)
> -
> -Let's see what happens at the logical flow level for an ICMP packet
> -from ``a`` to ``c``.  This generates a long trace but an interesting
> -one, so we'll look at it bit by bit.  The first three stanzas in the
> -output show the packet's ingress into ``n1`` and processing through
> -the firewall on that side (via the "ct_next" connection-tracking
> -action), and then the selection of the port that leads to router ``r``
> -as the output port::
> -
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC' && eth.dst ==
> '$N1SUBNET_MAC' && ip4.src == 10.1.1.5 && ip4.dst == 10.1.2.7 && ip.ttl ==
> 64 && icmp4.type == 8'
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src ==
> {fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
> -      next;
> -   1. ls_in_port_sec_ip (ovn-northd.c:2364): inport == "ap" && eth.src ==
> fa:16:3e:a9:4c:c7 && ip4.src == {10.1.1.5}, priority 90, uuid 343af48c
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2646): ip, priority 100, uuid 46c089e6
> -      reg0[0] = 1;
> -      next;
> -   5. ls_in_pre_stateful (ovn-northd.c:2764): reg0[0] == 1, priority 100,
> uuid d1941634
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   6. ls_in_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (inport == "ap" && ip4), priority 2002, uuid
> a12b39f0
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:f6:e2:8f,
> priority 50, uuid c43ead31
> -      outport = "17d870";
> -      output;
> -
> -  egress(dp="n1", inport="ap", outport="17d870")
> -  ----------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2626): ip && outport == "17d870",
> priority 110, uuid 60395450
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "17d870",
> priority 50, uuid 91b5cab0
> -      output;
> -      /* output to "17d870", type "patch" */
> -
> -The next two stanzas represent processing through logical router
> -``r``.  The processing in table 5 is the core of the routing
> -implementation: it recognizes that the packet is destined for an
> -attached subnet, decrements the TTL and updates the Ethernet source
> -address.  Table 6 then selects the Ethernet destination address based
> -on the IP destination.  The packet then passes to switch ``n2`` via an
> -OVN "logical patch port"::
> -
> -  ingress(dp="r", inport="lrp-17d870")
> -  ------------------------------------
> -   0. lr_in_admission (ovn-northd.c:4071): eth.dst == fa:16:3e:f6:e2:8f
> && inport == "lrp-17d870", priority 50, uuid fa5270b0
> -      next;
> -   5. lr_in_ip_routing (ovn-northd.c:3782): ip4.dst == 10.1.2.0/24,
> priority 49, uuid 5f9d469f
> -      ip.ttl--;
> -      reg0 = ip4.dst;
> -      reg1 = 10.1.2.1;
> -      eth.src = fa:16:3e:19:9f:46;
> -      outport = "lrp-82b983";
> -      flags.loopback = 1;
> -      next;
> -   6. lr_in_arp_resolve (ovn-northd.c:5088): outport == "lrp-82b983" &&
> reg0 == 10.1.2.7, priority 100, uuid 03d506d3
> -      eth.dst = fa:16:3e:89:f2:36;
> -      next;
> -   8. lr_in_arp_request (ovn-northd.c:5260): 1, priority 0, uuid 6dacdd82
> -      output;
> -
> -  egress(dp="r", inport="lrp-17d870", outport="lrp-82b983")
> -  ---------------------------------------------------------
> -   3. lr_out_delivery (ovn-northd.c:5288): outport == "lrp-82b983",
> priority 100, uuid 00bea4f2
> -      output;
> -      /* output to "lrp-82b983", type "patch" */
> -
> -Finally the logical switch for ``n2`` runs through the same logic as
> -``n1`` and the packet is delivered to VM ``c``::
> -
> -  ingress(dp="n2", inport="82b983")
> -  ---------------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "82b983", priority
> 50, uuid 9a789e06
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2624): ip && inport == "82b983",
> priority 110, uuid ab52f21a
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:89:f2:36,
> priority 50, uuid dcafb3e9
> -      outport = "cp";
> -      output;
> -
> -  egress(dp="n2", inport="82b983", outport="cp")
> -  ----------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2648): ip, priority 100, uuid cd9cfa74
> -      reg0[0] = 1;
> -      next;
> -   2. ls_out_pre_stateful (ovn-northd.c:2766): reg0[0] == 1, priority
> 100, uuid 9e8e22c5
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   4. ls_out_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (outport == "cp" && ip4 && ip4.src ==
> $as_ip4_0fc1b6cf_f925_49e6_8f00_6dd13beca9dc), priority 2002, uuid a746fa0d
> -      next;
> -   7. ls_out_port_sec_ip (ovn-northd.c:2364): outport == "cp" && eth.dst
> == fa:16:3e:89:f2:36 && ip4.dst == {255.255.255.255, 224.0.0.0/4,
> 10.1.2.7}, priority 90, uuid 4d9862b5
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "cp" && eth.dst
> == {fa:16:3e:89:f2:36}, priority 50, uuid 0242cdc3
> -      output;
> -      /* output to "cp", type "" */
> -
> -Physical Tracing
> -~~~~~~~~~~~~~~~~
> -
> -It's possible to use ``ofproto/trace``, just as before, to trace a
> -packet through OpenFlow tables, either for a hypothetical packet or
> -one that you get from a real test case using ``ovs-dpctl``.  The
> -process is just the same as before and the output is almost the same,
> -too.  Using a router doesn't actually introduce any interesting new
> -wrinkles, so we'll skip over this for this case and for the remainder
> -of the tutorial, but you can follow the steps on your own if you like.
> -
> -Adding a Gateway
> -----------------
> -
> -The VMs that we've created can access each other but they are isolated
> -from the physical world.  In OpenStack, the dominant way to connect a
> -VM to external networks is by creating what is called a "floating IP
> -address", which uses network address translation to connect an
> -external address to an internal one.
> -
> -DevStack created a pair of networks named "private" and "public".  To
> -use a floating IP address from a VM, we first add a port to the VM
> -with an IP address from the "private" network, then we create a
> -floating IP address on the "public" network, then we associate the
> -port with the floating IP address.
> -
> -Let's add a new VM ``d`` with a floating IP::
> -
> -  $ openstack server create --nic net-id=private --flavor m1.nano --image
> $IMAGE_ID --key-name demo d
> -  $ openstack port set --name dp $(openstack port list --server d -f
> value -c ID)
> -  $ DP_MAC=$(openstack port show -f value -c mac_address dp)
> -  $ openstack floating ip create --floating-ip-address 172.24.4.8 public
> -  $ openstack server add floating ip d 172.24.4.8
> -
> -(We specified a particular floating IP address to make the examples
> -easier to follow, but without that OpenStack will automatically
> -allocate one.)
> -
> -It's also necessary to configure the "public" network because DevStack
> -does not do it automatically::
> -
> -  $ sudo ip link set br-ex up
> -  $ sudo ip route add 172.24.4.0/24 dev br-ex
> -  $ sudo ip addr add 172.24.4.1/24 dev br-ex
> -
> -Now you should be able to "ping" VM ``d`` from the OpenStack host::
> -
> -  $ ping 172.24.4.8
> -  PING 172.24.4.8 (172.24.4.8) 56(84) bytes of data.
> -  64 bytes from 172.24.4.8: icmp_seq=1 ttl=63 time=56.0 ms
> -  64 bytes from 172.24.4.8: icmp_seq=2 ttl=63 time=1.44 ms
> -  64 bytes from 172.24.4.8: icmp_seq=3 ttl=63 time=1.04 ms
> -  64 bytes from 172.24.4.8: icmp_seq=4 ttl=63 time=0.403 ms
> -  ^C
> -  --- 172.24.4.8 ping statistics ---
> -  4 packets transmitted, 4 received, 0% packet loss, time 3003ms
> -  rtt min/avg/max/mdev = 0.403/14.731/56.028/23.845 ms
> -
> -You can also SSH in with the key that we created during setup::
> -
> -  $ ssh -i ~/id_rsa_demo cirros@172.24.4.8
> -
> -Let's dive in and see how this gets implemented in OVN.  First, the
> -relevant parts of the NB DB for the "public" and "private" networks
> -and the router between them::
> -
> -  $ ovn-nbctl show | abbrev
> -  switch 2579f4 (neutron-d1ac28) (aka public)
> -      port provnet-d1ac28
> -          type: localnet
> -          addresses: ["unknown"]
> -      port ae9b52
> -          type: router
> -          router-port: lrp-ae9b52
> -  switch 5b3d5f (neutron-c02c4d) (aka private)
> -      port b256dd
> -          type: router
> -          router-port: lrp-b256dd
> -      port f264e7
> -          type: router
> -          router-port: lrp-f264e7
> -      port cae25b (aka dp)
> -          addresses: ["fa:16:3e:c1:f5:a2 10.0.0.6
> fdb0:5860:4ba8:0:f816:3eff:fec1:f5a2"]
> -  ...
> -  router c59ad2 (neutron-9b057f) (aka router1)
> -      port lrp-ae9b52
> -          mac: "fa:16:3e:b2:d2:67"
> -          networks: ["172.24.4.9/24", "2001:db8::b/64"]
> -      port lrp-b256dd
> -          mac: "fa:16:3e:35:33:db"
> -          networks: ["fdb0:5860:4ba8::1/64"]
> -      port lrp-f264e7
> -          mac: "fa:16:3e:fc:c8:da"
> -          networks: ["10.0.0.1/26"]
> -      nat 788c6d
> -          external ip: "172.24.4.8"
> -          logical ip: "10.0.0.6"
> -          type: "dnat_and_snat"
> -      nat 80914c
> -          external ip: "172.24.4.9"
> -          logical ip: "10.0.0.0/26"
> -          type: "snat"
> -  ...
> -
> -What we see is:
> -
> -* VM ``d`` is on the "private" switch under its private IP address
> -  10.0.0.8.  The "private" switch is connected to "router1" via two
> -  router ports (one for IPv4, one for IPv6).
> -
> -* The "public" switch is connected to "router1" and to the physical
> -  network via a "localnet" port.
> -
> -* "router1" is in the middle between "private" and "public".  In
> -  addition to the router ports that connect to these switches, it has
> -  "nat" entries that direct network address translation.  The
> -  translation between floating IP address 172.24.4.8 and private
> -  address 10.0.0.8 makes perfect sense.
> -
> -When the NB DB gets translated into logical flows at the southbound
> -layer, the "nat" entries get translated into IP matches that then
> -invoke "ct_snat" and "ct_dnat" actions.  The details are intricate,
> -but you can get some of the idea by just looking for relevant flows::
> -
> -  $ ovn-sbctl lflow-list router1 | abbrev | grep nat | grep -E
> '172.24.4.8|10.0.0.8'
> -    table=3 (lr_in_unsnat       ), priority=100  , match=(ip && ip4.dst
> == 172.24.4.8 && inport == "lrp-ae9b52" &&
> is_chassis_resident("cr-lrp-ae9b52")), action=(ct_snat;)
> -    table=3 (lr_in_unsnat       ), priority=50   , match=(ip && ip4.dst
> == 172.24.4.8), action=(reg9[0] = 1; next;)
> -    table=4 (lr_in_dnat         ), priority=100  , match=(ip && ip4.dst
> == 172.24.4.8 && inport == "lrp-ae9b52" &&
> is_chassis_resident("cr-lrp-ae9b52")), action=(ct_dnat(10.0.0.6);)
> -    table=4 (lr_in_dnat         ), priority=50   , match=(ip && ip4.dst
> == 172.24.4.8), action=(reg9[0] = 1; next;)
> -    table=1 (lr_out_snat        ), priority=33   , match=(ip && ip4.src
> == 10.0.0.6 && outport == "lrp-ae9b52" &&
> is_chassis_resident("cr-lrp-ae9b52")), action=(ct_snat(172.24.4.8);)
> -
> -Let's take a look at how a packet passes through this whole gauntlet.
> -The first two stanzas just show the packet traveling through the
> -"public" network and being forwarded to the "router1" network::
> -
> -  $ ovn-trace public 'inport ==
> "provnet-d1ac2896-18a7-4bca-8f46-b21e2370e5b1" && eth.src ==
> 00:01:02:03:04:05 && eth.dst == fa:16:3e:b2:d2:67 && ip4.src == 172.24.4.1
> && ip4.dst == 172.24.4.8 && ip.ttl == 64 && icmp4.type==8'
> -  ...
> -  ingress(dp="public", inport="provnet-d1ac28")
> -  ---------------------------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "provnet-d1ac28",
> priority 50, uuid 8d86fb06
> -      next;
> -  10. ls_in_arp_rsp (ovn-northd.c:3266): inport == "provnet-d1ac28",
> priority 100, uuid 21313eff
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3571): eth.dst == fa:16:3e:b2:d2:67 &&
> is_chassis_resident("cr-lrp-ae9b52"), priority 50, uuid 7f28f51f
> -      outport = "ae9b52";
> -      output;
> -
> -  egress(dp="public", inport="provnet-d1ac28", outport="ae9b52")
> -  --------------------------------------------------------------
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "ae9b52",
> priority 50, uuid 72fea396
> -      output;
> -      /* output to "ae9b52", type "patch" */
> -
> -In "router1", first the ``ct_snat`` action without an argument
> -attempts to "un-SNAT" the packet.  ovn-trace treats this as a no-op,
> -because it doesn't have any state for tracking connections.  As an
> -alternative, it invokes ``ct_dnat(10.0.0.8)`` to NAT the destination
> -IP::
> -
> -  ingress(dp="router1", inport="lrp-ae9b52")
> -  ------------------------------------------
> -   0. lr_in_admission (ovn-northd.c:4071): eth.dst == fa:16:3e:b2:d2:67
> && inport == "lrp-ae9b52" && is_chassis_resident("cr-lrp-ae9b52"), priority
> 50, uuid 8c6945c2
> -      next;
> -   3. lr_in_unsnat (ovn-northd.c:4591): ip && ip4.dst == 172.24.4.8 &&
> inport == "lrp-ae9b52" && is_chassis_resident("cr-lrp-ae9b52"), priority
> 100, uuid e922f541
> -      ct_snat;
> -
> -  ct_snat /* assuming no un-snat entry, so no change */
> -  -----------------------------------------------------
> -   4. lr_in_dnat (ovn-northd.c:4649): ip && ip4.dst == 172.24.4.8 &&
> inport == "lrp-ae9b52" && is_chassis_resident("cr-lrp-ae9b52"), priority
> 100, uuid 02f41b79
> -      ct_dnat(10.0.0.6);
> -
> -Still in "router1", the routing and output steps transmit the packet
> -to the "private" network::
> -
> -  ct_dnat(ip4.dst=10.0.0.6)
> -  -------------------------
> -   5. lr_in_ip_routing (ovn-northd.c:3782): ip4.dst == 10.0.0.0/26,
> priority 53, uuid 86e005b0
> -      ip.ttl--;
> -      reg0 = ip4.dst;
> -      reg1 = 10.0.0.1;
> -      eth.src = fa:16:3e:fc:c8:da;
> -      outport = "lrp-f264e7";
> -      flags.loopback = 1;
> -      next;
> -   6. lr_in_arp_resolve (ovn-northd.c:5088): outport == "lrp-f264e7" &&
> reg0 == 10.0.0.6, priority 100, uuid 2963d67c
> -      eth.dst = fa:16:3e:c1:f5:a2;
> -      next;
> -   8. lr_in_arp_request (ovn-northd.c:5260): 1, priority 0, uuid eea419b7
> -      output;
> -
> -  egress(dp="router1", inport="lrp-ae9b52", outport="lrp-f264e7")
> -  ---------------------------------------------------------------
> -   3. lr_out_delivery (ovn-northd.c:5288): outport == "lrp-f264e7",
> priority 100, uuid 42dadc23
> -      output;
> -      /* output to "lrp-f264e7", type "patch" */
> -
> -In the "private" network, the packet passes through VM ``d``'s
> -firewall and is output to ``d``::
> -
> -  ingress(dp="private", inport="f264e7")
> -  --------------------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "f264e7", priority
> 50, uuid 5b721214
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2624): ip && inport == "f264e7",
> priority 110, uuid 5bdc3209
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:c1:f5:a2,
> priority 50, uuid 7957f80f
> -      outport = "dp";
> -      output;
> -
> -  egress(dp="private", inport="f264e7", outport="dp")
> -  ---------------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2648): ip, priority 100, uuid 4981c79d
> -      reg0[0] = 1;
> -      next;
> -   2. ls_out_pre_stateful (ovn-northd.c:2766): reg0[0] == 1, priority
> 100, uuid 247e02eb
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   4. ls_out_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (outport == "dp" && ip4 && ip4.src == 0.0.0.0/0
> && icmp4), priority 2002, uuid b860fc9f
> -      next;
> -   7. ls_out_port_sec_ip (ovn-northd.c:2364): outport == "dp" && eth.dst
> == fa:16:3e:c1:f5:a2 && ip4.dst == {255.255.255.255, 224.0.0.0/4,
> 10.0.0.6}, priority 90, uuid 15655a98
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "dp" && eth.dst
> == {fa:16:3e:c1:f5:a2}, priority 50, uuid 5916f94b
> -      output;
> -      /* output to "dp", type "" */
> -
> -IPv6
> -----
> -
> -OVN supports IPv6 logical routing.  Let's try it out.
> -
> -The first step is to add an IPv6 subnet to networks ``n1`` and ``n2``,
> -then attach those subnets to our router ``r``.  As usual, though
> -OpenStack can assign addresses itself, we use fixed ones to make the
> -discussion easier::
> -
> -  $ openstack subnet create --ip-version 6 --subnet-range fc11::/64
> --network n1 n1subnet6
> -  $ openstack subnet create --ip-version 6 --subnet-range fc22::/64
> --network n2 n2subnet6
> -  $ openstack router add subnet r n1subnet6
> -  $ openstack router add subnet r n2subnet6
> -
> -Then we add an IPv6 address to each of our VMs::
> -
> -  $ A_PORT_ID=$(openstack port list --server a -f value -c ID)
> -  $ openstack port set --fixed-ip subnet=n1subnet6,ip-address=fc11::5
> $A_PORT_ID
> -  $ B_PORT_ID=$(openstack port list --server b -f value -c ID)
> -  $ openstack port set --fixed-ip subnet=n1subnet6,ip-address=fc11::6
> $B_PORT_ID
> -  $ C_PORT_ID=$(openstack port list --server c -f value -c ID)
> -  $ openstack port set --fixed-ip subnet=n2subnet6,ip-address=fc22::7
> $C_PORT_ID
> -
> -At least for me, the new IPv6 addresses didn't automatically get
> -propagated into the VMs.  To do it by hand, pull up the console for
> -``a`` and run::
> -
> -  $ sudo ip addr add fc11::5/64 dev eth0
> -  $ sudo ip route add via fc11::1
> -
> -Then in ``b``::
> -
> -  $ sudo ip addr add fc11::6/64 dev eth0
> -  $ sudo ip route add via fc11::1
> -
> -Finally in ``c``::
> -
> -  $ sudo ip addr add fc22::7/64 dev eth0
> -  $ sudo ip route add via fc22::1
> -
> -Now you should have working IPv6 routing through router ``r``.  The
> -relevant parts of the NB DB look like the following.  The interesting
> -parts are the new ``fc11::`` and ``fc22::`` addresses on the ports in
> -``n1`` and ``n2`` and the new IPv6 router ports in ``r``::
> -
> -  $ ovn-nbctl show | abbrev
> -  ...
> -  switch f51234 (neutron-332346) (aka n2)
> -      port 1a8162
> -          type: router
> -          router-port: lrp-1a8162
> -      port 82b983
> -          type: router
> -          router-port: lrp-82b983
> -      port 2e585f (aka cp)
> -          addresses: ["fa:16:3e:89:f2:36 10.1.2.7 fc22::7"]
> -  switch 3eb263 (neutron-5b6baf) (aka n1)
> -      port ad952e
> -          type: router
> -          router-port: lrp-ad952e
> -      port c29d41 (aka bp)
> -          addresses: ["fa:16:3e:99:7a:17 10.1.1.6 fc11::6"]
> -      port 820c08 (aka ap)
> -          addresses: ["fa:16:3e:a9:4c:c7 10.1.1.5 fc11::5"]
> -      port 17d870
> -          type: router
> -          router-port: lrp-17d870
> -  ...
> -  router dde06c (neutron-f88ebc) (aka r)
> -      port lrp-1a8162
> -          mac: "fa:16:3e:06:de:ad"
> -          networks: ["fc22::1/64"]
> -      port lrp-82b983
> -          mac: "fa:16:3e:19:9f:46"
> -          networks: ["10.1.2.1/24"]
> -      port lrp-ad952e
> -          mac: "fa:16:3e:ef:2f:8b"
> -          networks: ["fc11::1/64"]
> -      port lrp-17d870
> -          mac: "fa:16:3e:f6:e2:8f"
> -          networks: ["10.1.1.1/24"]
> -
> -Try tracing a packet from ``a`` to ``c``.  The results correspond
> -closely to those for IPv4 which we already discussed back under
> -`Routing`_::
> -
> -  $ N1SUBNET6_MAC=$(ovn-nbctl --bare --columns=mac find
> logical_router_port networks=\"fc11::1/64\")
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC' && eth.dst ==
> '$N1SUBNET6_MAC' && ip6.src == fc11::5 && ip6.dst == fc22::7 && ip.ttl ==
> 64 && icmp6.type == 8'
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src ==
> {fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
> -      next;
> -   1. ls_in_port_sec_ip (ovn-northd.c:2390): inport == "ap" && eth.src ==
> fa:16:3e:a9:4c:c7 && ip6.src == {fe80::f816:3eff:fea9:4cc7, fc11::5},
> priority 90, uuid 604810ea
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2646): ip, priority 100, uuid 46c089e6
> -      reg0[0] = 1;
> -      next;
> -   5. ls_in_pre_stateful (ovn-northd.c:2764): reg0[0] == 1, priority 100,
> uuid d1941634
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   6. ls_in_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (inport == "ap" && ip6), priority 2002, uuid
> 7fdd607e
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:ef:2f:8b,
> priority 50, uuid e1d87fc5
> -      outport = "ad952e";
> -      output;
> -
> -  egress(dp="n1", inport="ap", outport="ad952e")
> -  ----------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2626): ip && outport == "ad952e",
> priority 110, uuid 88f68988
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "ad952e",
> priority 50, uuid 5935755e
> -      output;
> -      /* output to "ad952e", type "patch" */
> -
> -  ingress(dp="r", inport="lrp-ad952e")
> -  ------------------------------------
> -   0. lr_in_admission (ovn-northd.c:4071): eth.dst == fa:16:3e:ef:2f:8b
> && inport == "lrp-ad952e", priority 50, uuid ddfeb712
> -      next;
> -   5. lr_in_ip_routing (ovn-northd.c:3782): ip6.dst == fc22::/64,
> priority 129, uuid cc2130ec
> -      ip.ttl--;
> -      xxreg0 = ip6.dst;
> -      xxreg1 = fc22::1;
> -      eth.src = fa:16:3e:06:de:ad;
> -      outport = "lrp-1a8162";
> -      flags.loopback = 1;
> -      next;
> -   6. lr_in_arp_resolve (ovn-northd.c:5122): outport == "lrp-1a8162" &&
> xxreg0 == fc22::7, priority 100, uuid bcf75288
> -      eth.dst = fa:16:3e:89:f2:36;
> -      next;
> -   8. lr_in_arp_request (ovn-northd.c:5260): 1, priority 0, uuid 6dacdd82
> -      output;
> -
> -  egress(dp="r", inport="lrp-ad952e", outport="lrp-1a8162")
> -  ---------------------------------------------------------
> -   3. lr_out_delivery (ovn-northd.c:5288): outport == "lrp-1a8162",
> priority 100, uuid 5260dfc5
> -      output;
> -      /* output to "lrp-1a8162", type "patch" */
> -
> -  ingress(dp="n2", inport="1a8162")
> -  ---------------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "1a8162", priority
> 50, uuid 10957d1b
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2624): ip && inport == "1a8162",
> priority 110, uuid a27ebd00
> -      next;
> -  13. ls_in_l2_lkup (ovn-northd.c:3529): eth.dst == fa:16:3e:89:f2:36,
> priority 50, uuid dcafb3e9
> -      outport = "cp";
> -      output;
> -
> -  egress(dp="n2", inport="1a8162", outport="cp")
> -  ----------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2648): ip, priority 100, uuid cd9cfa74
> -      reg0[0] = 1;
> -      next;
> -   2. ls_out_pre_stateful (ovn-northd.c:2766): reg0[0] == 1, priority
> 100, uuid 9e8e22c5
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   4. ls_out_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (outport == "cp" && ip6 && ip6.src ==
> $as_ip6_0fc1b6cf_f925_49e6_8f00_6dd13beca9dc), priority 2002, uuid 12fc96f9
> -      next;
> -   7. ls_out_port_sec_ip (ovn-northd.c:2390): outport == "cp" && eth.dst
> == fa:16:3e:89:f2:36 && ip6.dst == {fe80::f816:3eff:fe89:f236, ff00::/8,
> fc22::7}, priority 90, uuid c622596a
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "cp" && eth.dst
> == {fa:16:3e:89:f2:36}, priority 50, uuid 0242cdc3
> -      output;
> -      /* output to "cp", type "" */
> -
> -ACLs
> -----
> -
> -Let's explore how ACLs work in OpenStack and OVN.  In OpenStack, ACL
> -rules are part of "security groups", which are "default deny", that
> -is, packets are not allowed by default and the rules added to security
> -groups serve to allow different classes of packets.  The default group
> -(named "default") that is assigned to each of our VMs so far allows
> -all traffic from our other VMs, which isn't very interesting for
> -testing.  So, let's create a new security group, which we'll name
> -"custom", add rules to it that allow incoming SSH and ICMP traffic,
> -and apply this security group to VM ``c``::
> -
> -  $ openstack security group create custom
> -  $ openstack security group rule create --dst-port 22 custom
> -  $ openstack security group rule create --protocol icmp custom
> -  $ openstack server remove security group c default
> -  $ openstack server add security group c custom
> -
> -Now we can do some experiments to test security groups.  From the
> -console on ``a`` or ``b``, it should now be possible to "ping" ``c``
> -or to SSH to it, but attempts to initiate connections on other ports
> -should be blocked.  (You can try to connect on another port with
> -``ssh -p PORT IP`` or ``nc PORT IP``.)  Connection attempts should
> -time out rather than receive the "connection refused" or "connection
> -reset" error that you would see between ``a`` and ``b``.
> -
> -It's also possible to test ACLs via ovn-trace, with one new wrinkle.
> -ovn-trace can't simulate connection tracking state in the network, so
> -by default it assumes that every packet represents an established
> -connection.  That's good enough for what we've been doing so far, but
> -for checking properties of security groups we want to look at more
> -detail.
> -
> -If you look back at the VM-to-VM traces we've done until now, you can
> -see that they execute two ``ct_next`` actions:
> -
> -* The first of these is for the packet passing outward through the
> -  source VM's firewall.  We can tell ovn-trace to treat the packet as
> -  starting a new connection or adding to an established connection by
> -  adding a ``--ct`` option: ``--ct new`` or ``--ct est``,
> -  respectively.  The latter is the default and therefore what we've
> -  been using so far.  We can also use ``--ct est,rpl``, which in
> -  addition to ``--ct est`` means that the connection was initiated by
> -  the destination VM rather than by the VM sending this packet.
> -
> -* The second is for the packet passing inward through the destination
> -  VM's firewall.  For this one, it makes sense to tell ovn-trace that
> -  the packet is starting a new connection, with ``--ct new``, or that
> -  it is a packet sent in reply to a connection established by the
> -  destination VM, with ``--ct est,rpl``.
> -
> -ovn-trace uses the ``--ct`` options in order, so if we want to
> -override the second ``ct_next`` behavior we have to specify two
> -options.
> -
> -Another useful ovn-trace option for this testing is ``--minimal``,
> -which reduces the amount of output.  In this case we're really just
> -interested in finding out whether the packet reaches the destination
> -VM, that is, whether there's an eventual ``output`` action to ``c``,
> -so ``--minimal`` works fine and the output is easier to read.
> -
> -Try a few traces.  For example:
> -
> -* VM ``a`` initiates a new SSH connection to ``c``::
> -
> -    $ ovn-trace --ct new --ct new --minimal n1 'inport == "ap" && eth.src
> == '$AP_MAC' && eth.dst == '$N1SUBNET6_MAC' && ip4.src == 10.1.1.5 &&
> ip4.dst == 10.1.2.7 && ip.ttl == 64 && tcp.dst == 22'
> -    ...
> -    ct_next(ct_state=new|trk) {
> -        ip.ttl--;
> -        eth.src = fa:16:3e:19:9f:46;
> -        eth.dst = fa:16:3e:89:f2:36;
> -        ct_next(ct_state=new|trk) {
> -            output("cp");
> -        };
> -    };
> -
> -  This succeeds, as you can see since there is an ``output`` action.
> -
> -* VM ``a`` initiates a new Telnet connection to ``c``::
> -
> -    $ ovn-trace --ct new --ct new --minimal n1 'inport == "ap" && eth.src
> == '$AP_MAC' && eth.dst == '$N1SUBNET6_MAC' && ip4.src == 10.1.1.5 &&
> ip4.dst == 10.1.2.7 && ip.ttl == 64 && tcp.dst == 23'
> -    ct_next(ct_state=new|trk) {
> -        ip.ttl--;
> -        eth.src = fa:16:3e:19:9f:46;
> -        eth.dst = fa:16:3e:89:f2:36;
> -        ct_next(ct_state=new|trk);
> -    };
> -
> -  This fails, as you can see from the lack of an ``output`` action.
> -
> -* VM ``a`` replies to a packet that is part of a Telnet connection
> -  originally initiated by ``c``::
> -
> -    $ ovn-trace --ct est,rpl --ct est,rpl --minimal n1 'inport == "ap" &&
> eth.src == '$AP_MAC' && eth.dst == '$N1SUBNET6_MAC' && ip4.src == 10.1.1.5
> && ip4.dst == 10.1.2.7 && ip.ttl == 64 && tcp.dst == 23'
> -    ...
> -    ct_next(ct_state=est|rpl|trk) {
> -        ip.ttl--;
> -        eth.src = fa:16:3e:19:9f:46;
> -        eth.dst = fa:16:3e:89:f2:36;
> -        ct_next(ct_state=est|rpl|trk) {
> -            output("cp");
> -        };
> -    };
> -
> -  This succeeds, as you can see from the ``output`` action, since
> -  traffic received in reply to an outgoing connection is always
> -  allowed.
> -
> -DHCP
> -----
> -
> -As a final demonstration of the OVN architecture, let's examine the
> -DHCP implementation.  Like switching, routing, and NAT, the OVN
> -implementation of DHCP involves configuration in the NB DB and logical
> -flows in the SB DB.
> -
> -Let's look at the DHCP support for ``a``'s port ``ap``.  The port's
> -Logical_Switch_Port record shows that ``ap`` has DHCPv4 options::
> -
> -  $ ovn-nbctl list logical_switch_port ap | abbrev
> -  _uuid               : ef17e5
> -  addresses           : ["fa:16:3e:a9:4c:c7 10.1.1.5 fc11::5"]
> -  dhcpv4_options      : 165974
> -  dhcpv6_options      : 26f7cd
> -  dynamic_addresses   : []
> -  enabled             : true
> -  external_ids        : {"neutron:port_name"=ap}
> -  name                : "820c08"
> -  options             : {}
> -  parent_name         : []
> -  port_security       : ["fa:16:3e:a9:4c:c7 10.1.1.5 fc11::5"]
> -  tag                 : []
> -  tag_request         : []
> -  type                : ""
> -  up                  : true
> -
> -We can then list them either by UUID or, more easily, by port name::
> -
> -  $ ovn-nbctl list dhcp_options ap | abbrev
> -  _uuid               : 165974
> -  cidr                : "10.1.1.0/24"
> -  external_ids        : {subnet_id="5e67e7"}
> -  options             : {lease_time="43200", mtu="1442",
> router="10.1.1.1", server_id="10.1.1.1", server_mac="fa:16:3e:bb:94:72"}
> -
> -These options show the basic DHCP configuration for the subnet.  They
> -do not include the IP address itself, which comes from the
> -Logical_Switch_Port record.  This allows a whole Neutron subnet to
> -share a single DHCP_Options record.  You can see this sharing in
> -action, if you like, by listing the record for port ``bp``, which is
> -on the same subnet as ``ap``, and see that it is the same record as
> before::
> -
> -  $ ovn-nbctl list dhcp_options bp | abbrev
> -  _uuid               : 165974
> -  cidr                : "10.1.1.0/24"
> -  external_ids        : {subnet_id="5e67e7"}
> -  options             : {lease_time="43200", mtu="1442",
> router="10.1.1.1", server_id="10.1.1.1", server_mac="fa:16:3e:bb:94:72"}
> -
> -You can take another look at the southbound flow table if you like,
> -but the best demonstration is to trace a DHCP packet.  The following
> -is a trace of a DHCP request inbound from ``ap``.  The first part is
> -just the usual travel through the firewall::
> -
> -  $ ovn-trace n1 'inport == "ap" && eth.src == '$AP_MAC' && eth.dst ==
> ff:ff:ff:ff:ff:ff && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst
> == 67 && ip.ttl == 1'
> -  ...
> -  ingress(dp="n1", inport="ap")
> -  -----------------------------
> -   0. ls_in_port_sec_l2 (ovn-northd.c:3234): inport == "ap" && eth.src ==
> {fa:16:3e:a9:4c:c7}, priority 50, uuid 6dcc418a
> -      next;
> -   1. ls_in_port_sec_ip (ovn-northd.c:2325): inport == "ap" && eth.src ==
> fa:16:3e:a9:4c:c7 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 &&
> udp.src == 68 && udp.dst == 67, priority 90, uuid e46bed6f
> -      next;
> -   3. ls_in_pre_acl (ovn-northd.c:2646): ip, priority 100, uuid 46c089e6
> -      reg0[0] = 1;
> -      next;
> -   5. ls_in_pre_stateful (ovn-northd.c:2764): reg0[0] == 1, priority 100,
> uuid d1941634
> -      ct_next;
> -
> -The next part is the new part.  First, an ACL in table 6 allows a DHCP
> -request to pass through.  In table 11, the special ``put_dhcp_opts``
> -action replaces a DHCPDISCOVER or DHCPREQUEST packet by a
> -reply.  Table 12 flips the packet's source and destination and sends
> -it back the way it came in::
> -
> -   6. ls_in_acl (ovn-northd.c:2925): !ct.new && ct.est && !ct.rpl &&
> ct_label.blocked == 0 && (inport == "ap" && ip4 && ip4.dst ==
> {255.255.255.255, 10.1.1.0/24} && udp && udp.src == 68 && udp.dst == 67),
> priority 2002, uuid 9c90245d
> -      next;
> -  11. ls_in_dhcp_options (ovn-northd.c:3409): inport == "ap" && eth.src
> == fa:16:3e:a9:4c:c7 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 &&
> udp.src == 68 && udp.dst == 67, priority 100, uuid 8d63f29c
> -      reg0[3] = put_dhcp_opts(offerip = 10.1.1.5, lease_time = 43200, mtu
> = 1442, netmask = 255.255.255.0, router = 10.1.1.1, server_id = 10.1.1.1);
> -      /* We assume that this packet is DHCPDISCOVER or DHCPREQUEST. */
> -      next;
> -  12. ls_in_dhcp_response (ovn-northd.c:3438): inport == "ap" && eth.src
> == fa:16:3e:a9:4c:c7 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3],
> priority 100, uuid 995eeaa9
> -      eth.dst = eth.src;
> -      eth.src = fa:16:3e:bb:94:72;
> -      ip4.dst = 10.1.1.5;
> -      ip4.src = 10.1.1.1;
> -      udp.src = 67;
> -      udp.dst = 68;
> -      outport = inport;
> -      flags.loopback = 1;
> -      output;
> -
> -Then the last part is just traveling back through the firewall to VM
> -``a``::
> -
> -  egress(dp="n1", inport="ap", outport="ap")
> -  ------------------------------------------
> -   1. ls_out_pre_acl (ovn-northd.c:2648): ip, priority 100, uuid 3752b746
> -      reg0[0] = 1;
> -      next;
> -   2. ls_out_pre_stateful (ovn-northd.c:2766): reg0[0] == 1, priority
> 100, uuid 0c066ea1
> -      ct_next;
> -
> -  ct_next(ct_state=est|trk /* default (use --ct to customize) */)
> -  ---------------------------------------------------------------
> -   4. ls_out_acl (ovn-northd.c:3008): outport == "ap" && eth.src ==
> fa:16:3e:bb:94:72 && ip4.src == 10.1.1.1 && udp && udp.src == 67 && udp.dst
> == 68, priority 34000, uuid 0b383e77
> -      ct_commit;
> -      next;
> -   7. ls_out_port_sec_ip (ovn-northd.c:2364): outport == "ap" && eth.dst
> == fa:16:3e:a9:4c:c7 && ip4.dst == {255.255.255.255, 224.0.0.0/4,
> 10.1.1.5}, priority 90, uuid 7b8cbcd5
> -      next;
> -   8. ls_out_port_sec_l2 (ovn-northd.c:3654): outport == "ap" && eth.dst
> == {fa:16:3e:a9:4c:c7}, priority 50, uuid b874ece8
> -      output;
> -      /* output to "ap", type "" */
> -
> -Further Directions
> -------------------
> -
> -We've looked at a fair bit of how OVN works and how it interacts with
> -OpenStack.  If you still have some interest, then you might want to
> -explore some of these directions:
> -
> -* Adding more than one hypervisor ("compute node", in OpenStack
> -  parlance).  OVN connects compute nodes by tunneling packets with the
> -  STT or Geneve protocols.  OVN scales to 1000 compute nodes or more,
> -  but two compute nodes demonstrate the principle.  All of the tools
> -  and techniques we demonstrated also work with multiple compute
> -  nodes.
> -
> -* Container support.  OVN supports seamlessly connecting VMs to
> -  containers, whether the containers are hosted on "bare metal" or
> -  nested inside VMs.  OpenStack support for containers, however, is
> -  still evolving, and too difficult to incorporate into the tutorial
> -  at this point.
> -
> -* Other kinds of gateways.  In addition to floating IPs with NAT, OVN
> -  supports directly attaching VMs to a physical network and connecting
> -  logical switches to VTEP hardware.
> diff --git a/Documentation/tutorials/ovn-rbac.rst
> b/Documentation/tutorials/ovn-rbac.rst
> deleted file mode 100644
> index ec163e2df..000000000
> --- a/Documentation/tutorials/ovn-rbac.rst
> +++ /dev/null
> @@ -1,134 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -=============================================
> -OVN Role-Based Access Control (RBAC) Tutorial
> -=============================================
> -
> -This document provides a step-by-step guide for setting up role-based
> access
> -control (RBAC) in OVN. In OVN, hypervisors (chassis) read and write the
> -southbound database to do configuration. Without restricting hypervisor's
> -access to the southbound database, a compromised hypervisor might disrupt
> the
> -entire OVN deployment by corrupting the database. RBAC ensures that each
> -hypervisor can only modify its own data and thus improves the security of
> OVN.
> -More details about the RBAC design can be found in
> ``ovn-architecture``\(7)
> -manpage.
> -
> -This document assumes OVN is installed in your system and runs normally.
> -
> -.. _gen-certs-keys:
> -
> -Generating Certificates and Keys
> ---------------------------------
> -
> -In the OVN RBAC deployment, ovn-controller connects to the southbound
> database
> -via SSL connection. The southbound database uses CA-signed certificate to
> -authenticate ovn-controller.
> -
> -Suppose there are three machines in your deployment. `machine_1` runs
> -`chassis_1` and has IP address `machine_1-ip`. `machine_2` runs
> `chassis_2` and
> -has IP address `machine_2-ip`. `machine_3` hosts southbound database and
> has IP
> -address `machine_3-ip`. `machine_3` also hosts public key infrastructure
> (PKI).
> -
> -1. Initiate PKI.
> -
> -   In `machine_3`::
> -
> -      $ ovs-pki init
> -
> -2. Generate southbound database's certificate request. Sign the
> certificate
> -   request with the CA key.
> -
> -   In `machine_3`::
> -
> -      $ ovs-pki req -u sbdb
> -      $ ovs-pki sign sbdb switch
> -
> -3. Generate chassis certificate requests. Copy the certificate requests to
> -   `machine_3`.
> -
> -   In `machine_1`::
> -
> -      $ ovs-pki req -u chassis_1
> -      $ scp chassis_1-req.pem \
> -                    machine_3@machine_3-ip:/path/to/chassis_1-req.pem
> -
> -   In `machine_2`::
> -
> -      $ ovs-pki req -u chassis_2
> -      $ scp chassis_2-req.pem \
> -                    machine_3@machine_3-ip:/path/to/chassis_2-req.pem
> -
> -   .. note::
> -
> -     chassis_1 must be the same string as ``external_ids:system-id`` in
> the
> -     Open_vSwitch table (the chassis name) of machine_1. Same applies for
> -     chassis_2.
> -
> -4. Sign the chassis certificate requests with the CA key. Copy
> `chassis_1`'s
> -   signed certificate and the CA certificate to `machine_1`. Copy
> `chassis_2`'s
> -   signed certificate and the CA certificate to `machine_2`.
> -
> -   In `machine_3`::
> -
> -      $ ovs-pki sign chassis_1 switch
> -      $ ovs-pki sign chassis_2 switch
> -      $ scp chassis_1-cert.pem \
> -                    machine_1@machine_1-ip:/path/to/chassis_1-cert.pem
> -      $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
> -                    machine_1@machine_1-ip:/path/to/cacert.pem
> -      $ scp chassis_2-cert.pem \
> -                    machine_2@machine_2-ip:/path/to/chassis_2-cert.pem
> -      $ scp /var/lib/openvswitch/pki/switchca/cacert.pem \
> -                    machine_2@machine_2-ip:/path/to/cacert.pem
> -
> -Configuring RBAC
> -----------------
> -
> -1. Set certificate, private key, and CA certificate for the southbound
> -   database. Configure the southbound database to listen on SSL
> connection and
> -   enforce role-based access control.
> -
> -   In `machine_3`::
> -
> -      $ ovn-sbctl set-ssl /path/to/sbdb-privkey.pem \
> -                          /path/to/sbdb-cert.pem /path/to/cacert.pem
> -      $ ovn-sbctl set-connection role=ovn-controller pssl:6642
> -
> -2. Set certificate, private key, and CA certificate for `chassis_1` and
> -   `chassis_2`. Configure `chassis_1` and `chassis_2` to connect
> southbound
> -   database via SSL.
> -
> -   In `machine_1`::
> -
> -      $ ovs-vsctl set-ssl /path/to/chassis_1-privkey.pem \
> -                    /path/to/chassis_1-cert.pem /path/to/cacert.pem
> -      $ ovs-vsctl set open_vswitch . \
> -                    external_ids:ovn-remote=ssl:machine_3-ip:6642
> -
> -   In `machine_2`::
> -
> -      $ ovs-vsctl set-ssl /path/to/chassis_2-privkey.pem \
> -                    /path/to/chassis_2-cert.pem /path/to/cacert.pem
> -      $ ovs-vsctl set open_vswitch . \
> -                    external_ids:ovn-remote=ssl:machine_3-ip:6642
> diff --git a/Documentation/tutorials/ovn-sandbox.rst
> b/Documentation/tutorials/ovn-sandbox.rst
> deleted file mode 100644
> index b906b799d..000000000
> --- a/Documentation/tutorials/ovn-sandbox.rst
> +++ /dev/null
> @@ -1,177 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -===========
> -OVN Sandbox
> -===========
> -
> -This tutorial shows you how to explore features using ``ovs-sandbox`` as a
> -simulated test environment.  It's assumed that you have an understanding
> of OVS
> -before going through this tutorial. Detail about OVN is covered in
> -ovn-architecture_, but this tutorial lets you quickly see it in action.
> -
> -Getting Started
> ----------------
> -
> -For some general information about ``ovs-sandbox``, see the "Getting
> Started"
> -section of :doc:`ovs-advanced`.
> -
> -``ovs-sandbox`` does not include OVN support by default.  To enable OVN,
> you
> -must pass the ``--ovn`` flag.  For example, if running it straight from
> the OVS
> -git tree you would run::
> -
> -    $ make sandbox SANDBOXFLAGS="--ovn"
> -
> -Running the sandbox with OVN enabled does the following additional steps
> to the
> -environment:
> -
> -1. Creates the ``OVN_Northbound`` and ``OVN_Southbound`` databases as
> described in
> -   `ovn-nb(5)`_ and `ovn-sb(5)`_.
> -
> -2. Creates a backup server for ``OVN_Southbond`` database. Sandbox launch
> -   screen provides the instructions on accessing the backup database.
> However
> -   access to the backup server is not required to go through the tutorial.
> -
> -3. Creates the ``hardware_vtep`` database as described in `vtep(5)`_.
> -
> -4. Runs the `ovn-northd(8)`_, `ovn-controller(8)`_, and
> -   `ovn-controller-vtep(8)`_ daemons.
> -
> -5. Makes OVN and VTEP utilities available for use in the environment,
> including
> -   `vtep-ctl(8)`_, `ovn-nbctl(8)`_, and `ovn-sbctl(8)`_.
> -
> -Using GDB
> ----------
> -
> -GDB support is not required to go through the tutorial. See the "Using
> GDB"
> -section of :doc:`ovs-advanced` for more info. Additional flags exist for
> -launching the debugger for the OVN programs::
> -
> -    --gdb-ovn-northd
> -    --gdb-ovn-controller
> -    --gdb-ovn-controller-vtep
> -
> -Creating OVN Resources
> -----------------------
> -
> -Once you have ``ovs-sandbox`` running with OVN enabled, you can start
> using OVN
> -utilities to create resources in OVN.  As an example, we will create an
> -environment that has two logical switches connected by a logical router.
> -
> -Create the first logical switch with one port::
> -
> -    $ 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
> 192.168.0.2"
> -
> -Create the second logical switch with one port::
> -
> -    $ ovn-nbctl ls-add sw1
> -    $ ovn-nbctl lsp-add sw1 sw1-port1
> -    $ ovn-nbctl lsp-set-addresses sw1-port1 "50:54:00:00:00:03 11.0.0.2"
> -
> -Create the logical router and attach both logical switches::
> -
> -    $ ovn-nbctl lr-add lr0
> -    $ ovn-nbctl lrp-add lr0 lrp0 00:00:00:00:ff:01 192.168.0.1/24
> -    $ ovn-nbctl lsp-add sw0 lrp0-attachment
> -    $ ovn-nbctl lsp-set-type lrp0-attachment router
> -    $ ovn-nbctl lsp-set-addresses lrp0-attachment 00:00:00:00:ff:01
> -    $ ovn-nbctl lsp-set-options lrp0-attachment router-port=lrp0
> -    $ ovn-nbctl lrp-add lr0 lrp1 00:00:00:00:ff:02 11.0.0.1/24
> -    $ ovn-nbctl lsp-add sw1 lrp1-attachment
> -    $ ovn-nbctl lsp-set-type lrp1-attachment router
> -    $ ovn-nbctl lsp-set-addresses lrp1-attachment 00:00:00:00:ff:02
> -    $ ovn-nbctl lsp-set-options lrp1-attachment router-port=lrp1
> -
> -View a summary of OVN's current logical configuration::
> -
> -    $ ovn-nbctl show
> -        switch 1396cf55-d176-4082-9a55-1c06cef626e4 (sw1)
> -            port lrp1-attachment
> -                addresses: ["00:00:00:00:ff:02"]
> -            port sw1-port1
> -                addresses: ["50:54:00:00:00:03 11.0.0.2"]
> -        switch 2c9d6d03-09fc-4e32-8da6-305f129b0d53 (sw0)
> -            port lrp0-attachment
> -                addresses: ["00:00:00:00:ff:01"]
> -            port sw0-port1
> -                addresses: ["50:54:00:00:00:01 192.168.0.2"]
> -        router f8377e8c-f75e-4fc8-8751-f3ea03c6dd98 (lr0)
> -            port lrp0
> -                mac: "00:00:00:00:ff:01"
> -                networks: ["192.168.0.1/24"]
> -            port lrp1
> -                mac: "00:00:00:00:ff:02"
> -                networks: ["11.0.0.1/24"]
> -
> -The ``tutorial`` directory of the OVS source tree includes a script
> -that runs all of the commands for you::
> -
> -    $ ./ovn-setup.sh
> -
> -Using ovn-trace
> ----------------
> -
> -Once you have configured resources in OVN, try using ``ovn-trace`` to see
> -how OVN would process a sample packet through its logical pipeline.
> -
> -For example, we can trace an IP packet from ``sw0-port1`` to
> ``sw1-port1``.
> -The ``--minimal`` output shows each visible action performed on the
> packet,
> -which includes:
> -
> -#. The logical router will decrement the IP TTL field.
> -#. The logical router will change the source and destination
> -   MAC addresses to reflect the next hop.
> -#. The packet will be output to ``sw1-port1``.
> -
> -::
> -
> -    $ ovn-trace --minimal sw0 'inport == "sw0-port1" \
> -    > && eth.src == 50:54:00:00:00:01 && ip4.src == 192.168.0.2 \
> -    > && eth.dst == 00:00:00:00:ff:01 && ip4.dst == 11.0.0.2 \
> -    > && ip.ttl == 64'
> -
> -    #
> ip,reg14=0x1,vlan_tci=0x0000,dl_src=50:54:00:00:00:01,dl_dst=00:00:00:00:ff:01,nw_src=192.168.0.2,nw_dst=11.0.0.2,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=64
> -    ip.ttl--;
> -    eth.src = 00:00:00:00:ff:02;
> -    eth.dst = 50:54:00:00:00:03;
> -    output("sw1-port1");
> -
> -The ``ovn-trace`` utility can also provide much more detail on how the
> packet
> -would be processed through OVN's logical pipeline, as well as correlate
> that
> -to OpenFlow flows programmed by ``ovn-controller``.  See the
> `ovn-trace(8)`_
> -man page for more detail.
> -
> -
> -.. _ovn-architecture:
> http://openvswitch.org/support/dist-docs/ovn-architecture.7.html
> -.. _ovn-nb(5): http://openvswitch.org/support/dist-docs/ovn-nb.5.html
> -.. _ovn-sb(5): http://openvswitch.org/support/dist-docs/ovn-sb.5.html
> -.. _vtep(5): http://openvswitch.org/support/dist-docs/vtep.5.html
> -.. _ovn-northd(8):
> http://openvswitch.org/support/dist-docs/ovn-northd.8.html
> -.. _ovn-controller(8):
> http://openvswitch.org/support/dist-docs/ovn-controller.8.html
> -.. _ovn-controller-vtep(8):
> http://openvswitch.org/support/dist-docs/ovn-controller-vtep.8.html
> -.. _vtep-ctl(8): http://openvswitch.org/support/dist-docs/vtep-ctl.8.html
> -.. _ovn-nbctl(8):
> http://openvswitch.org/support/dist-docs/ovn-nbctl.8.html
> -.. _ovn-sbctl(8):
> http://openvswitch.org/support/dist-docs/ovn-sbctl.8.html
> -.. _ovn-trace(8):
> http://openvswitch.org/support/dist-docs/ovn-trace.8.html
> diff --git a/Makefile.am b/Makefile.am
> index ff1f94b48..a03a0351a 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -495,6 +495,5 @@ include vtep/automake.mk
>  include datapath-windows/automake.mk
>  include datapath-windows/include/automake.mk
>  include windows/automake.mk
> -include ovn/automake.mk
>  include selinux/automake.mk
>  include build-aux/automake.mk
> diff --git a/NEWS b/NEWS
> index c5caa13d6..289d1e4f9 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,6 +1,9 @@
>  Post-v2.12.0
>  ---------------------
> -
> +   - OVN:
> +     * OVN has been removed from this repository. It now exists as a
> +       separate project. You can find it at
> +       https://github.com/ovn-org/ovn.git
>
>  v2.12.0 - xx xxx xxxx
>  ---------------------
> diff --git a/configure.ac b/configure.ac
> index e3603926b..64ce4cef0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -148,7 +148,6 @@ AC_CONFIG_FILES([
>      ofproto/libofproto.sym
>      lib/libsflow.sym
>      lib/libopenvswitch.sym
> -    ovn/lib/libovn.sym
>      vtep/libvtep.sym])
>
>  OVS_ENABLE_OPTION([-Wall])
> @@ -210,8 +209,6 @@ dnl This makes sure that include/openflow gets created
> in the build directory.
>  AC_CONFIG_COMMANDS([include/openflow/openflow.h.stamp])
>
>  AC_CONFIG_COMMANDS([utilities/bugtool/dummy], [:])
> -AC_CONFIG_COMMANDS([ovn/dummy], [:])
> -AC_CONFIG_COMMANDS([ovn/utilities/dummy], [:])
>  AC_CONFIG_COMMANDS([ipsec/dummy], [:])
>
>  m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
> diff --git a/debian/.gitignore b/debian/.gitignore
> index 9ec70eb9c..441a8ffb7 100644
> --- a/debian/.gitignore
> +++ b/debian/.gitignore
> @@ -22,10 +22,5 @@
>  /openvswitch-test
>  /openvswitch-testcontroller
>  /openvswitch-vtep
> -/ovn-common
> -/ovn-controller-vtep
> -/ovn-host
> -/ovn-central
> -/ovn-docker
>  /python-openvswitch
>  /tmp
> diff --git a/debian/automake.mk b/debian/automake.mk
> index 8a8d43c9f..03a1d68c2 100644
> --- a/debian/automake.mk
> +++ b/debian/automake.mk
> @@ -52,28 +52,6 @@ EXTRA_DIST += \
>         debian/openvswitch-vtep.init \
>         debian/openvswitch-vtep.install \
>         debian/openvswitch-vtep.manpages \
> -       debian/ovn-central.dirs \
> -       debian/ovn-central.init \
> -       debian/ovn-central.install \
> -       debian/ovn-central.manpages \
> -       debian/ovn-central.postinst \
> -       debian/ovn-central.postrm \
> -       debian/ovn-central.template \
> -       debian/ovn-controller-vtep.init \
> -       debian/ovn-controller-vtep.install \
> -       debian/ovn-controller-vtep.manpages \
> -       debian/ovn-common.install \
> -       debian/ovn-common.manpages \
> -       debian/ovn-common.postinst \
> -       debian/ovn-common.postrm \
> -       debian/ovn-docker.install \
> -       debian/ovn-host.dirs \
> -       debian/ovn-host.init \
> -       debian/ovn-host.install \
> -       debian/ovn-host.manpages \
> -       debian/ovn-host.postinst \
> -       debian/ovn-host.postrm \
> -       debian/ovn-host.template \
>         debian/python-openvswitch.dirs \
>         debian/python-openvswitch.install \
>         debian/rules \
> diff --git a/debian/control b/debian/control
> index b97e99b92..2ad35f2ce 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -119,84 +119,6 @@ Description: Open vSwitch switch implementations
>   openvswitch-switch provides the userspace components and utilities for
>   the Open vSwitch kernel-based switch.
>
> -Package: ovn-common
> -Architecture: linux-any
> -Depends: openvswitch-common (= ${binary:Version}),
> -         ${misc:Depends},
> -         ${shlibs:Depends}
> -Description: OVN common components
> - OVN, the Open Virtual Network, is a system to support virtual network
> - abstraction.  OVN complements the existing capabilities of OVS to add
> - native support for virtual network abstractions, such as virtual L2 and
> L3
> - overlays and security groups.
> - .
> - ovn-common provides components required by other OVN packages.
> -
> -Package: ovn-controller-vtep
> -Architecture: linux-any
> -Depends: ovn-common (= ${binary:Version}),
> -         ${misc:Depends},
> -         ${shlibs:Depends}
> -Description: OVN vtep controller
> - ovn-controller-vtep is the local controller daemon in
> - OVN, the Open Virtual Network, for VTEP enabled physical switches.
> - It connects up to the OVN Southbound database over the OVSDB protocol,
> - and down to the VTEP database over the OVSDB protocol.
> - .
> - ovn-controller-vtep provides the ovn-controller-vtep binary for
> controlling
> - vtep gateways.
> -
> -
> -Package: ovn-host
> -Architecture: linux-any
> -Depends: openvswitch-switch (= ${binary:Version}),
> -         openvswitch-common (= ${binary:Version}),
> -         ovn-common (= ${binary:Version}),
> -         ${misc:Depends},
> -         ${shlibs:Depends}
> -Description: OVN host components
> - OVN, the Open Virtual Network, is a system to support virtual network
> - abstraction.  OVN complements the existing capabilities of OVS to add
> - native support for virtual network abstractions, such as virtual L2 and
> L3
> - overlays and security groups.
> - .
> - ovn-host provides the userspace components and utilities for
> - OVN that can be run on every host/hypervisor.
> -
> -Package: ovn-central
> -Architecture: linux-any
> -Depends: openvswitch-switch (= ${binary:Version}),
> -         openvswitch-common (= ${binary:Version}),
> -         ovn-common (= ${binary:Version}),
> -         ${misc:Depends},
> -         ${shlibs:Depends}
> -Description: OVN central components
> - OVN, the Open Virtual Network, is a system to support virtual network
> - abstraction.  OVN complements the existing capabilities of OVS to add
> - native support for virtual network abstractions, such as virtual L2 and
> L3
> - overlays and security groups.
> - .
> - ovn-central provides the userspace daemons, utilities and
> - databases for OVN that is run at a central location.
> -
> -Package: ovn-docker
> -Architecture: linux-any
> -Depends: openvswitch-switch (= ${binary:Version}),
> -         openvswitch-common (= ${binary:Version}),
> -         python (>= 2.7),
> -         python-openvswitch (= ${source:Version}),
> -         ovn-common (= ${binary:Version}),
> -         ${misc:Depends},
> -         ${python:Depends},
> -         ${shlibs:Depends}
> -Description: OVN Docker drivers
> - OVN, the Open Virtual Network, is a system to support virtual network
> - abstraction.  OVN complements the existing capabilities of OVS to add
> - native support for virtual network abstractions, such as virtual L2 and
> L3
> - overlays and security groups.
> - .
> - ovn-docker provides the docker drivers for OVN.
> -
>  Package: openvswitch-pki
>  Architecture: all
>  Depends: openvswitch-common (<< ${source:Version}.1~),
> diff --git a/debian/ovn-central.dirs b/debian/ovn-central.dirs
> deleted file mode 100644
> index 6394883ce..000000000
> --- a/debian/ovn-central.dirs
> +++ /dev/null
> @@ -1 +0,0 @@
> -/usr/share/ovn/central
> diff --git a/debian/ovn-central.init b/debian/ovn-central.init
> deleted file mode 100755
> index 60cee95a3..000000000
> --- a/debian/ovn-central.init
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -#! /bin/sh
> -#
> -### BEGIN INIT INFO
> -# Provides:          ovn-central
> -# Required-Start:    openvswitch-switch $remote_fs $syslog
> -# Required-Stop:     $remote_fs
> -# Default-Start:     2 3 4 5
> -# Default-Stop:      0 1 6
> -# Short-Description: OVN central components
> -# Description:       ovn-central provides the userspace daemons,
> -#                    utilities and databases for OVN that is run at a
> central
> -#                    location.
> -### END INIT INFO
> -
> -test -x /usr/bin/ovn-northd  || exit 0
> -test -x /usr/share/openvswitch/scripts/ovn-ctl || exit 0
> -
> -_SYSTEMCTL_SKIP_REDIRECT=yes
> -SYSTEMCTL_SKIP_REDIRECT=yes
> -
> -. /usr/share/openvswitch/scripts/ovs-lib
> -if [ -e /etc/default/ovn-central ]; then
> -    . /etc/default/ovn-central
> -fi
> -
> -start () {
> -    set /usr/share/openvswitch/scripts/ovn-ctl ${1-start_northd}
> -    set "$@" $OVN_CTL_OPTS
> -    "$@" || exit $?
> -}
> -
> -stop_northd () {
> -    set /usr/share/openvswitch/scripts/ovn-ctl ${1-stop_northd}
> -    set "$@" $OVN_CTL_OPTS
> -    "$@" || exit $?
> -}
> -
> -case $1 in
> -    start)
> -        start
> -        ;;
> -    stop)
> -        stop_northd
> -        ;;
> -    restart)
> -        start restart_northd
> -        ;;
> -    reload | force-reload)
> -        ;;
> -    status)
> -        /usr/share/openvswitch/scripts/ovn-ctl status_northd
> -        exit $?
> -        ;;
> -    *)
> -        echo "Usage: $0 {start|stop|reload|force-reload|restart|status}"
> >&2
> -        exit 1
> -        ;;
> -esac
> -
> -exit 0
> diff --git a/debian/ovn-central.install b/debian/ovn-central.install
> deleted file mode 100644
> index 733d3fc5e..000000000
> --- a/debian/ovn-central.install
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -usr/bin/ovn-northd
> -usr/share/openvswitch/ovn-nb.ovsschema
> -usr/share/openvswitch/ovn-sb.ovsschema
> diff --git a/debian/ovn-central.manpages b/debian/ovn-central.manpages
> deleted file mode 100644
> index 2ddb43784..000000000
> --- a/debian/ovn-central.manpages
> +++ /dev/null
> @@ -1 +0,0 @@
> -ovn/northd/ovn-northd.8
> diff --git a/debian/ovn-central.postinst b/debian/ovn-central.postinst
> deleted file mode 100755
> index 10e07ece4..000000000
> --- a/debian/ovn-central.postinst
> +++ /dev/null
> @@ -1,49 +0,0 @@
> -#!/bin/sh
> -# postinst script for ovn-central
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -# summary of how this script can be called:
> -#        * <postinst> `configure' <most-recently-configured-version>
> -#        * <old-postinst> `abort-upgrade' <new version>
> -#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
> -#          <new-version>
> -#        * <postinst> `abort-remove'
> -#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
> -#          <failed-install-package> <version> `removing'
> -#          <conflicting-package> <version>
> -# for details, see http://www.debian.org/doc/debian-policy/ or
> -# the debian-policy package
> -
> -
> -case "$1" in
> -    configure)
> -        DEFAULT=/etc/default/ovn-central
> -        TEMPLATE=/usr/share/ovn/central/default.template
> -        if ! test -e $DEFAULT; then
> -            cp $TEMPLATE $DEFAULT
> -        else
> -            for var in $(awk -F'[ :]' '/^# [_A-Z0-9]+:/{print $2}'
> $TEMPLATE)
> -            do
> -                if ! grep $var $DEFAULT >/dev/null 2>&1; then
> -                    echo >> $DEFAULT
> -                    sed -n "/$var:/,/$var=/p" $TEMPLATE >> $DEFAULT
> -                fi
> -            done
> -        fi
> -        ;;
> -
> -    abort-upgrade|abort-remove|abort-deconfigure)
> -        ;;
> -
> -    *)
> -        echo "postinst called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -#DEBHELPER#
> -
> -exit 0
> diff --git a/debian/ovn-central.postrm b/debian/ovn-central.postrm
> deleted file mode 100755
> index 0e654a37a..000000000
> --- a/debian/ovn-central.postrm
> +++ /dev/null
> @@ -1,48 +0,0 @@
> -#!/bin/sh
> -# postrm script for ovn-central
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -# summary of how this script can be called:
> -#        * <postrm> `remove'
> -#        * <postrm> `purge'
> -#        * <old-postrm> `upgrade' <new-version>
> -#        * <new-postrm> `failed-upgrade' <old-version>
> -#        * <new-postrm> `abort-install'
> -#        * <new-postrm> `abort-install' <old-version>
> -#        * <new-postrm> `abort-upgrade' <old-version>
> -#        * <disappearer's-postrm> `disappear' <overwriter>
> -#          <overwriter-version>
> -# for details, see http://www.debian.org/doc/debian-policy/ or
> -# the debian-policy package
> -
> -
> -case "$1" in
> -    purge)
> -        rm -f /etc/default/ovn-central
> -        rm -f /etc/openvswitch/ovnnb.db*
> -        rm -f /etc/openvswitch/.ovnnb.db.~lock~
> -        rm -f /etc/openvswitch/ovnsb.db*
> -        rm -f /etc/openvswitch/.ovnsb.db.~lock~
> -        rm -f /var/log/openvswitch/ovn-northd.log* || true
> -        ;;
> -
> -    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
> -        ;;
> -
> -    *)
> -        echo "postrm called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -# dh_installdeb will replace this with shell code automatically
> -# generated by other debhelper scripts.
> -
> -#DEBHELPER#
> -
> -exit 0
> -
> -
> diff --git a/debian/ovn-central.template b/debian/ovn-central.template
> deleted file mode 100644
> index 7cea13e50..000000000
> --- a/debian/ovn-central.template
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -# This is a POSIX shell fragment                -*- sh -*-
> -
> -# OVN_CTL_OPTS: Extra options to pass to ovs-ctl.  This is, for example,
> -# a suitable place to specify --ovn-northd-wrapper=valgrind.
> -# OVN_CTL_OPTS=
> diff --git a/debian/ovn-common.install b/debian/ovn-common.install
> deleted file mode 100644
> index 90484d2fe..000000000
> --- a/debian/ovn-common.install
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -usr/bin/ovn-nbctl
> -usr/bin/ovn-sbctl
> -usr/bin/ovn-trace
> -usr/bin/ovn-detrace
> -usr/share/openvswitch/scripts/ovn-ctl
> -usr/share/openvswitch/scripts/ovndb-servers.ocf
> -usr/lib/*/libovn*.so.*
> diff --git a/debian/ovn-common.manpages b/debian/ovn-common.manpages
> deleted file mode 100644
> index 249349ed8..000000000
> --- a/debian/ovn-common.manpages
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -ovn/ovn-architecture.7
> -ovn/ovn-nb.5
> -ovn/ovn-sb.5
> -ovn/utilities/ovn-ctl.8
> -ovn/utilities/ovn-nbctl.8
> -ovn/utilities/ovn-sbctl.8
> -ovn/utilities/ovn-trace.8
> -ovn/utilities/ovn-detrace.1
> diff --git a/debian/ovn-common.postinst b/debian/ovn-common.postinst
> deleted file mode 100644
> index 588044fbc..000000000
> --- a/debian/ovn-common.postinst
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -#!/bin/sh
> -# postinst script for ovn-common
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -case "$1" in
> -    configure)
> -        mkdir -p /usr/lib/ocf/resource.d/ovn
> -        ln -sf /usr/share/openvswitch/scripts/ovndb-servers.ocf
> /usr/lib/ocf/resource.d/ovn/ovndb-servers
> -        ;;
> -    abort-upgrade|abort-remove|abort-deconfigure)
> -        ;;
> -
> -    *)
> -        echo "postinst called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -#DEBHELPER#
> -
> -exit 0
> diff --git a/debian/ovn-common.postrm b/debian/ovn-common.postrm
> deleted file mode 100644
> index 9face726b..000000000
> --- a/debian/ovn-common.postrm
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -#!/bin/sh
> -# postrm script for openvswitch-testcontroller
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -case "$1" in
> -    purge|remove)
> -        rm -rf /usr/lib/ocf/resource.d/ovn
> -        ;;
> -    upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
> -        ;;
> -
> -    *)
> -        echo "postrm called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -#DEBHELPER#
> -
> -exit 0
> diff --git a/debian/ovn-controller-vtep.init
> b/debian/ovn-controller-vtep.init
> deleted file mode 100755
> index be0a24358..000000000
> --- a/debian/ovn-controller-vtep.init
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -#! /bin/sh
> -#
> -### BEGIN INIT INFO
> -# Provides:          ovn-controller-vtep
> -# Required-Start:    openvswitch-switch $remote_fs $syslog
> -# Required-Stop:     $remote_fs
> -# Default-Start:     2 3 4 5
> -# Default-Stop:      0 1 6
> -# Short-Description: OVN Controller for VTEP enabled devices
> -# Description:       ovn-controller-vtep provides the userspace
> -#                    components and utilities for OVN that can be run on
> -#                    hosts taht connect to VTEP enabled devices.
> -### END INIT INFO
> -
> -test -x /usr/bin/ovn-controller-vtep  || exit 0
> -test -x /usr/share/openvswitch/scripts/ovn-ctl || exit 0
> -
> -_SYSTEMCTL_SKIP_REDIRECT=yes
> -SYSTEMCTL_SKIP_REDIRECT=yes
> -
> -. /usr/share/openvswitch/scripts/ovs-lib
> -if [ -e /etc/default/ovn-controller-vtep ]; then
> -    . /etc/default/ovn-controller-vtep
> -fi
> -
> -start () {
> -    set /usr/share/openvswitch/scripts/ovn-ctl ${1-start_controller_vtep}
> -    set "$@" $OVN_CTL_OPTS
> -    "$@" || exit $?
> -}
> -
> -case $1 in
> -    start)
> -        start
> -        ;;
> -    stop | force-stop)
> -        /usr/share/openvswitch/scripts/ovn-ctl stop_controller_vtep
> -        ;;
> -    restart)
> -        start restart_controller_vtep
> -        ;;
> -    status)
> -        /usr/share/openvswitch/scripts/ovn-ctl status_controller_vtep
> -        exit $?
> -        ;;
> -    reload | force-reload)
> -        ;;
> -    *)
> -        echo "Usage: $0 {start|stop|reload|force-reload|restart|status}"
> >&2
> -        exit 1
> -        ;;
> -esac
> -
> -exit 0
> diff --git a/debian/ovn-controller-vtep.install
> b/debian/ovn-controller-vtep.install
> deleted file mode 100644
> index 1d208f37e..000000000
> --- a/debian/ovn-controller-vtep.install
> +++ /dev/null
> @@ -1 +0,0 @@
> -usr/bin/ovn-controller-vtep
> diff --git a/debian/ovn-controller-vtep.manpages
> b/debian/ovn-controller-vtep.manpages
> deleted file mode 100644
> index 787301704..000000000
> --- a/debian/ovn-controller-vtep.manpages
> +++ /dev/null
> @@ -1 +0,0 @@
> -ovn/controller-vtep/ovn-controller-vtep.8
> diff --git a/debian/ovn-docker.install b/debian/ovn-docker.install
> deleted file mode 100644
> index 583306732..000000000
> --- a/debian/ovn-docker.install
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -usr/bin/ovn-docker-overlay-driver
> -usr/bin/ovn-docker-underlay-driver
> diff --git a/debian/ovn-host.dirs b/debian/ovn-host.dirs
> deleted file mode 100644
> index 7d3c761e1..000000000
> --- a/debian/ovn-host.dirs
> +++ /dev/null
> @@ -1 +0,0 @@
> -/usr/share/ovn/host
> diff --git a/debian/ovn-host.init b/debian/ovn-host.init
> deleted file mode 100755
> index 39c3bcf16..000000000
> --- a/debian/ovn-host.init
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -#! /bin/sh
> -#
> -### BEGIN INIT INFO
> -# Provides:          ovn-host
> -# Required-Start:    openvswitch-switch $remote_fs $syslog
> -# Required-Stop:     $remote_fs
> -# Default-Start:     2 3 4 5
> -# Default-Stop:      0 1 6
> -# Short-Description: OVN host components
> -# Description:       ovn-host provides the userspace
> -#                    components and utilities for OVN that can be run on
> -#                    every host/hypervisor.
> -### END INIT INFO
> -
> -test -x /usr/bin/ovn-controller  || exit 0
> -test -x /usr/share/openvswitch/scripts/ovn-ctl || exit 0
> -
> -_SYSTEMCTL_SKIP_REDIRECT=yes
> -SYSTEMCTL_SKIP_REDIRECT=yes
> -
> -. /usr/share/openvswitch/scripts/ovs-lib
> -if [ -e /etc/default/ovn-host ]; then
> -    . /etc/default/ovn-host
> -fi
> -
> -start () {
> -    set /usr/share/openvswitch/scripts/ovn-ctl ${1-start_controller}
> -    set "$@" $OVN_CTL_OPTS
> -    "$@" || exit $?
> -}
> -
> -case $1 in
> -    start)
> -        start
> -        ;;
> -    stop | force-stop)
> -        /usr/share/openvswitch/scripts/ovn-ctl stop_controller
> -        ;;
> -    restart)
> -        start restart_controller
> -        ;;
> -    status)
> -        /usr/share/openvswitch/scripts/ovn-ctl status_controller
> -        exit $?
> -        ;;
> -    reload | force-reload)
> -        ;;
> -    *)
> -        echo "Usage: $0 {start|stop|reload|force-reload|restart|status}"
> >&2
> -        exit 1
> -        ;;
> -esac
> -
> -exit 0
> diff --git a/debian/ovn-host.install b/debian/ovn-host.install
> deleted file mode 100644
> index d2de82fd9..000000000
> --- a/debian/ovn-host.install
> +++ /dev/null
> @@ -1 +0,0 @@
> -usr/bin/ovn-controller
> diff --git a/debian/ovn-host.manpages b/debian/ovn-host.manpages
> deleted file mode 100644
> index 4f9e7bc90..000000000
> --- a/debian/ovn-host.manpages
> +++ /dev/null
> @@ -1 +0,0 @@
> -ovn/controller/ovn-controller.8
> diff --git a/debian/ovn-host.postinst b/debian/ovn-host.postinst
> deleted file mode 100755
> index 4b3edeb75..000000000
> --- a/debian/ovn-host.postinst
> +++ /dev/null
> @@ -1,49 +0,0 @@
> -#!/bin/sh
> -# postinst script for ovn-host
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -# summary of how this script can be called:
> -#        * <postinst> `configure' <most-recently-configured-version>
> -#        * <old-postinst> `abort-upgrade' <new version>
> -#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
> -#          <new-version>
> -#        * <postinst> `abort-remove'
> -#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
> -#          <failed-install-package> <version> `removing'
> -#          <conflicting-package> <version>
> -# for details, see http://www.debian.org/doc/debian-policy/ or
> -# the debian-policy package
> -
> -
> -case "$1" in
> -    configure)
> -        DEFAULT=/etc/default/ovn-host
> -        TEMPLATE=/usr/share/ovn/host/default.template
> -        if ! test -e $DEFAULT; then
> -            cp $TEMPLATE $DEFAULT
> -        else
> -            for var in $(awk -F'[ :]' '/^# [_A-Z0-9]+:/{print $2}'
> $TEMPLATE)
> -            do
> -                if ! grep $var $DEFAULT >/dev/null 2>&1; then
> -                    echo >> $DEFAULT
> -                    sed -n "/$var:/,/$var=/p" $TEMPLATE >> $DEFAULT
> -                fi
> -            done
> -        fi
> -        ;;
> -
> -    abort-upgrade|abort-remove|abort-deconfigure)
> -        ;;
> -
> -    *)
> -        echo "postinst called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -#DEBHELPER#
> -
> -exit 0
> diff --git a/debian/ovn-host.postrm b/debian/ovn-host.postrm
> deleted file mode 100755
> index 4cceb9087..000000000
> --- a/debian/ovn-host.postrm
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -#!/bin/sh
> -# postrm script for ovn-host
> -#
> -# see: dh_installdeb(1)
> -
> -set -e
> -
> -# summary of how this script can be called:
> -#        * <postrm> `remove'
> -#        * <postrm> `purge'
> -#        * <old-postrm> `upgrade' <new-version>
> -#        * <new-postrm> `failed-upgrade' <old-version>
> -#        * <new-postrm> `abort-install'
> -#        * <new-postrm> `abort-install' <old-version>
> -#        * <new-postrm> `abort-upgrade' <old-version>
> -#        * <disappearer's-postrm> `disappear' <overwriter>
> -#          <overwriter-version>
> -# for details, see http://www.debian.org/doc/debian-policy/ or
> -# the debian-policy package
> -
> -
> -case "$1" in
> -    purge)
> -        rm -f /etc/default/ovn-host
> -        rm -f /var/log/openvswitch/ovn-controller.log* || true
> -        ;;
> -
> -    remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
> -        ;;
> -
> -    *)
> -        echo "postrm called with unknown argument \`$1'" >&2
> -        exit 1
> -        ;;
> -esac
> -
> -# dh_installdeb will replace this with shell code automatically
> -# generated by other debhelper scripts.
> -
> -#DEBHELPER#
> -
> -exit 0
> -
> -
> diff --git a/debian/ovn-host.template b/debian/ovn-host.template
> deleted file mode 100644
> index 7fd54efda..000000000
> --- a/debian/ovn-host.template
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -# This is a POSIX shell fragment                -*- sh -*-
> -
> -# OVN_CTL_OPTS: Extra options to pass to ovs-ctl.  This is, for example,
> -# a suitable place to specify --ovn-controller-wrapper=valgrind.
> -# OVN_CTL_OPTS=
> diff --git a/debian/rules b/debian/rules
> index 9d0a81f1a..77f3a1984 100755
> --- a/debian/rules
> +++ b/debian/rules
> @@ -53,12 +53,6 @@ override_dh_install-arch:
>         # openvswitch-switch
>         cp debian/openvswitch-switch.template
> debian/openvswitch-switch/usr/share/openvswitch/switch/default.template
>
> -       # ovn-host
> -       cp debian/ovn-host.template
> debian/ovn-host/usr/share/ovn/host/default.template
> -
> -       # ovn-central
> -       cp debian/ovn-central.template
> debian/ovn-central/usr/share/ovn/central/default.template
> -
>  override_dh_install-indep:
>         dh_install
>
> diff --git a/include/automake.mk b/include/automake.mk
> index 01031e88d..e982da87d 100644
> --- a/include/automake.mk
> +++ b/include/automake.mk
> @@ -11,7 +11,6 @@ include/odp-netlink-macros.h: include/odp-netlink.h \
>  EXTRA_DIST += build-aux/extract-odp-netlink-h
> build-aux/extract-odp-netlink-macros-h
>  CLEANFILES += include/odp-netlink.h include/odp-netlink-macros.h
>
> -include include/ovn/automake.mk
>  include include/openflow/automake.mk
>  include include/openvswitch/automake.mk
>  include include/sparse/automake.mk
> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> deleted file mode 100644
> index 63d3907d8..000000000
> --- a/include/ovn/actions.h
> +++ /dev/null
> @@ -1,622 +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.
> - */
> -
> -#ifndef OVN_ACTIONS_H
> -#define OVN_ACTIONS_H 1
> -
> -#include <stdbool.h>
> -#include <stdint.h>
> -#include "compiler.h"
> -#include "expr.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/uuid.h"
> -#include "util.h"
> -
> -struct expr;
> -struct lexer;
> -struct ofpbuf;
> -struct shash;
> -struct simap;
> -struct ovn_extend_table;
> -
> -/* List of OVN logical actions.
> - *
> - * This macro is used directly only internally by this header and its
> - * corresponding .c file, but the list is still of interest to developers.
> - *
> - * Each OVNACT invocation has the following parameters:
> - *
> - * 1. <ENUM>, used below in the enum definition of OVNACT_<ENUM>, and
> - *    elsewhere.
> - *
> - * 2. <STRUCT> corresponding to a structure "struct <STRUCT>", that must
> be a
> - *    defined below.  This structure must be an abstract definition of the
> - *    action.  Its first member must have type "struct ovnact" and name
> - *    "ovnact".  The structure must have a fixed length, that is, it may
> not
> - *    end with a flexible array member.
> - */
> -#define OVNACTS                                       \
> -    OVNACT(OUTPUT,            ovnact_null)            \
> -    OVNACT(NEXT,              ovnact_next)            \
> -    OVNACT(LOAD,              ovnact_load)            \
> -    OVNACT(MOVE,              ovnact_move)            \
> -    OVNACT(EXCHANGE,          ovnact_move)            \
> -    OVNACT(DEC_TTL,           ovnact_null)            \
> -    OVNACT(CT_NEXT,           ovnact_ct_next)         \
> -    OVNACT(CT_COMMIT,         ovnact_ct_commit)       \
> -    OVNACT(CT_DNAT,           ovnact_ct_nat)          \
> -    OVNACT(CT_SNAT,           ovnact_ct_nat)          \
> -    OVNACT(CT_LB,             ovnact_ct_lb)           \
> -    OVNACT(CT_CLEAR,          ovnact_null)            \
> -    OVNACT(CLONE,             ovnact_nest)            \
> -    OVNACT(ARP,               ovnact_nest)            \
> -    OVNACT(ICMP4,             ovnact_nest)            \
> -    OVNACT(ICMP4_ERROR,       ovnact_nest)            \
> -    OVNACT(ICMP6,             ovnact_nest)            \
> -    OVNACT(IGMP,              ovnact_null)            \
> -    OVNACT(TCP_RESET,         ovnact_nest)            \
> -    OVNACT(ND_NA,             ovnact_nest)            \
> -    OVNACT(ND_NA_ROUTER,      ovnact_nest)            \
> -    OVNACT(GET_ARP,           ovnact_get_mac_bind)    \
> -    OVNACT(PUT_ARP,           ovnact_put_mac_bind)    \
> -    OVNACT(GET_ND,            ovnact_get_mac_bind)    \
> -    OVNACT(PUT_ND,            ovnact_put_mac_bind)    \
> -    OVNACT(PUT_DHCPV4_OPTS,   ovnact_put_opts)        \
> -    OVNACT(PUT_DHCPV6_OPTS,   ovnact_put_opts)        \
> -    OVNACT(SET_QUEUE,         ovnact_set_queue)       \
> -    OVNACT(DNS_LOOKUP,        ovnact_dns_lookup)      \
> -    OVNACT(LOG,               ovnact_log)             \
> -    OVNACT(PUT_ND_RA_OPTS,    ovnact_put_opts)        \
> -    OVNACT(ND_NS,             ovnact_nest)            \
> -    OVNACT(SET_METER,         ovnact_set_meter)       \
> -    OVNACT(OVNFIELD_LOAD,     ovnact_load)            \
> -    OVNACT(CHECK_PKT_LARGER,  ovnact_check_pkt_larger) \
> -    OVNACT(TRIGGER_EVENT,     ovnact_controller_event)
> -
> -/* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
> -enum OVS_PACKED_ENUM ovnact_type {
> -#define OVNACT(ENUM, STRUCT) OVNACT_##ENUM,
> -    OVNACTS
> -#undef OVNACT
> -};
> -
> -/* Define N_OVNACTS to the number of types of ovnacts. */
> -enum {
> -#define OVNACT(ENUM, STRUCT) + 1
> -    N_OVNACTS = OVNACTS
> -#undef OVNACT
> -};
> -
> -/* Header for an action.
> - *
> - * Each action is a structure "struct ovnact_*" that begins with "struct
> - * ovnact", usually followed by other data that describes the action.
> Actions
> - * are padded out to a multiple of OVNACT_ALIGNTO bytes in length.
> - */
> -struct ovnact {
> -    /* We want the space advantage of an 8-bit type here on every
> -     * implementation, without giving up the advantage of having a useful
> type
> -     * on implementations that support packed enums. */
> -#ifdef HAVE_PACKED_ENUM
> -    enum ovnact_type type;      /* OVNACT_*. */
> -#else
> -    uint8_t type;               /* OVNACT_* */
> -#endif
> -    uint8_t pad;                /* Pad to multiple of 16 bits. */
> -
> -    uint16_t len;               /* Length of the action, in bytes,
> including
> -                                 * struct ovnact, excluding padding. */
> -};
> -BUILD_ASSERT_DECL(sizeof(struct ovnact) == 4);
> -
> -/* Alignment. */
> -#define OVNACT_ALIGNTO 8
> -#define OVNACT_ALIGN(SIZE) ROUND_UP(SIZE, OVNACT_ALIGNTO)
> -
> -/* Returns the ovnact following 'ovnact'. */
> -static inline struct ovnact *
> -ovnact_next(const struct ovnact *ovnact)
> -{
> -    return (void *) ((uint8_t *) ovnact + OVNACT_ALIGN(ovnact->len));
> -}
> -
> -struct ovnact *ovnact_next_flattened(const struct ovnact *);
> -
> -static inline struct ovnact *
> -ovnact_end(const struct ovnact *ovnacts, size_t ovnacts_len)
> -{
> -    return (void *) ((uint8_t *) ovnacts + ovnacts_len);
> -}
> -
> -/* Assigns POS to each ovnact, in turn, in the OVNACTS_LEN bytes of
> ovnacts
> - * starting at OVNACTS. */
> -#define OVNACT_FOR_EACH(POS, OVNACTS, OVNACTS_LEN)                      \
> -    for ((POS) = (OVNACTS); (POS) < ovnact_end(OVNACTS, OVNACTS_LEN);  \
> -         (POS) = ovnact_next(POS))
> -
> -static inline int
> -ovnacts_count(const struct ovnact *ovnacts, size_t ovnacts_len)
> -{
> -    uint8_t n_ovnacts = 0;
> -    if (ovnacts) {
> -        const struct ovnact *a;
> -
> -        OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
> -            n_ovnacts++;
> -        }
> -    }
> -    return n_ovnacts;
> -}
> -
> -/* Action structure for each OVNACT_*. */
> -
> -/* Action structure for actions that do not have any extra data beyond the
> - * action type. */
> -struct ovnact_null {
> -    struct ovnact ovnact;
> -};
> -
> -/* Logical pipeline in which a set of actions is executed. */
> -enum ovnact_pipeline {
> -    OVNACT_P_INGRESS,
> -    OVNACT_P_EGRESS,
> -};
> -
> -/* OVNACT_NEXT. */
> -struct ovnact_next {
> -    struct ovnact ovnact;
> -
> -    /* Arguments. */
> -    uint8_t ltable;                /* Logical table ID of next table. */
> -    enum ovnact_pipeline pipeline; /* Pipeline of next table. */
> -
> -    /* Information about the flow that the action is in.  This does not
> affect
> -     * behavior, since the implementation of "next" doesn't depend on the
> -     * source table or pipeline.  It does affect how ovnacts_format()
> prints
> -     * the action. */
> -    uint8_t src_ltable;                /* Logical table ID of source
> table. */
> -    enum ovnact_pipeline src_pipeline; /* Pipeline of source table. */
> -};
> -
> -/* OVNACT_LOAD. */
> -struct ovnact_load {
> -    struct ovnact ovnact;
> -    struct expr_field dst;
> -    union expr_constant imm;
> -};
> -
> -/* OVNACT_MOVE, OVNACT_EXCHANGE. */
> -struct ovnact_move {
> -    struct ovnact ovnact;
> -    struct expr_field lhs;
> -    struct expr_field rhs;
> -};
> -
> -/* OVNACT_CT_NEXT. */
> -struct ovnact_ct_next {
> -    struct ovnact ovnact;
> -    uint8_t ltable;                /* Logical table ID of next table. */
> -};
> -
> -/* OVNACT_CT_COMMIT. */
> -struct ovnact_ct_commit {
> -    struct ovnact ovnact;
> -    uint32_t ct_mark, ct_mark_mask;
> -    ovs_be128 ct_label, ct_label_mask;
> -};
> -
> -/* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */
> -struct ovnact_ct_nat {
> -    struct ovnact ovnact;
> -    ovs_be32 ip;
> -    uint8_t ltable;             /* Logical table ID of next table. */
> -};
> -
> -struct ovnact_ct_lb_dst {
> -    int family;
> -    union {
> -        struct in6_addr ipv6;
> -        ovs_be32 ipv4;
> -    };
> -    uint16_t port;
> -};
> -
> -/* OVNACT_CT_LB. */
> -struct ovnact_ct_lb {
> -    struct ovnact ovnact;
> -    struct ovnact_ct_lb_dst *dsts;
> -    size_t n_dsts;
> -    uint8_t ltable;             /* Logical table ID of next table. */
> -};
> -
> -/* OVNACT_ARP, OVNACT_ND_NA, OVNACT_CLONE. */
> -struct ovnact_nest {
> -    struct ovnact ovnact;
> -    struct ovnact *nested;
> -    size_t nested_len;
> -};
> -
> -/* OVNACT_GET_ARP, OVNACT_GET_ND. */
> -struct ovnact_get_mac_bind {
> -    struct ovnact ovnact;
> -    struct expr_field port;     /* Logical port name. */
> -    struct expr_field ip;       /* 32-bit or 128-bit IP address. */
> -};
> -
> -/* OVNACT_PUT_ARP, ONVACT_PUT_ND. */
> -struct ovnact_put_mac_bind {
> -    struct ovnact ovnact;
> -    struct expr_field port;     /* Logical port name. */
> -    struct expr_field ip;       /* 32-bit or 128-bit IP address. */
> -    struct expr_field mac;      /* 48-bit Ethernet address. */
> -};
> -
> -struct ovnact_gen_option {
> -    const struct gen_opts_map *option;
> -    struct expr_constant_set value;
> -};
> -
> -/* OVNACT_PUT_DHCPV4_OPTS, OVNACT_PUT_DHCPV6_OPTS. */
> -struct ovnact_put_opts {
> -    struct ovnact ovnact;
> -    struct expr_field dst;      /* 1-bit destination field. */
> -    struct ovnact_gen_option *options;
> -    size_t n_options;
> -};
> -
> -/* Valid arguments to SET_QUEUE action.
> - *
> - * QDISC_MIN_QUEUE_ID is the default queue, so user-defined queues should
> - * start at QDISC_MIN_QUEUE_ID+1. */
> -#define QDISC_MIN_QUEUE_ID  0
> -#define QDISC_MAX_QUEUE_ID  0xf000
> -
> -/* OVNACT_SET_QUEUE. */
> -struct ovnact_set_queue {
> -    struct ovnact ovnact;
> -    uint16_t queue_id;
> -};
> -
> -/* OVNACT_DNS_LOOKUP. */
> -struct ovnact_dns_lookup {
> -    struct ovnact ovnact;
> -    struct expr_field dst;      /* 1-bit destination field. */
> -};
> -
> -/* OVNACT_LOG. */
> -struct ovnact_log {
> -    struct ovnact ovnact;
> -    uint8_t verdict;            /* One of LOG_VERDICT_*. */
> -    uint8_t severity;           /* One of LOG_SEVERITY_*. */
> -    char *name;
> -    char *meter;
> -};
> -
> -/* OVNACT_SET_METER. */
> -struct ovnact_set_meter {
> -    struct ovnact ovnact;
> -    uint64_t rate;                   /* rate field, in kbps. */
> -    uint64_t burst;                  /* burst rate field, in kbps. */
> -};
> -
> -/* OVNACT_CHECK_IP_PKT_LARGER. */
> -struct ovnact_check_pkt_larger {
> -    struct ovnact ovnact;
> -    uint16_t pkt_len;
> -    struct expr_field dst;      /* 1-bit destination field. */
> -};
> -
> -/* OVNACT_EVENT. */
> -struct ovnact_controller_event {
> -    struct ovnact ovnact;
> -    int event_type;   /* controller event type */
> -    struct ovnact_gen_option *options;
> -    size_t n_options;
> -};
> -
> -/* Internal use by the helpers below. */
> -void ovnact_init(struct ovnact *, enum ovnact_type, size_t len);
> -void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len);
> -
> -/* For each OVNACT_<ENUM> with a corresponding struct <STRUCT>, this
> defines
> - * the following commonly useful functions:
> - *
> - *   struct <STRUCT> *ovnact_put_<ENUM>(struct ofpbuf *ovnacts);
> - *
> - *     Appends a new 'ovnact', of length OVNACT_<ENUM>_SIZE, to 'ovnacts',
> - *     initializes it with ovnact_init_<ENUM>(), and returns it.  Also
> sets
> - *     'ovnacts->header' to the returned action.
> - *
> - *   struct <STRUCT> *ovnact_get_<ENUM>(const struct ovnact *ovnact);
> - *
> - *     Returns 'ovnact' cast to "struct <STRUCT> *".  'ovnact->type' must
> be
> - *     OVNACT_<ENUM>.
> - *
> - * as well as the following more rarely useful definitions:
> - *
> - *   void ovnact_init_<ENUM>(struct <STRUCT> *ovnact);
> - *
> - *     Initializes the parts of 'ovnact' that identify it as having type
> - *     OVNACT_<ENUM> and length OVNACT_<ENUM>_SIZE and zeros the rest.
> - *
> - *   <ENUM>_SIZE
> - *
> - *     The size of the action structure, that is, sizeof(struct <STRUCT>)
> - *     rounded up to a multiple of OVNACT_ALIGNTO.
> - */
> -#define OVNACT(ENUM, STRUCT)                                            \
> -    BUILD_ASSERT_DECL(offsetof(struct STRUCT, ovnact) == 0);            \
> -                                                                        \
> -    enum { OVNACT_##ENUM##_SIZE = OVNACT_ALIGN(sizeof(struct STRUCT)) }; \
> -                                                                        \
> -    static inline struct STRUCT *                                       \
> -    ovnact_get_##ENUM(const struct ovnact *ovnact)                      \
> -    {                                                                   \
> -        ovs_assert(ovnact->type == OVNACT_##ENUM);                      \
> -        return ALIGNED_CAST(struct STRUCT *, ovnact);                   \
> -    }                                                                   \
> -                                                                        \
> -    static inline struct STRUCT *                                       \
> -    ovnact_put_##ENUM(struct ofpbuf *ovnacts)                           \
> -    {                                                                   \
> -        return ovnact_put(ovnacts, OVNACT_##ENUM,                       \
> -                          OVNACT_##ENUM##_SIZE);                        \
> -    }                                                                   \
> -                                                                        \
> -    static inline void                                                  \
> -    ovnact_init_##ENUM(struct STRUCT *ovnact)                           \
> -    {                                                                   \
> -        ovnact_init(&ovnact->ovnact, OVNACT_##ENUM,                     \
> -                    OVNACT_##ENUM##_SIZE);                              \
> -    }
> -OVNACTS
> -#undef OVNACT
> -
> -enum action_opcode {
> -    /* "arp { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_ARP,
> -
> -    /* "put_arp(port, ip, mac)"
> -     *
> -     * Arguments are passed through the packet metadata and data, as
> follows:
> -     *
> -     *     MFF_REG0 = ip
> -     *     MFF_LOG_INPORT = port
> -     *     MFF_ETH_SRC = mac
> -     */
> -    ACTION_OPCODE_PUT_ARP,
> -
> -    /* "result = put_dhcp_opts(offer_ip, option, ...)".
> -     *
> -     * Arguments follow the action_header, in this format:
> -     *   - A 32-bit or 64-bit OXM header designating the result field.
> -     *   - A 32-bit integer specifying a bit offset within the result
> field.
> -     *   - The 32-bit DHCP offer IP.
> -     *   - Any number of DHCP options.
> -     */
> -    ACTION_OPCODE_PUT_DHCP_OPTS,
> -
> -    /* "nd_na { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_ND_NA,
> -
> -    /* "put_nd(port, ip6, mac)"
> -     *
> -     * Arguments are passed through the packet metadata and data, as
> follows:
> -     *
> -     *     MFF_XXREG0 = ip6
> -     *     MFF_LOG_INPORT = port
> -     *     MFF_ETH_SRC = mac
> -     */
> -    ACTION_OPCODE_PUT_ND,
> -
> -    /* "result = put_dhcpv6_opts(option, ...)".
> -     *
> -     * Arguments follow the action_header, in this format:
> -     *   - A 32-bit or 64-bit OXM header designating the result field.
> -     *   - A 32-bit integer specifying a bit offset within the result
> field.
> -     *   - Any number of DHCPv6 options.
> -     */
> -    ACTION_OPCODE_PUT_DHCPV6_OPTS,
> -
> -    /* "result = dns_lookup()".
> -     * Arguments follow the action_header, in this format:
> -     *   - A 32-bit or 64-bit OXM header designating the result field.
> -     *   - A 32-bit integer specifying a bit offset within the result
> field.
> -     *
> -     */
> -    ACTION_OPCODE_DNS_LOOKUP,
> -
> -    /* "log(arguments)".
> -     *
> -     * Arguments are as follows:
> -     *   - An 8-bit verdict.
> -     *   - An 8-bit severity.
> -     *   - A variable length string containing the name.
> -     */
> -    ACTION_OPCODE_LOG,
> -
> -    /* "result = put_nd_ra_opts(option, ...)".
> -     * Arguments follow the action_header, in this format:
> -     *   - A 32-bit or 64-bit OXM header designating the result field.
> -     *   - A 32-bit integer specifying a bit offset within the result
> field.
> -     *   - Any number of ICMPv6 options.
> -     */
> -    ACTION_OPCODE_PUT_ND_RA_OPTS,
> -
> -    /* "nd_ns { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_ND_NS,
> -
> -    /* "icmp4 { ...actions... } and icmp6 { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_ICMP,
> -
> -    /* "tcp_reset { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_TCP_RESET,
> -
> -    /* "nd_na_router { ...actions... }" with rso flag 'ND_RSO_ROUTER' set.
> -        *
> -        * The actions, in OpenFlow 1.3 format, follow the action_header.
> -        */
> -    ACTION_OPCODE_ND_NA_ROUTER,
> -
> -     /* MTU value (to put in the icmp4 header field - frag_mtu) follow the
> -     * action header. */
> -    ACTION_OPCODE_PUT_ICMP4_FRAG_MTU,
> -
> -    /* "icmp4_error { ...actions... }".
> -     *
> -     * The actions, in OpenFlow 1.3 format, follow the action_header.
> -     */
> -    ACTION_OPCODE_ICMP4_ERROR,
> -
> -    /* "trigger_event (event_type)" */
> -    ACTION_OPCODE_EVENT,
> -
> -    /* "igmp".
> -     *
> -     * Snoop IGMP, learn the multicast participants
> -     */
> -    ACTION_OPCODE_IGMP,
> -};
> -
> -/* Header. */
> -struct action_header {
> -    ovs_be32 opcode;            /* One of ACTION_OPCODE_* */
> -    uint8_t pad[4];
> -};
> -BUILD_ASSERT_DECL(sizeof(struct action_header) == 8);
> -
> -OVS_PACKED(
> -struct ovnfield_act_header {
> -    ovs_be16 id; /* one of enum ovnfield_id. */
> -    ovs_be16 len; /* Length of the ovnfield data. */
> -});
> -
> -struct ovnact_parse_params {
> -    /* A table of "struct expr_symbol"s to support (as one would provide
> to
> -     * expr_parse()). */
> -    const struct shash *symtab;
> -
> -    /* hmap of 'struct gen_opts_map' to support 'put_dhcp_opts' action */
> -    const struct hmap *dhcp_opts;
> -
> -    /* hmap of 'struct gen_opts_map'  to support 'put_dhcpv6_opts' action
> */
> -    const struct hmap *dhcpv6_opts;
> -
> -    /* hmap of 'struct gen_opts_map' to support 'put_nd_ra_opts' action */
> -    const struct hmap *nd_ra_opts;
> -
> -    /* Array of hmap of 'struct gen_opts_map' to support 'trigger_event'
> -     * action */
> -    const struct controller_event_options *controller_event_opts;
> -
> -    /* Each OVN flow exists in a logical table within a logical pipeline.
> -     * These parameters express this context for a set of OVN actions
> being
> -     * parsed:
> -     *
> -     *     - 'n_tables' is the number of tables in the logical ingress and
> -     *        egress pipelines, that is, "next" may specify a table less
> than
> -     *        or equal to 'n_tables'.  If 'n_tables' is 0 then "next" is
> -     *        disallowed entirely.
> -     *
> -     *     - 'cur_ltable' is the logical table of the current flow, within
> -     *       'pipeline'.  If cur_ltable + 1 < n_tables, then this defines
> the
> -     *       default table that "next" will jump to.
> -     *
> -     *     - 'pipeline' is the logical pipeline.  It is the default
> pipeline to
> -     *       which 'next' will jump.  If 'pipeline' is OVNACT_P_EGRESS,
> then
> -     *       'next' will also be able to jump into the ingress pipeline,
> but
> -     *       the reverse is not true. */
> -    enum ovnact_pipeline pipeline; /* Logical pipeline. */
> -    uint8_t n_tables;              /* Number of logical flow tables. */
> -    uint8_t cur_ltable;            /* 0 <= cur_ltable < n_tables. */
> -};
> -
> -bool ovnacts_parse(struct lexer *, const struct ovnact_parse_params *,
> -                    struct ofpbuf *ovnacts, struct expr **prereqsp);
> -char *ovnacts_parse_string(const char *s, const struct
> ovnact_parse_params *,
> -                           struct ofpbuf *ovnacts, struct expr **prereqsp)
> -    OVS_WARN_UNUSED_RESULT;
> -
> -void ovnacts_format(const struct ovnact[], size_t ovnacts_len, struct ds
> *);
> -
> -struct ovnact_encode_params {
> -    /* Looks up logical port 'port_name'.  If found, stores its port
> number in
> -     * '*portp' and returns true; otherwise, returns false. */
> -    bool (*lookup_port)(const void *aux, const char *port_name,
> -                        unsigned int *portp);
> -    const void *aux;
> -
> -    /* 'true' if the flow is for a switch. */
> -    bool is_switch;
> -
> -    /* A struct to figure out the group_id for group actions. */
> -    struct ovn_extend_table *group_table;
> -
> -    /* A struct to figure out the meter_id for meter actions. */
> -    struct ovn_extend_table *meter_table;
> -
> -    /* The logical flow uuid that drove this action. */
> -    struct uuid lflow_uuid;
> -
> -    /* OVN maps each logical flow table (ltable), one-to-one, onto a
> physical
> -     * OpenFlow flow table (ptable).  A number of parameters describe this
> -     * mapping and data related to flow tables:
> -     *
> -     *     - 'pipeline' is the logical pipeline in which the actions are
> -     *       executing.
> -     *
> -     *     - 'ingress_ptable' is the OpenFlow table that corresponds to
> OVN
> -     *       ingress table 0.
> -     *
> -     *     - 'egress_ptable' is the OpenFlow table that corresponds to OVN
> -     *       egress table 0.
> -     *
> -     *     - 'output_ptable' should be the OpenFlow table to which the
> logical
> -     *       "output" action will resubmit.
> -     *
> -     *     - 'mac_bind_ptable' should be the OpenFlow table used to track
> MAC
> -     *       bindings. */
> -    enum ovnact_pipeline pipeline; /* Logical pipeline. */
> -    uint8_t ingress_ptable;     /* First OpenFlow ingress table. */
> -    uint8_t egress_ptable;      /* First OpenFlow egress table. */
> -    uint8_t output_ptable;      /* OpenFlow table for 'output' to
> resubmit. */
> -    uint8_t mac_bind_ptable;    /* OpenFlow table for 'get_arp'/'get_nd'
> to
> -                                   resubmit. */
> -};
> -
> -void ovnacts_encode(const struct ovnact[], size_t ovnacts_len,
> -                    const struct ovnact_encode_params *,
> -                    struct ofpbuf *ofpacts);
> -
> -void ovnacts_free(struct ovnact[], size_t ovnacts_len);
> -
> -#endif /* ovn/actions.h */
> diff --git a/include/ovn/automake.mk b/include/ovn/automake.mk
> deleted file mode 100644
> index 54b0e2c0e..000000000
> --- a/include/ovn/automake.mk
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -ovnincludedir = $(includedir)/ovn
> -ovninclude_HEADERS = \
> -       include/ovn/actions.h \
> -       include/ovn/expr.h \
> -       include/ovn/lex.h  \
> -       include/ovn/logical-fields.h
> diff --git a/include/ovn/expr.h b/include/ovn/expr.h
> deleted file mode 100644
> index 22f633e57..000000000
> --- a/include/ovn/expr.h
> +++ /dev/null
> @@ -1,518 +0,0 @@
> -/*
> - * Copyright (c) 2015, 2016 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.
> - */
> -
> -#ifndef OVN_EXPR_H
> -#define OVN_EXPR_H 1
> -
> -/* OVN matching expression tree
> - * ============================
> - *
> - * The data structures here form an abstract expression tree for matching
> - * expressions in OVN.
> - *
> - * The abstract syntax tree representation of a matching expression is
> one of:
> - *
> - *    - A Boolean literal ("true" or "false").
> - *
> - *    - A comparison of a field (or part of a field) against a constant
> - *      with one of the operators == != < <= > >=.
> - *
> - *    - The logical AND or OR of two or more matching expressions.
> - *
> - * Literals and comparisons are called "terminal" nodes, logical AND and
> OR
> - * nodes are "nonterminal" nodes.
> - *
> - * The syntax for expressions includes a few other concepts that are not
> part
> - * of the abstract syntax tree.  In these examples, x is a field, a, b,
> and c
> - * are constants, and e1 and e2 are arbitrary expressions:
> - *
> - *    - Logical NOT.  The parser implements NOT by inverting the sense of
> the
> - *      operand: !(x == a) becomes x != a, !(e1 && e2) becomes !e1 ||
> !e2, and
> - *      so on.
> - *
> - *    - Set membership.  The parser translates x == {a, b, c} into
> - *      x == a || x == b || x == c.
> - *
> - *    - Reversed comparisons.  The parser translates a < x into x > a.
> - *
> - *    - Range expressions.  The parser translates a < x < b into
> - *      x > a && x < b.
> - */
> -
> -#include "classifier.h"
> -#include "lex.h"
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/list.h"
> -#include "openvswitch/match.h"
> -#include "openvswitch/meta-flow.h"
> -#include "logical-fields.h"
> -
> -struct ds;
> -struct expr;
> -struct flow;
> -struct ofpbuf;
> -struct shash;
> -struct simap;
> -struct sset;
> -
> -/* "Measurement level" of a field.  See "Level of Measurement" in the
> large
> - * comment on struct expr_symbol below for more information. */
> -enum expr_level {
> -    EXPR_L_NOMINAL,
> -
> -    /* Boolean values are nominal, however because of their simple nature
> OVN
> -     * can allow both equality and inequality tests on them. */
> -    EXPR_L_BOOLEAN,
> -
> -    /* Ordinal values can at least be ordered on a scale.  OVN allows
> equality
> -     * and inequality and relational tests on ordinal values.  These are
> the
> -     * fields on which OVS allows bitwise matching. */
> -    EXPR_L_ORDINAL
> -};
> -
> -const char *expr_level_to_string(enum expr_level);
> -
> -/* A symbol.
> - *
> - *
> - * Name
> - * ====
> - *
> - * Every symbol must have a name.  To be useful, the name must satisfy the
> - * lexer's syntax for an identifier.
> - *
> - *
> - * Width
> - * =====
> - *
> - * Every symbol has a width.  For integer symbols, this is the number of
> bits
> - * in the value; for string symbols, this is 0.
> - *
> - *
> - * Types
> - * =====
> - *
> - * There are three kinds of symbols:
> - *
> - *   Fields:
> - *
> - *     One might, for example, define a field named "vlan.tci" to refer to
> - *     MFF_VLAN_TCI.  'field' specifies the field.
> - *
> - *     'parent' and 'predicate' are NULL, and 'parent_ofs' is 0.
> - *
> - *     Integer fields can be nominal or ordinal (see below).  String
> fields are
> - *     always nominal.
> - *
> - *   Subfields:
> - *
> - *     'parent' specifies the field (which may itself be a subfield,
> - *     recursively) in which the subfield is embedded, and 'parent_ofs' a
> - *     bitwise offset from the least-significant bit of the parent.  The
> - *     subfield can contain a subset of the bits of the parent or all of
> them
> - *     (in the latter case the subfield is really just a synonym for the
> - *     parent).
> - *
> - *     'field' and 'predicate' are NULL.
> - *
> - *     Only ordinal fields (see below) may have subfields, and subfields
> are
> - *     always ordinal.
> - *
> - *   Predicates:
> - *
> - *     A predicate is an arbitrary Boolean expression that can be used in
> an
> - *     expression much like a 1-bit field.  'predicate' specifies the
> Boolean
> - *     expression, e.g. "ip4" might expand to "eth.type == 0x800".  The
> - *     epxression might refer to other predicates, e.g. "icmp4" might
> expand to
> - *     "ip4 && ip4.proto == 1".
> - *
> - *     'field' and 'parent' are NULL, and 'parent_ofs' is 0.
> - *
> - *     A predicate that refers to any nominal field or predicate (see
> below) is
> - *     nominal; other predicates have Boolean level of measurement.
> - *
> - *
> - * Level of Measurement
> - * ====================
> - *
> - * See http://en.wikipedia.org/wiki/Level_of_measurement for the
> statistical
> - * concept on which this classification is based.  There are three levels:
> - *
> - *   Ordinal:
> - *
> - *     In statistics, ordinal values can be ordered on a scale.  Here, we
> - *     consider a field (or subfield) to be ordinal if its bits can be
> examined
> - *     individually.  This is true for the OpenFlow fields that OpenFlow
> or
> - *     Open vSwitch makes "maskable".
> - *
> - *     OVN supports all the usual arithmetic relations (== != < <= > >=)
> on
> - *     ordinal fields and their subfields, because all of these can be
> - *     implemented as collections of bitwise tests.
> - *
> - *   Nominal:
> - *
> - *     In statistics, nominal values cannot be usefully compared except
> for
> - *     equality.  This is true of OpenFlow port numbers, Ethernet types,
> and IP
> - *     protocols are examples: all of these are just identifiers assigned
> - *     arbitrarily with no deeper meaning.  In OpenFlow and Open vSwitch,
> bits
> - *     in these fields generally aren't individually addressable.
> - *
> - *     OVN only supports arithmetic tests for equality on nominal fields,
> - *     because OpenFlow and Open vSwitch provide no way for a flow to
> - *     efficiently implement other comparisons on them.  (A test for
> inequality
> - *     can be sort of built out of two flows with different priorities,
> but OVN
> - *     matching expressions always generate flows with a single priority.)
> - *
> - *     String fields are always nominal.
> - *
> - *   Boolean:
> - *
> - *     A nominal field that has only two values, 0 and 1, is somewhat
> - *     exceptional, since it is easy to support both equality and
> inequality
> - *     tests on such a field: either one can be implemented as a test for
> 0 or
> - *     1.
> - *
> - *     Only predicates (see above) have a Boolean level of measurement.
> - *
> - *     This isn't a standard level of measurement.
> - *
> - *
> - * Prerequisites
> - * =============
> - *
> - * Any symbol can have prerequisites, which are specified as a string
> giving an
> - * additional expression that must be true whenever the symbol is
> referenced.
> - * For example, the "icmp4.type" symbol might have prerequisite "icmp4",
> which
> - * would cause an expression "icmp4.type == 0" to be interpreted as
> "icmp4.type
> - * == 0 && icmp4", which would in turn expand to "icmp4.type == 0 &&
> eth.type
> - * == 0x800 && ip4.proto == 1" (assuming "icmp4" is a predicate defined as
> - * suggested under "Types" above).
> - *
> - *
> - * Crossproducting
> - * ===============
> - *
> - * Ordinarily OVN is willing to consider using any field as a dimension
> in the
> - * Open vSwitch "conjunctive match" extension (see ovs-ofctl(8)).
> However,
> - * some fields can't actually be used that way because they are necessary
> as
> - * prerequisites.  For example, from an expression like "tcp.src ==
> {1,2,3}
> - * && tcp.dst == {4,5,6}", OVN might naturally generate flows like this:
> - *
> - *     conj_id=1,actions=...
> - *     ip,actions=conjunction(1,1/3)
> - *     ip6,actions=conjunction(1,1/3)
> - *     tp_src=1,actions=conjunction(1,2/3)
> - *     tp_src=2,actions=conjunction(1,2/3)
> - *     tp_src=3,actions=conjunction(1,2/3)
> - *     tp_dst=4,actions=conjunction(1,3/3)
> - *     tp_dst=5,actions=conjunction(1,3/3)
> - *     tp_dst=6,actions=conjunction(1,3/3)
> - *
> - * but that's not valid because any flow that matches on tp_src or tp_dst
> must
> - * also match on either ip or ip6.  Thus, one would mark eth.type as "must
> - * crossproduct", to force generating flows like this:
> - *
> - *     conj_id=1,actions=...
> - *     ip,tp_src=1,actions=conjunction(1,1/2)
> - *     ip,tp_src=2,actions=conjunction(1,1/2)
> - *     ip,tp_src=3,actions=conjunction(1,1/2)
> - *     ip6,tp_src=1,actions=conjunction(1,1/2)
> - *     ip6,tp_src=2,actions=conjunction(1,1/2)
> - *     ip6,tp_src=3,actions=conjunction(1,1/2)
> - *     ip,tp_dst=4,actions=conjunction(1,2/2)
> - *     ip,tp_dst=5,actions=conjunction(1,2/2)
> - *     ip,tp_dst=6,actions=conjunction(1,2/2)
> - *     ip6,tp_dst=4,actions=conjunction(1,2/2)
> - *     ip6,tp_dst=5,actions=conjunction(1,2/2)
> - *     ip6,tp_dst=6,actions=conjunction(1,2/2)
> - *
> - * which are acceptable.
> - */
> -struct expr_symbol {
> -    char *name;
> -    int width;
> -
> -    const struct mf_field *field;     /* Fields only, otherwise NULL. */
> -    const struct ovn_field *ovn_field;  /* OVN Fields only, otherwise
> NULL. */
> -    const struct expr_symbol *parent; /* Subfields only, otherwise NULL.
> */
> -    int parent_ofs;                   /* Subfields only, otherwise 0. */
> -    char *predicate;                  /* Predicates only, otherwise NULL.
> */
> -
> -    enum expr_level level;
> -
> -    char *prereqs;
> -    bool must_crossproduct;
> -    bool rw;
> -};
> -
> -void expr_symbol_format(const struct expr_symbol *, struct ds *);
> -
> -/* A reference to a symbol or a subfield of a symbol.
> - *
> - * For string fields, ofs and n_bits are 0. */
> -struct expr_field {
> -    const struct expr_symbol *symbol; /* The symbol. */
> -    int ofs;                          /* Starting bit offset. */
> -    int n_bits;                       /* Number of bits. */
> -};
> -
> -bool expr_field_parse(struct lexer *, const struct shash *symtab,
> -                      struct expr_field *, struct expr **prereqsp);
> -void expr_field_format(const struct expr_field *, struct ds *);
> -
> -struct expr_symbol *expr_symtab_add_field(struct shash *symtab,
> -                                          const char *name, enum
> mf_field_id,
> -                                          const char *prereqs,
> -                                          bool must_crossproduct);
> -struct expr_symbol *expr_symtab_add_subfield(struct shash *symtab,
> -                                             const char *name,
> -                                             const char *prereqs,
> -                                             const char *subfield);
> -struct expr_symbol *expr_symtab_add_string(struct shash *symtab,
> -                                           const char *name, enum
> mf_field_id,
> -                                           const char *prereqs);
> -struct expr_symbol *expr_symtab_add_predicate(struct shash *symtab,
> -                                              const char *name,
> -                                              const char *expansion);
> -struct expr_symbol *expr_symtab_add_ovn_field(struct shash *symtab,
> -                                              const char *name,
> -                                              enum ovn_field_id id);
> -void expr_symtab_destroy(struct shash *symtab);
> -
> -/* Expression type. */
> -enum expr_type {
> -    EXPR_T_CMP,                 /* Compare symbol with constant. */
> -    EXPR_T_AND,                 /* Logical AND of 2 or more
> subexpressions. */
> -    EXPR_T_OR,                  /* Logical OR of 2 or more
> subexpressions. */
> -    EXPR_T_BOOLEAN,             /* True or false constant. */
> -    EXPR_T_CONDITION,           /* Conditional to be evaluated in the
> -                                 * controller during expr_simplify(),
> -                                 * prior to constructing OpenFlow
> matches. */
> -};
> -
> -/* Expression condition type. */
> -enum expr_cond_type {
> -    EXPR_COND_CHASSIS_RESIDENT, /* Check if specified logical port name is
> -                                 * resident on the controller chassis. */
> -};
> -
> -/* Relational operator. */
> -enum expr_relop {
> -    EXPR_R_EQ,                  /* == */
> -    EXPR_R_NE,                  /* != */
> -    EXPR_R_LT,                  /* < */
> -    EXPR_R_LE,                  /* <= */
> -    EXPR_R_GT,                  /* > */
> -    EXPR_R_GE,                  /* >= */
> -};
> -const char *expr_relop_to_string(enum expr_relop);
> -bool expr_relop_from_token(enum lex_type type, enum expr_relop *relop);
> -
> -/* An abstract syntax tree for a matching expression.
> - *
> - * The expression code maintains and relies on a few important invariants:
> - *
> - *     - An EXPR_T_AND or EXPR_T_OR node never has a child of the same
> type.
> - *       (Any such children could be merged into their parent.)  A node
> may
> - *       have grandchildren of its own type.
> - *
> - *       As a consequence, every nonterminal node at the same distance
> from the
> - *       root has the same type.
> - *
> - *     - EXPR_T_AND and EXPR_T_OR nodes must have at least two children.
> - *
> - *     - An EXPR_T_CMP node always has a nonzero mask, and never has a
> 1-bit
> - *       in its value in a position where the mask is a 0-bit.
> - *
> - * The expr_honors_invariants() function can check invariants. */
> -struct expr {
> -    struct ovs_list node;       /* In parent EXPR_T_AND or EXPR_T_OR if
> any. */
> -    enum expr_type type;        /* Expression type. */
> -
> -    union {
> -        /* EXPR_T_CMP.
> -         *
> -         * The symbol is on the left, e.g. "field < constant". */
> -        struct {
> -            const struct expr_symbol *symbol;
> -            enum expr_relop relop;
> -
> -            union {
> -                char *string;
> -                struct {
> -                    union mf_subvalue value;
> -                    union mf_subvalue mask;
> -                };
> -            };
> -        } cmp;
> -
> -        /* EXPR_T_AND, EXPR_T_OR. */
> -        struct ovs_list andor;
> -
> -        /* EXPR_T_BOOLEAN. */
> -        bool boolean;
> -
> -        /* EXPR_T_CONDITION. */
> -        struct {
> -            enum expr_cond_type type;
> -            bool not;
> -            /* XXX Should arguments for conditions be generic? */
> -            char *string;
> -        } cond;
> -    };
> -};
> -
> -struct expr *expr_create_boolean(bool b);
> -struct expr *expr_create_andor(enum expr_type);
> -struct expr *expr_combine(enum expr_type, struct expr *a, struct expr *b);
> -
> -static inline struct expr *
> -expr_from_node(const struct ovs_list *node)
> -{
> -    return CONTAINER_OF(node, struct expr, node);
> -}
> -
> -void expr_format(const struct expr *, struct ds *);
> -void expr_print(const struct expr *);
> -struct expr *expr_parse(struct lexer *, const struct shash *symtab,
> -                        const struct shash *addr_sets,
> -                        const struct shash *port_groups,
> -                        struct sset *addr_sets_ref);
> -struct expr *expr_parse_string(const char *, const struct shash *symtab,
> -                               const struct shash *addr_sets,
> -                               const struct shash *port_groups,
> -                               struct sset *addr_sets_ref,
> -                               char **errorp);
> -
> -struct expr *expr_clone(struct expr *);
> -void expr_destroy(struct expr *);
> -
> -struct expr *expr_annotate(struct expr *, const struct shash *symtab,
> -                           char **errorp);
> -struct expr *expr_simplify(struct expr *,
> -                           bool (*is_chassis_resident)(const void *c_aux,
> -                                                       const char
> *port_name),
> -                           const void *c_aux);
> -struct expr *expr_normalize(struct expr *);
> -
> -bool expr_honors_invariants(const struct expr *);
> -bool expr_is_simplified(const struct expr *);
> -bool expr_is_normalized(const struct expr *);
> -
> -char *expr_parse_microflow(const char *, const struct shash *symtab,
> -                           const struct shash *addr_sets,
> -                           const struct shash *port_groups,
> -                           bool (*lookup_port)(const void *aux,
> -                                               const char *port_name,
> -                                               unsigned int *portp),
> -                           const void *aux, struct flow *uflow)
> -    OVS_WARN_UNUSED_RESULT;
> -
> -bool expr_evaluate(const struct expr *, const struct flow *uflow,
> -                   bool (*lookup_port)(const void *aux, const char
> *port_name,
> -                                       unsigned int *portp),
> -                   const void *aux);
> -
> -/* Converting expressions to OpenFlow flows. */
> -
> -/* An OpenFlow match generated from a Boolean expression.  See
> - * expr_to_matches() for more information. */
> -struct expr_match {
> -    struct hmap_node hmap_node;
> -    struct match match;
> -    struct cls_conjunction *conjunctions;
> -    size_t n, allocated;
> -};
> -
> -uint32_t expr_to_matches(const struct expr *,
> -                         bool (*lookup_port)(const void *aux,
> -                                             const char *port_name,
> -                                             unsigned int *portp),
> -                         const void *aux,
> -                         struct hmap *matches);
> -void expr_matches_destroy(struct hmap *matches);
> -void expr_matches_print(const struct hmap *matches, FILE *);
> -
> -/* Action parsing helper. */
> -
> -char *expr_type_check(const struct expr_field *, int n_bits, bool rw)
> -    OVS_WARN_UNUSED_RESULT;
> -struct mf_subfield expr_resolve_field(const struct expr_field *);
> -
> -/* Type of a "union expr_constant" or "struct expr_constant_set". */
> -enum expr_constant_type {
> -    EXPR_C_INTEGER,
> -    EXPR_C_STRING
> -};
> -
> -/* A string or integer constant (one must know which from context). */
> -union expr_constant {
> -    /* Integer constant.
> -     *
> -     * The width of a constant isn't always clear, e.g. if you write "1",
> -     * there's no way to tell whether you mean for that to be a 1-bit
> constant
> -     * or a 128-bit constant or somewhere in between. */
> -    struct {
> -        union mf_subvalue value;
> -        union mf_subvalue mask; /* Only initialized if 'masked'. */
> -        bool masked;
> -
> -        enum lex_format format; /* From the constant's lex_token. */
> -    };
> -
> -    /* Null-terminated string constant. */
> -    char *string;
> -};
> -
> -bool expr_constant_parse(struct lexer *, const struct expr_field *,
> -                         union expr_constant *);
> -void expr_constant_format(const union expr_constant *,
> -                          enum expr_constant_type, struct ds *);
> -void expr_constant_destroy(const union expr_constant *,
> -                           enum expr_constant_type);
> -
> -/* A collection of "union expr_constant"s of the same type. */
> -struct expr_constant_set {
> -    union expr_constant *values;  /* Constants. */
> -    size_t n_values;              /* Number of constants. */
> -    enum expr_constant_type type; /* Type of the constants. */
> -    bool in_curlies;              /* Whether the constants were in {}. */
> -};
> -
> -bool expr_constant_set_parse(struct lexer *, struct expr_constant_set *);
> -void expr_constant_set_format(const struct expr_constant_set *, struct ds
> *);
> -void expr_constant_set_destroy(struct expr_constant_set *cs);
> -
> -
> -/* Constant sets.
> - *
> - * For example, instead of referring to a set of IP addresses as:
> - *    {addr1, addr2, ..., addrN}
> - * You can register a set of values and refer to them as:
> - *    $name
> - *
> - * If convert_to_integer is true, the set must contain
> - * integer/masked-integer values. The values that don't qualify
> - * are ignored.
> - */
> -
> -void expr_const_sets_add(struct shash *const_sets, const char *name,
> -                         const char * const *values, size_t n_values,
> -                         bool convert_to_integer);
> -void expr_const_sets_remove(struct shash *const_sets, const char *name);
> -void expr_const_sets_destroy(struct shash *const_sets);
> -
> -#endif /* ovn/expr.h */
> diff --git a/include/ovn/lex.h b/include/ovn/lex.h
> deleted file mode 100644
> index 8d5585766..000000000
> --- a/include/ovn/lex.h
> +++ /dev/null
> @@ -1,152 +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.
> - */
> -
> -#ifndef OVN_LEX_H
> -#define OVN_LEX_H 1
> -
> -/* OVN lexical analyzer
> - * ====================
> - *
> - * This is a simple lexical analyzer (or tokenizer) for OVN match
> expressions
> - * and ACLs. */
> -
> -#include "openvswitch/meta-flow.h"
> -
> -struct ds;
> -
> -/* Token type. */
> -enum lex_type {
> -    LEX_T_END,                  /* end of input */
> -
> -    /* Tokens with auxiliary data. */
> -    LEX_T_ID,                   /* foo */
> -    LEX_T_STRING,               /* "foo" */
> -    LEX_T_INTEGER,              /* 12345 or 1.2.3.4 or ::1 or
> 01:02:03:04:05 */
> -    LEX_T_MASKED_INTEGER,       /* 12345/10 or 1.2.0.0/16 or ::2/127
> or... */
> -    LEX_T_MACRO,                /* $NAME */
> -    LEX_T_PORT_GROUP,            /* @NAME */
> -    LEX_T_ERROR,                /* invalid input */
> -
> -    /* Bare tokens. */
> -    LEX_T_LPAREN,               /* ( */
> -    LEX_T_RPAREN,               /* ) */
> -    LEX_T_LCURLY,               /* { */
> -    LEX_T_RCURLY,               /* } */
> -    LEX_T_LSQUARE,              /* [ */
> -    LEX_T_RSQUARE,              /* ] */
> -    LEX_T_EQ,                   /* == */
> -    LEX_T_NE,                   /* != */
> -    LEX_T_LT,                   /* < */
> -    LEX_T_LE,                   /* <= */
> -    LEX_T_GT,                   /* > */
> -    LEX_T_GE,                   /* >= */
> -    LEX_T_LOG_NOT,              /* ! */
> -    LEX_T_LOG_AND,              /* && */
> -    LEX_T_LOG_OR,               /* || */
> -    LEX_T_ELLIPSIS,             /* .. */
> -    LEX_T_COMMA,                /* , */
> -    LEX_T_SEMICOLON,            /* ; */
> -    LEX_T_EQUALS,               /* = */
> -    LEX_T_EXCHANGE,             /* <-> */
> -    LEX_T_DECREMENT,            /* -- */
> -    LEX_T_COLON,                /* : */
> -};
> -
> -/* Subtype for LEX_T_INTEGER and LEX_T_MASKED_INTEGER tokens.
> - *
> - * These do not change the semantics of a token; instead, they determine
> the
> - * format used when a token is serialized back to a text form.  That's
> - * important because 3232268289 is meaningless to a human whereas
> 192.168.128.1
> - * has some actual significance. */
> -enum lex_format {
> -    LEX_F_DECIMAL,
> -    LEX_F_HEXADECIMAL,
> -    LEX_F_IPV4,
> -    LEX_F_IPV6,
> -    LEX_F_ETHERNET,
> -};
> -const char *lex_format_to_string(enum lex_format);
> -
> -/* A token. */
> -struct lex_token {
> -    /* One of LEX_*. */
> -    enum lex_type type;
> -
> -    /* Meaningful for LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO
> only.
> -     * For these token types, 's' may point to 'buffer'; otherwise, it
> points
> -     * to malloc()ed memory owned by the token.
> -     *
> -     * Must be NULL for other token types.
> -     *
> -     * For LEX_T_MACRO, 's' does not include the leading $. */
> -    char *s;
> -
> -    /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */
> -    enum lex_format format;
> -
> -    union {
> -        /* LEX_T_INTEGER, LEX_T_MASKED_INTEGER only. */
> -        struct {
> -            union mf_subvalue value; /* LEX_T_INTEGER,
> LEX_T_MASKED_INTEGER. */
> -            union mf_subvalue mask;  /* LEX_T_MASKED_INTEGER only. */
> -        };
> -
> -        /* LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO only. */
> -        char buffer[256];
> -    };
> -};
> -
> -void lex_token_init(struct lex_token *);
> -void lex_token_destroy(struct lex_token *);
> -void lex_token_swap(struct lex_token *, struct lex_token *);
> -void lex_token_strcpy(struct lex_token *, const char *s, size_t length);
> -void lex_token_strset(struct lex_token *, char *s);
> -void lex_token_vsprintf(struct lex_token *, const char *format, va_list
> args);
> -
> -void lex_token_format(const struct lex_token *, struct ds *);
> -const char *lex_token_parse(struct lex_token *, const char *input,
> -                            const char **startp);
> -
> -/* A lexical analyzer. */
> -struct lexer {
> -    const char *input;          /* Remaining input (not owned by lexer).
> */
> -    const char *start;          /* Start of current token in 'input'. */
> -    struct lex_token token;     /* Current token (owned by lexer). */
> -    char *error;                /* Error message, if any (owned by
> lexer). */
> -};
> -
> -void lexer_init(struct lexer *, const char *input);
> -void lexer_destroy(struct lexer *);
> -
> -enum lex_type lexer_get(struct lexer *);
> -enum lex_type lexer_lookahead(const struct lexer *);
> -bool lexer_match(struct lexer *, enum lex_type);
> -bool lexer_force_match(struct lexer *, enum lex_type);
> -bool lexer_match_id(struct lexer *, const char *id);
> -bool lexer_is_int(const struct lexer *);
> -bool lexer_get_int(struct lexer *, int *value);
> -bool lexer_force_int(struct lexer *, int *value);
> -
> -bool lexer_force_end(struct lexer *);
> -
> -void lexer_error(struct lexer *, const char *message, ...)
> -    OVS_PRINTF_FORMAT(2, 3);
> -void lexer_syntax_error(struct lexer *, const char *message, ...)
> -    OVS_PRINTF_FORMAT(2, 3);
> -
> -char *lexer_steal_error(struct lexer *);
> -
> -#endif /* ovn/lex.h */
> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
> deleted file mode 100644
> index 9bac8e027..000000000
> --- a/include/ovn/logical-fields.h
> +++ /dev/null
> @@ -1,130 +0,0 @@
> -/* Copyright (c) 2015, 2016 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.
> - */
> -
> -#ifndef OVN_LOGICAL_FIELDS_H
> -#define OVN_LOGICAL_FIELDS_H 1
> -
> -#include "openvswitch/meta-flow.h"
> -
> -struct shash;
> -
> -enum ovn_controller_event {
> -    OVN_EVENT_EMPTY_LB_BACKENDS = 0,
> -    OVN_EVENT_MAX,
> -};
> -
> -/* Logical fields.
> - *
> - * These values are documented in ovn-architecture(7), please update the
> - * documentation if you change any of them. */
> -#define MFF_LOG_DATAPATH MFF_METADATA /* Logical datapath (64 bits). */
> -#define MFF_LOG_FLAGS      MFF_REG10  /* One of MLF_* (32 bits). */
> -#define MFF_LOG_DNAT_ZONE  MFF_REG11  /* conntrack dnat zone for gateway
> router
> -                                       * (32 bits). */
> -#define MFF_LOG_SNAT_ZONE  MFF_REG12  /* conntrack snat zone for gateway
> router
> -                                       * (32 bits). */
> -#define MFF_LOG_CT_ZONE    MFF_REG13  /* Logical conntrack zone for lports
> -                                       * (32 bits). */
> -#define MFF_LOG_INPORT     MFF_REG14  /* Logical input port (32 bits). */
> -#define MFF_LOG_OUTPORT    MFF_REG15  /* Logical output port (32 bits). */
> -
> -/* Logical registers.
> - *
> - * Make sure these don't overlap with the logical fields! */
> -#define MFF_LOG_REG0 MFF_REG0
> -#define MFF_N_LOG_REGS 10
> -
> -void ovn_init_symtab(struct shash *symtab);
> -
> -/* MFF_LOG_FLAGS_REG bit assignments */
> -enum mff_log_flags_bits {
> -    MLF_ALLOW_LOOPBACK_BIT = 0,
> -    MLF_RCV_FROM_VXLAN_BIT = 1,
> -    MLF_FORCE_SNAT_FOR_DNAT_BIT = 2,
> -    MLF_FORCE_SNAT_FOR_LB_BIT = 3,
> -    MLF_LOCAL_ONLY_BIT = 4,
> -    MLF_NESTED_CONTAINER_BIT = 5,
> -};
> -
> -/* MFF_LOG_FLAGS_REG flag assignments */
> -enum mff_log_flags {
> -    /* Allow outputting back to inport. */
> -    MLF_ALLOW_LOOPBACK = (1 << MLF_ALLOW_LOOPBACK_BIT),
> -
> -    /* Indicate that a packet was received from a VXLAN tunnel to
> -     * compensate for the lack of egress port information available in
> -     * VXLAN encapsulation.  Egress port information is available for
> -     * Geneve and STT tunnel types. */
> -    MLF_RCV_FROM_VXLAN = (1 << MLF_RCV_FROM_VXLAN_BIT),
> -
> -    /* Indicate that a packet needs a force SNAT in the gateway router
> when
> -     * DNAT has taken place. */
> -    MLF_FORCE_SNAT_FOR_DNAT = (1 << MLF_FORCE_SNAT_FOR_DNAT_BIT),
> -
> -    /* Indicate that a packet needs a force SNAT in the gateway router
> when
> -     * load-balancing has taken place. */
> -    MLF_FORCE_SNAT_FOR_LB = (1 << MLF_FORCE_SNAT_FOR_LB_BIT),
> -
> -    /* Indicate that a packet that should be distributed across multiple
> -     * hypervisors should instead only be output to local targets
> -     */
> -    MLF_LOCAL_ONLY = (1 << MLF_LOCAL_ONLY_BIT),
> -
> -    /* Indicate that a packet was received from a nested container. */
> -    MLF_NESTED_CONTAINER = (1 << MLF_NESTED_CONTAINER_BIT),
> -};
> -
> -/* OVN logical fields
> - * ===================
> - * These are the fields which OVN supports modifying which gets translated
> - * to OFFlow controller action.
> - *
> - * OpenvSwitch doesn't support modifying these fields yet. If a field is
> - * supported later by OpenvSwitch, it can be deleted from here.
> - */
> -
> -enum ovn_field_id {
> -    /*
> -     * Name: "icmp4.frag_mtu" -
> -     * Type: be16
> -     * Description: Sets the low-order 16 bits of the ICMP4 header field
> -     * (that is labelled "unused" in the ICMP specification) of the ICMP4
> -     * packet as per the RFC 1191.
> -     */
> -    OVN_ICMP4_FRAG_MTU,
> -
> -    OVN_FIELD_N_IDS
> -};
> -
> -struct ovn_field {
> -    enum ovn_field_id id;
> -    const char *name;
> -    unsigned int n_bytes;       /* Width of the field in bytes. */
> -    unsigned int n_bits;        /* Number of significant bits in field. */
> -};
> -
> -static inline const struct ovn_field *
> -ovn_field_from_id(enum ovn_field_id id)
> -{
> -    extern const struct ovn_field ovn_fields[OVN_FIELD_N_IDS];
> -    ovs_assert((unsigned int) id < OVN_FIELD_N_IDS);
> -    return &ovn_fields[id];
> -}
> -
> -const char *event_to_string(enum ovn_controller_event event);
> -int string_to_event(const char *s);
> -const struct ovn_field *ovn_field_from_name(const char *name);
> -void ovn_destroy_ovnfields(void);
> -#endif /* ovn/lib/logical-fields.h */
> diff --git a/lib/db-ctl-base.xml b/lib/db-ctl-base.xml
> index a5fcc901c..10124c3ad 100644
> --- a/lib/db-ctl-base.xml
> +++ b/lib/db-ctl-base.xml
> @@ -40,8 +40,8 @@
>      <dd>
>        Either a universally unique identifier in the style of RFC 4122,
>        e.g. <code>f81d4fae-7dec-11d0-a765-00a0c91e6bf6</code>, or an
> <code>@</code><var>name</var>
> -      defined by a <code>get</code> or <code>create</code> command within
> the same <code>ovn-nbctl</code>
> -      invocation.
> +      defined by a <code>get</code> or <code>create</code> command within
> the
> +      same <code>ovs-vsctl</code> invocation.
>      </dd>
>
>    </dl>
> @@ -177,7 +177,7 @@
>        </p>
>
>        <p>
> -        The UUIDs shown for rows created in the same
> <code>ovn-nbctl</code>
> +        The UUIDs shown for rows created in the same
> <code>ovs-vsctl</code>
>          invocation will be wrong.
>        </p>
>
> @@ -199,7 +199,7 @@
>        </p>
>        <p>
>          If <code>@</code><var>name</var> is specified, then the UUID for
> <var>record</var> may be
> -        referred to by that name later in the same <code>ovn-nbctl</code>
> +        referred to by that name later in the same <code>ovs-vsctl</code>
>          invocation in contexts where a UUID is expected.
>        </p>
>        <p>
> @@ -379,8 +379,8 @@
>        </dl>
>        <p>
>          Consider specifying <code>--timeout=0</code> along with
> -        <code>--wait-until</code>, to prevent <code>ovn-nbctl</code> from
> terminating
> -        after waiting only at most 5 seconds.
> +        <code>--wait-until</code>, to prevent <code>ovs-vsctl</code> from
> +        terminating after waiting only at most 5 seconds.
>        </p>
>      </dd>
>
> diff --git a/manpages.mk b/manpages.mk
> index 5f43aa387..5012977aa 100644
> --- a/manpages.mk
> +++ b/manpages.mk
> @@ -1,33 +1,5 @@
>  # Generated automatically -- do not modify!    -*- buffer-read-only: t -*-
>
> -ovn/utilities/ovn-detrace.1: \
> -       ovn/utilities/ovn-detrace.1.in \
> -       lib/common-syn.man \
> -       lib/common.man \
> -       lib/ovs.tmac
> -ovn/utilities/ovn-detrace.1.in:
> -lib/common-syn.man:
> -lib/common.man:
> -lib/ovs.tmac:
> -
> -ovn/utilities/ovn-sbctl.8: \
> -       ovn/utilities/ovn-sbctl.8.in \
> -       lib/common.man \
> -       lib/db-ctl-base.man \
> -       lib/ovs.tmac \
> -       lib/ssl-bootstrap.man \
> -       lib/ssl.man \
> -       lib/table.man \
> -       lib/vlog.man
> -ovn/utilities/ovn-sbctl.8.in:
> -lib/common.man:
> -lib/db-ctl-base.man:
> -lib/ovs.tmac:
> -lib/ssl-bootstrap.man:
> -lib/ssl.man:
> -lib/table.man:
> -lib/vlog.man:
> -
>  ovsdb/ovsdb-client.1: \
>         ovsdb/ovsdb-client.1.in \
>         lib/common-syn.man \
> diff --git a/ovn/.gitignore b/ovn/.gitignore
> deleted file mode 100644
> index d971938aa..000000000
> --- a/ovn/.gitignore
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -/ovn-architecture.7
> -/ovn-nb.5
> -/ovn-nb.gv
> -/ovn-nb.pic
> -/ovn-sb.5
> -/ovn-sb.gv
> -/ovn-sb.pic
> -/*.ovsschema.stamp
> diff --git a/ovn/TODO.rst b/ovn/TODO.rst
> deleted file mode 100644
> index 33489174f..000000000
> --- a/ovn/TODO.rst
> +++ /dev/null
> @@ -1,147 +0,0 @@
> -..
> -      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.
> -
> -      Convention for heading levels in Open vSwitch documentation:
> -
> -      =======  Heading 0 (reserved for the title in a document)
> -      -------  Heading 1
> -      ~~~~~~~  Heading 2
> -      +++++++  Heading 3
> -      '''''''  Heading 4
> -
> -      Avoid deeper levels because they do not render well.
> -
> -==============
> -OVN To-do List
> -==============
> -
> -* Get incremental updates in ovn-controller and ovn-northd in some
> -  sensible way.
> -
> -* Live migration.
> -
> -  Russell Bryant: "When you're ready to have the destination take over,
> you
> -  have to remove the iface-id from the source and add it at the
> destination and
> -  I think it'd typically be configured on both ends, since it's a clone
> of the
> -  source VM (and it's config)."
> -
> -* VLAN trunk ports.
> -
> -  Russell Bryant: "Today that would require creating 4096 ports for the
> VM and
> -  attach to 4096 OVN networks, so doable, but not quite ideal."
> -
> -* Service function chaining.
> -
> -* MAC learning.
> -
> -  Han Zhou: "To support VMs that hosts workloads with their own macs, e.g.
> -  containers, if not using OVN native container support."
> -
> -* Finish up ARP/ND support: re-checking bindings, expiring bindings.
> -
> -* Hitless upgrade, especially for data plane.
> -
> -* Use OpenFlow "bundles" for transactional data plane updates.
> -
> -* Dynamic IP to MAC binding enhancements.
> -
> -  OVN has basic support for establishing IP to MAC bindings dynamically,
> using
> -  ARP.
> -
> -  * Ratelimiting.
> -
> -    From casual observation, Linux appears to generate at most one ARP per
> -    second per destination.
> -
> -    This might be supported by adding a new OVN logical action for
> -    rate-limiting.
> -
> -  * Tracking queries
> -
> -     It's probably best to only record in the database responses to
> queries
> -     actually issued by an L3 logical router, so somehow they have to be
> -     tracked, probably by putting a tentative binding without a MAC
> address
> -     into the database.
> -
> -  * Renewal and expiration.
> -
> -    Something needs to make sure that bindings remain valid and expire
> those
> -    that become stale.
> -
> -    One way to do this might be to add some support for time to the
> database
> -    server itself.
> -
> -  * Table size limiting.
> -
> -    The table of MAC bindings must not be allowed to grow unreasonably
> large.
> -
> -  * MTU handling (fragmentation on output)
> -
> -* ovsdb-server
> -
> -  ovsdb-server should have adequate features for OVN but it probably
> needs work
> -  for scale and possibly for availability as deployments grow.  Here are
> some
> -  thoughts.
> -
> -  * Multithreading.
> -
> -    If it turns out that other changes don't let ovsdb-server scale
> -    adequately, we can multithread ovsdb-server.  Initially one might
> -    only break protocol handling into separate threads, leaving the
> -    actual database work serialized through a lock.
> -
> -  * Reducing startup time.
> -
> -    As-is, if ovsdb-server restarts, every client will fetch a fresh copy
> of
> -    the part of the database that it cares about.  With hundreds of
> clients,
> -    this could cause heavy CPU load on ovsdb-server and use excessive
> network
> -    bandwidth.  It would be better to allow incremental updates even
> across
> -    connection loss.  One way might be to use "Difference Digests" as
> described
> -    in Epstein et al., "What's the Difference? Efficient Set
> Reconciliation
> -    Without Prior Context".  (I'm not yet aware of previous non-academic
> use of
> -    this technique.)
> -
> -* Support multiple tunnel encapsulations in Chassis.
> -
> -  So far, both ovn-controller and ovn-controller-vtep only allow chassis
> to
> -  have one tunnel encapsulation entry.  We should extend the
> implementation
> -  to support multiple tunnel encapsulations.
> -
> -* Update learned MAC addresses from VTEP to OVN
> -
> -  The VTEP gateway stores all MAC addresses learned from its physical
> -  interfaces in the 'Ucast_Macs_Local' and the 'Mcast_Macs_Local' tables.
> -  ovn-controller-vtep should be able to update that information back to
> -  ovn-sb database, so that other chassis know where to send packets
> destined
> -  to the extended external network instead of broadcasting.
> -
> -* Translate ovn-sb Multicast_Group table into VTEP config
> -
> -  The ovn-controller-vtep daemon should be able to translate the
> -  Multicast_Group table entry in ovn-sb database into Mcast_Macs_Remote
> table
> -  configuration in VTEP database.
> -
> -* OVN OCF pacemaker script to support Active / Passive HA for OVN dbs
> provides
> -  the option to configure the inactivity_probe value. The default 5
> seconds
> -  inactivity_probe value is not sufficient and ovsdb-server drops the
> client
> -  IDL connections for openstack deployments when the neutron server is
> heavily
> -  loaded.
> -
> -  We need to find a proper solution to solve this issue instead of
> increasing
> -  the inactivity_probe value.
> -
> -* ACL
> -
> -  * Support FTP ALGs.
> -
> -  * Support reject action.
> diff --git a/ovn/automake.mk b/ovn/automake.mk
> deleted file mode 100644
> index b33112ef1..000000000
> --- a/ovn/automake.mk
> +++ /dev/null
> @@ -1,92 +0,0 @@
> -# OVN southbound schema and IDL
> -EXTRA_DIST += ovn/ovn-sb.ovsschema
> -pkgdata_DATA += ovn/ovn-sb.ovsschema
> -
> -# OVN southbound E-R diagram
> -#
> -# If "python" or "dot" is not available, then we do not add graphical
> diagram
> -# to the documentation.
> -if HAVE_PYTHON
> -if HAVE_DOT
> -ovn/ovn-sb.gv: ovsdb/ovsdb-dot.in ovn/ovn-sb.ovsschema
> -       $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-sb.ovsschema
> > $@
> -ovn/ovn-sb.pic: ovn/ovn-sb.gv ovsdb/dot2pic
> -       $(AM_V_GEN)(dot -T plain < ovn/ovn-sb.gv | $(PYTHON)
> $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> -       mv $@.tmp $@
> -OVN_SB_PIC = ovn/ovn-sb.pic
> -OVN_SB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_SB_PIC)
> -CLEANFILES += ovn/ovn-sb.gv ovn/ovn-sb.pic
> -endif
> -endif
> -
> -# OVN southbound schema documentation
> -EXTRA_DIST += ovn/ovn-sb.xml
> -CLEANFILES += ovn/ovn-sb.5
> -man_MANS += ovn/ovn-sb.5
> -ovn/ovn-sb.5: \
> -       ovsdb/ovsdb-doc ovn/ovn-sb.xml ovn/ovn-sb.ovsschema $(OVN_SB_PIC)
> -       $(AM_V_GEN)$(OVSDB_DOC) \
> -               $(OVN_SB_DOT_DIAGRAM_ARG) \
> -               --version=$(VERSION) \
> -               $(srcdir)/ovn/ovn-sb.ovsschema \
> -               $(srcdir)/ovn/ovn-sb.xml > $@.tmp && \
> -       mv $@.tmp $@
> -
> -# OVN northbound schema and IDL
> -EXTRA_DIST += ovn/ovn-nb.ovsschema
> -pkgdata_DATA += ovn/ovn-nb.ovsschema
> -
> -# OVN northbound E-R diagram
> -#
> -# If "python" or "dot" is not available, then we do not add graphical
> diagram
> -# to the documentation.
> -if HAVE_PYTHON
> -if HAVE_DOT
> -ovn/ovn-nb.gv: ovsdb/ovsdb-dot.in ovn/ovn-nb.ovsschema
> -       $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-nb.ovsschema
> > $@
> -ovn/ovn-nb.pic: ovn/ovn-nb.gv ovsdb/dot2pic
> -       $(AM_V_GEN)(dot -T plain < ovn/ovn-nb.gv | $(PYTHON)
> $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> -       mv $@.tmp $@
> -OVN_NB_PIC = ovn/ovn-nb.pic
> -OVN_NB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_NB_PIC)
> -CLEANFILES += ovn/ovn-nb.gv ovn/ovn-nb.pic
> -endif
> -endif
> -
> -# OVN northbound schema documentation
> -EXTRA_DIST += ovn/ovn-nb.xml
> -CLEANFILES += ovn/ovn-nb.5
> -man_MANS += ovn/ovn-nb.5
> -ovn/ovn-nb.5: \
> -       ovsdb/ovsdb-doc ovn/ovn-nb.xml ovn/ovn-nb.ovsschema $(OVN_NB_PIC)
> -       $(AM_V_GEN)$(OVSDB_DOC) \
> -               $(OVN_NB_DOT_DIAGRAM_ARG) \
> -               --version=$(VERSION) \
> -               $(srcdir)/ovn/ovn-nb.ovsschema \
> -               $(srcdir)/ovn/ovn-nb.xml > $@.tmp && \
> -       mv $@.tmp $@
> -
> -man_MANS += ovn/ovn-architecture.7
> -EXTRA_DIST += ovn/ovn-architecture.7.xml
> -CLEANFILES += ovn/ovn-architecture.7
> -
> -EXTRA_DIST += \
> -       ovn/TODO.rst
> -
> -# Version checking for ovn-nb.ovsschema.
> -ALL_LOCAL += ovn/ovn-nb.ovsschema.stamp
> -ovn/ovn-nb.ovsschema.stamp: ovn/ovn-nb.ovsschema
> -       $(srcdir)/build-aux/cksum-schema-check $? $@
> -CLEANFILES += ovn/ovn-nb.ovsschema.stamp
> -
> -# Version checking for ovn-sb.ovsschema.
> -ALL_LOCAL += ovn/ovn-sb.ovsschema.stamp
> -ovn/ovn-sb.ovsschema.stamp: ovn/ovn-sb.ovsschema
> -       $(srcdir)/build-aux/cksum-schema-check $? $@
> -CLEANFILES += ovn/ovn-sb.ovsschema.stamp
> -
> -include ovn/controller/automake.mk
> -include ovn/controller-vtep/automake.mk
> -include ovn/lib/automake.mk
> -include ovn/northd/automake.mk
> -include ovn/utilities/automake.mk
> diff --git a/ovn/controller-vtep/.gitignore
> b/ovn/controller-vtep/.gitignore
> deleted file mode 100644
> index 3ec8072c7..000000000
> --- a/ovn/controller-vtep/.gitignore
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -/ovn-controller-vtep
> -/ovn-controller-vtep.8
> diff --git a/ovn/controller-vtep/automake.mk b/ovn/controller-vtep/
> automake.mk
> deleted file mode 100644
> index 0c83dc70a..000000000
> --- a/ovn/controller-vtep/automake.mk
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -bin_PROGRAMS += ovn/controller-vtep/ovn-controller-vtep
> -ovn_controller_vtep_ovn_controller_vtep_SOURCES = \
> -       ovn/controller-vtep/binding.c \
> -       ovn/controller-vtep/binding.h \
> -       ovn/controller-vtep/gateway.c \
> -       ovn/controller-vtep/gateway.h \
> -       ovn/controller-vtep/ovn-controller-vtep.c \
> -       ovn/controller-vtep/ovn-controller-vtep.h \
> -       ovn/controller-vtep/vtep.c \
> -       ovn/controller-vtep/vtep.h
> -ovn_controller_vtep_ovn_controller_vtep_LDADD = ovn/lib/libovn.la lib/
> libopenvswitch.la vtep/libvtep.la
> -man_MANS += ovn/controller-vtep/ovn-controller-vtep.8
> -EXTRA_DIST += ovn/controller-vtep/ovn-controller-vtep.8.xml
> -CLEANFILES += ovn/controller-vtep/ovn-controller-vtep.8
> diff --git a/ovn/controller-vtep/binding.c b/ovn/controller-vtep/binding.c
> deleted file mode 100644
> index 9cbfadc71..000000000
> --- a/ovn/controller-vtep/binding.c
> +++ /dev/null
> @@ -1,274 +0,0 @@
> -/* Copyright (c) 2015 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 "binding.h"
> -
> -#include "openvswitch/shash.h"
> -#include "lib/smap.h"
> -#include "lib/util.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn-controller-vtep.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "vtep/vtep-idl.h"
> -
> -VLOG_DEFINE_THIS_MODULE(binding);
> -
> -/*
> - * This module scans through the Port_Binding table in ovnsb.  If there
> is a
> - * logical port binding entry for logical switch in vtep gateway chassis's
> - * 'vtep_logical_switches' column, sets the binding's chassis column to
> the
> - * corresponding vtep gateway chassis.
> - *
> - */
> -
> -
> -/* Returns true if the 'vtep_lswitch' specified in 'port_binding_rec'
> - * has already been bound to another port binding entry, and resets
> - * 'port_binding_rec''s chassis column.  Otherwise, updates 'ls_to_pb'
> - * and returns false. */
> -static bool
> -check_pb_conflict(struct shash *ls_to_pb,
> -                  const struct sbrec_port_binding *port_binding_rec,
> -                  const char *chassis_name,
> -                  const char *vtep_lswitch)
> -{
> -    const struct sbrec_port_binding *pb_conflict =
> -        shash_find_data(ls_to_pb, vtep_lswitch);
> -
> -    if (pb_conflict) {
> -        VLOG_WARN("logical switch (%s), on vtep gateway chassis "
> -                  "(%s) has already been associated with logical "
> -                  "port (%s), ignore logical port (%s)",
> -                  vtep_lswitch, chassis_name,
> -                  pb_conflict->logical_port,
> -                  port_binding_rec->logical_port);
> -        sbrec_port_binding_set_chassis(port_binding_rec, NULL);
> -
> -        return true;
> -    }
> -
> -    shash_add(ls_to_pb, vtep_lswitch, port_binding_rec);
> -    return false;
> -}
> -
> -/* Returns true if the 'vtep_lswitch' specified in 'port_binding_rec'
> - * has already been bound to a different datapath, and resets
> - * 'port_binding_rec''s chassis column.  Otherwise, updates 'ls_to_db' and
> - * returns false. */
> -static bool
> -check_db_conflict(struct shash *ls_to_db,
> -                  const struct sbrec_port_binding *port_binding_rec,
> -                  const char *chassis_name,
> -                  const char *vtep_lswitch)
> -{
> -    const struct sbrec_datapath_binding *db_conflict =
> -        shash_find_data(ls_to_db, vtep_lswitch);
> -
> -    if (db_conflict && db_conflict != port_binding_rec->datapath) {
> -        VLOG_WARN("logical switch (%s), on vtep gateway chassis "
> -                  "(%s) has already been associated with logical "
> -                  "datapath (with tunnel key %"PRId64"), ignore "
> -                  "logical port (%s) which belongs to logical "
> -                  "datapath (with tunnel key %"PRId64")",
> -                  vtep_lswitch, chassis_name,
> -                  db_conflict->tunnel_key,
> -                  port_binding_rec->logical_port,
> -                  port_binding_rec->datapath->tunnel_key);
> -        sbrec_port_binding_set_chassis(port_binding_rec, NULL);
> -
> -        return true;
> -    }
> -
> -    shash_replace(ls_to_db, vtep_lswitch, port_binding_rec->datapath);
> -    return false;
> -}
> -
> -/* Updates the 'port_binding_rec''s chassis column to 'chassis_rec'. */
> -static void
> -update_pb_chassis(const struct sbrec_port_binding *port_binding_rec,
> -                  const struct sbrec_chassis *chassis_rec)
> -{
> -    if (port_binding_rec->chassis != chassis_rec) {
> -        if (chassis_rec && port_binding_rec->chassis) {
> -            VLOG_DBG("Changing chassis association of logical "
> -                     "port (%s) from (%s) to (%s)",
> -                     port_binding_rec->logical_port,
> -                     port_binding_rec->chassis->name,
> -                     chassis_rec->name);
> -        }
> -        sbrec_port_binding_set_chassis(port_binding_rec, chassis_rec);
> -    }
> -}
> -
> -
> -/* Checks and updates logical port to vtep logical switch bindings for
> each
> - * physical switch in VTEP. */
> -void
> -binding_run(struct controller_vtep_ctx *ctx)
> -{
> -    if (!ctx->ovnsb_idl_txn) {
> -        return;
> -    }
> -
> -    /* 'ls_to_db'
> -     *
> -     * Maps vtep logical switch name to the datapath binding entry.  This
> is
> -     * used to guarantee that each vtep logical switch is only included
> -     * in only one ovn datapath (ovn logical switch).  See
> check_db_conflict()
> -     * for details.
> -     *
> -     * 'ls_to_pb'
> -     *
> -     * Maps vtep logical switch name to the port binding entry.  This is
> used
> -     * to guarantee that each vtep logical switch on a vtep physical
> switch
> -     * is only bound to one logical port.  See check_pb_conflict() for
> -     * details.
> -     *
> -     */
> -    struct shash ls_to_db = SHASH_INITIALIZER(&ls_to_db);
> -
> -    /* Stores the 'chassis' and the 'ls_to_pb' map related to
> -     * a vtep physcial switch. */
> -    struct ps {
> -        const struct sbrec_chassis *chassis_rec;
> -        struct shash ls_to_pb;
> -    };
> -    struct shash ps_map = SHASH_INITIALIZER(&ps_map);
> -    const struct vteprec_physical_switch *pswitch;
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
> -        const struct sbrec_chassis *chassis_rec
> -            = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
> -        struct ps *ps = xmalloc(sizeof *ps);
> -        size_t i;
> -
> -        /* 'chassis_rec' must exist. */
> -        ovs_assert(chassis_rec);
> -        ps->chassis_rec = chassis_rec;
> -        shash_init(&ps->ls_to_pb);
> -        for (i = 0; i < chassis_rec->n_vtep_logical_switches; i++) {
> -            shash_add(&ps->ls_to_pb,
> chassis_rec->vtep_logical_switches[i],
> -                      NULL);
> -        }
> -        shash_add(&ps_map, chassis_rec->name, ps);
> -    }
> -
> -    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
> -                              "ovn-controller-vtep: updating bindings");
> -
> -    const struct sbrec_port_binding *port_binding_rec;
> -    /* Port binding for vtep gateway chassis must have type "vtep",
> -     * and matched physical switch name and logical switch name. */
> -    SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
> -        const char *type = port_binding_rec->type;
> -        const char *vtep_pswitch = smap_get(&port_binding_rec->options,
> -                                            "vtep-physical-switch");
> -        const char *vtep_lswitch = smap_get(&port_binding_rec->options,
> -                                            "vtep-logical-switch");
> -        struct ps *ps
> -            = vtep_pswitch ? shash_find_data(&ps_map, vtep_pswitch) :
> NULL;
> -        bool found_ls
> -            = ps && vtep_lswitch && shash_find(&ps->ls_to_pb,
> vtep_lswitch);
> -
> -        if (!strcmp(type, "vtep") && found_ls) {
> -            bool pb_conflict, db_conflict;
> -
> -            pb_conflict = check_pb_conflict(&ps->ls_to_pb,
> port_binding_rec,
> -                                            ps->chassis_rec->name,
> -                                            vtep_lswitch);
> -            db_conflict = check_db_conflict(&ls_to_db, port_binding_rec,
> -                                            ps->chassis_rec->name,
> -                                            vtep_lswitch);
> -            /* Updates port binding's chassis column when there
> -             * is no conflict. */
> -            if (!pb_conflict && !db_conflict) {
> -                update_pb_chassis(port_binding_rec, ps->chassis_rec);
> -            }
> -        } else if (port_binding_rec->chassis
> -                   && shash_find(&ps_map,
> port_binding_rec->chassis->name)) {
> -            /* Resets 'port_binding_rec' since it is no longer bound to
> -             * any vtep logical switch. */
> -            update_pb_chassis(port_binding_rec, NULL);
> -        }
> -    }
> -
> -    struct shash_node *iter, *next;
> -    SHASH_FOR_EACH_SAFE (iter, next, &ps_map) {
> -        struct ps *ps = iter->data;
> -        struct shash_node *node;
> -
> -        SHASH_FOR_EACH (node, &ps->ls_to_pb) {
> -            if (!node->data) {
> -                static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(1, 5);
> -                VLOG_DBG_RL(&rl, "No port binding entry for logical
> switch (%s)"
> -                            "on vtep gateway chassis (%s)", node->name,
> -                            ps->chassis_rec->name);
> -            }
> -        }
> -        shash_delete(&ps_map, iter);
> -        shash_destroy(&ps->ls_to_pb);
> -        free(ps);
> -    }
> -    shash_destroy(&ls_to_db);
> -    shash_destroy(&ps_map);
> -}
> -
> -/* Removes all port binding association with vtep gateway chassis.
> - * Returns true when done (i.e. there is no change made to
> 'ctx->ovnsb_idl'),
> - * otherwise returns false. */
> -bool
> -binding_cleanup(struct controller_vtep_ctx *ctx)
> -{
> -    if (!ctx->ovnsb_idl_txn) {
> -        return false;
> -    }
> -
> -    struct shash ch_to_pb = SHASH_INITIALIZER(&ch_to_pb);
> -    const struct sbrec_port_binding *port_binding_rec;
> -    bool all_done = true;
> -    /* Hashs all port binding entries using the associated chassis name.
> */
> -    SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
> -        if (port_binding_rec->chassis) {
> -            shash_add(&ch_to_pb, port_binding_rec->chassis->name,
> -                      port_binding_rec);
> -        }
> -    }
> -
> -    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
> -                              "ovn-controller-vtep: removing bindings");
> -
> -    const struct vteprec_physical_switch *pswitch;
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
> -        const struct sbrec_chassis *chassis_rec
> -            = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
> -
> -        if (!chassis_rec) {
> -            continue;
> -        }
> -
> -        for (;;) {
> -            port_binding_rec = shash_find_and_delete(&ch_to_pb,
> -                                                     chassis_rec->name);
> -            if (!port_binding_rec) {
> -                break;
> -            }
> -            all_done = false;
> -            update_pb_chassis(port_binding_rec, NULL);
> -        }
> -    }
> -    shash_destroy(&ch_to_pb);
> -
> -    return all_done;
> -}
> diff --git a/ovn/controller-vtep/binding.h b/ovn/controller-vtep/binding.h
> deleted file mode 100644
> index 374c1ccf8..000000000
> --- a/ovn/controller-vtep/binding.h
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -/* Copyright (c) 2015 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.
> - */
> -
> -
> -#ifndef OVN_BINDING_H
> -#define OVN_BINDING_H 1
> -
> -#include <stdbool.h>
> -
> -struct controller_vtep_ctx;
> -
> -void binding_run(struct controller_vtep_ctx *);
> -bool binding_cleanup(struct controller_vtep_ctx *);
> -
> -#endif /* ovn/controller-gw/binding.h */
> diff --git a/ovn/controller-vtep/gateway.c b/ovn/controller-vtep/gateway.c
> deleted file mode 100644
> index 619c3c49a..000000000
> --- a/ovn/controller-vtep/gateway.c
> +++ /dev/null
> @@ -1,230 +0,0 @@
> -/* Copyright (c) 2015 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 "gateway.h"
> -
> -#include "openvswitch/poll-loop.h"
> -#include "lib/simap.h"
> -#include "lib/sset.h"
> -#include "lib/util.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "vtep/vtep-idl.h"
> -#include "ovn-controller-vtep.h"
> -
> -VLOG_DEFINE_THIS_MODULE(gateway);
> -
> -/*
> - * Registers the physical switches in vtep to ovnsb as chassis.  For each
> - * physical switch in the vtep database, finds all vtep logical switches
> that
> - * are associated with the physical switch, and updates the corresponding
> - * chassis's 'vtep_logical_switches' column.
> - *
> - */
> -
> -/* Global revalidation sequence number, incremented at each call to
> - * 'revalidate_gateway()'. */
> -static unsigned int gw_reval_seq;
> -
> -/* Maps all chassis created by the gateway module to their own reval_seq.
> */
> -static struct simap gw_chassis_map = SIMAP_INITIALIZER(&gw_chassis_map);
> -
> -/* Creates and returns a new instance of 'struct sbrec_chassis'. */
> -static const struct sbrec_chassis *
> -create_chassis_rec(struct ovsdb_idl_txn *txn, const char *name,
> -                   const char *encap_ip)
> -{
> -    const struct sbrec_chassis *chassis_rec;
> -    struct sbrec_encap *encap_rec;
> -
> -    VLOG_INFO("add Chassis row for VTEP physical switch (%s)", name);
> -
> -    chassis_rec = sbrec_chassis_insert(txn);
> -    sbrec_chassis_set_name(chassis_rec, name);
> -    encap_rec = sbrec_encap_insert(txn);
> -    sbrec_encap_set_type(encap_rec, OVN_SB_ENCAP_TYPE);
> -    sbrec_encap_set_ip(encap_rec, encap_ip);
> -    const struct smap options = SMAP_CONST1(&options, "csum", "false");
> -    sbrec_encap_set_options(encap_rec, &options);
> -    sbrec_chassis_set_encaps(chassis_rec, &encap_rec, 1);
> -
> -    return chassis_rec;
> -}
> -
> -/* Revalidates chassis in ovnsb against vtep database.  Creates chassis
> for
> - * new vtep physical switch.  And removes chassis which no longer have
> - * physical switch in vtep.
> - *
> - * xxx: Support multiple tunnel encaps.
> - *
> - * */
> -static void
> -revalidate_gateway(struct controller_vtep_ctx *ctx)
> -{
> -    const struct vteprec_physical_switch *pswitch;
> -
> -    /* Increments the global revalidation sequence number. */
> -    gw_reval_seq++;
> -
> -    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
> -                              "ovn-controller-vtep: updating vtep
> chassis");
> -
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
> -        const struct sbrec_chassis *chassis_rec;
> -        struct simap_node *gw_node;
> -        const char *encap_ip;
> -
> -        encap_ip = pswitch->n_tunnel_ips ? pswitch->tunnel_ips[0] : "";
> -        gw_node = simap_find(&gw_chassis_map, pswitch->name);
> -        chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
> -        if (chassis_rec) {
> -            if (!gw_node &&
> -                (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)
> -                 || strcmp(chassis_rec->encaps[0]->ip, encap_ip))) {
> -                VLOG_WARN("Chassis config changing on startup, make sure "
> -                          "multiple chassis are not configured :
> %s/%s->%s/%s",
> -                          chassis_rec->encaps[0]->type,
> -                          chassis_rec->encaps[0]->ip,
> -                          OVN_SB_ENCAP_TYPE, encap_ip);
> -            }
> -            /* Updates chassis's encap if anything changed. */
> -            if (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)) {
> -                VLOG_WARN("Chassis for VTEP physical switch (%s) can only
> have "
> -                          "encap type \"%s\"", pswitch->name,
> OVN_SB_ENCAP_TYPE);
> -                sbrec_encap_set_type(chassis_rec->encaps[0],
> OVN_SB_ENCAP_TYPE);
> -            }
> -            if (strcmp(chassis_rec->encaps[0]->ip, encap_ip)) {
> -                sbrec_encap_set_ip(chassis_rec->encaps[0], encap_ip);
> -            }
> -            if (smap_get_bool(&chassis_rec->encaps[0]->options, "csum",
> true)) {
> -                const struct smap options = SMAP_CONST1(&options, "csum",
> -
> "false");
> -                sbrec_encap_set_options(chassis_rec->encaps[0], &options);
> -            }
> -        } else {
> -            if (gw_node) {
> -                VLOG_WARN("Chassis for VTEP physical switch (%s)
> disappears, "
> -                          "maybe deleted by ovn-sbctl, adding it back",
> -                          pswitch->name);
> -            }
> -            /* Creates a new chassis for the VTEP physical switch. */
> -            create_chassis_rec(ctx->ovnsb_idl_txn, pswitch->name,
> encap_ip);
> -        }
> -        /* Updates or creates the simap node for 'pswitch->name'. */
> -        simap_put(&gw_chassis_map, pswitch->name, gw_reval_seq);
> -    }
> -
> -    struct simap_node *iter, *next;
> -    /* For 'gw_node' in 'gw_chassis_map' whose data is not
> -     * 'gw_reval_seq', it means the corresponding physical switch no
> -     * longer exist.  So, garbage collects them. */
> -    SIMAP_FOR_EACH_SAFE (iter, next, &gw_chassis_map) {
> -        if (iter->data != gw_reval_seq) {
> -            const struct sbrec_chassis *chassis_rec;
> -
> -            chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, iter->name);
> -            if (chassis_rec) {
> -                sbrec_chassis_delete(chassis_rec);
> -            }
> -            simap_delete(&gw_chassis_map, iter);
> -        }
> -    }
> -}
> -
> -/* Updates the 'vtep_logical_switches' column in the Chassis table based
> - * on vtep database configuration. */
> -static void
> -update_vtep_logical_switches(struct controller_vtep_ctx *ctx)
> -{
> -    const struct vteprec_physical_switch *pswitch;
> -
> -    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
> -                              "updating chassis's vtep_logical_switches");
> -
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
> -        const struct sbrec_chassis *chassis_rec =
> -            get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
> -        struct sset lswitches = SSET_INITIALIZER(&lswitches);
> -        size_t i;
> -
> -        for (i = 0; i < pswitch->n_ports; i++) {
> -            const struct vteprec_physical_port *port = pswitch->ports[i];
> -            size_t j;
> -
> -            for (j = 0; j < port->n_vlan_bindings; j++) {
> -                const struct vteprec_logical_switch *vtep_lswitch;
> -
> -                vtep_lswitch = port->value_vlan_bindings[j];
> -                /* If not already in 'lswitches', records it. */
> -                if (!sset_find(&lswitches, vtep_lswitch->name)) {
> -                    sset_add(&lswitches, vtep_lswitch->name);
> -                }
> -            }
> -        }
> -
> -        const char **ls_arr = sset_array(&lswitches);
> -        sbrec_chassis_set_vtep_logical_switches(chassis_rec, ls_arr,
> -                                                sset_count(&lswitches));
> -        free(ls_arr);
> -        sset_destroy(&lswitches);
> -    }
> -}
> -
> -
> -void
> -gateway_run(struct controller_vtep_ctx *ctx)
> -{
> -    if (!ctx->ovnsb_idl_txn) {
> -        return;
> -    }
> -
> -    revalidate_gateway(ctx);
> -    update_vtep_logical_switches(ctx);
> -}
> -
> -/* Destroys the chassis table entries for vtep physical switches.
> - * Returns true when done (i.e. there is no change made to
> 'ctx->ovnsb_idl'),
> - * otherwise returns false. */
> -bool
> -gateway_cleanup(struct controller_vtep_ctx *ctx)
> -{
> -    static bool simap_destroyed = false;
> -    const struct vteprec_physical_switch *pswitch;
> -
> -    if (!ctx->ovnsb_idl_txn) {
> -        return false;
> -    }
> -
> -    bool all_done = true;
> -    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
> -                              "unregistering vtep chassis");
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
> -        const struct sbrec_chassis *chassis_rec;
> -
> -        chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
> -        if (!chassis_rec) {
> -            continue;
> -        }
> -        all_done = false;
> -        sbrec_chassis_delete(chassis_rec);
> -    }
> -    if (!simap_destroyed) {
> -        simap_destroy(&gw_chassis_map);
> -        simap_destroyed = true;
> -    }
> -
> -    return all_done;
> -}
> diff --git a/ovn/controller-vtep/gateway.h b/ovn/controller-vtep/gateway.h
> deleted file mode 100644
> index 0086191d9..000000000
> --- a/ovn/controller-vtep/gateway.h
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -/* Copyright (c) 2015 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.
> - */
> -
> -#ifndef OVN_GATEWAY_H
> -#define OVN_GATEWAY_H 1
> -
> -#include <stdbool.h>
> -
> -struct controller_vtep_ctx;
> -
> -void gateway_run(struct controller_vtep_ctx *);
> -bool gateway_cleanup(struct controller_vtep_ctx *);
> -
> -#endif /* ovn/controller-gw/gateway.h */
> diff --git a/ovn/controller-vtep/ovn-controller-vtep.8.xml
> b/ovn/controller-vtep/ovn-controller-vtep.8.xml
> deleted file mode 100644
> index 2c706e46e..000000000
> --- a/ovn/controller-vtep/ovn-controller-vtep.8.xml
> +++ /dev/null
> @@ -1,80 +0,0 @@
> -<?xml version="1.0" encoding="utf-8"?>
> -<manpage program="ovn-controller-vtep" section="8"
> title="ovn-controller-vtep">
> -    <h1>Name</h1>
> -    <p>ovn-controller-vtep -- Open Virtual Network local controller for
> -       vtep enabled physical switches.
> -    </p>
> -
> -    <h1>Synopsis</h1>
> -    <p><code>ovn-controller-vtep</code> [<var>options</var>]
> -    [<var>--vtep-db=vtep-database</var>]
> [<var>--ovnsb-db=ovnsb-database</var>]
> -    </p>
> -
> -    <h1>Description</h1>
> -    <p>
> -      <code>ovn-controller-vtep</code> is the local controller daemon in
> -      OVN, the Open Virtual Network, for VTEP enabled physical switches.
> -      It connects up to the OVN Southbound database (see
> -      <code>ovn-sb</code>(5)) over the OVSDB protocol, and down to the
> VTEP
> -      database (see <code>vtep</code>(5)) over the OVSDB protocol.
> -    </p>
> -
> -    <h2>PKI Options</h2>
> -    <p>
> -      PKI configuration is required in order to use SSL for the
> connections to
> -      the VTEP and Southbound databases.
> -    </p>
> -    <xi:include href="lib/ssl.xml" xmlns:xi="
> http://www.w3.org/2003/XInclude"/>
> -    <xi:include href="lib/ssl-bootstrap.xml" xmlns:xi="
> http://www.w3.org/2003/XInclude"/>
> -    <xi:include href="lib/ssl-peer-ca-cert.xml" xmlns:xi="
> http://www.w3.org/2003/XInclude"/>
> -
> -    <h1>Configuration</h1>
> -    <p>
> -      <code>ovn-controller-vtep</code> retrieves its configuration
> -      information from both the ovnsb and the vtep database.  If the
> -      database locations are not given from command line, the default
> -      is the <code>db.sock</code> in local OVSDB's 'run' directory.
> -      The datapath location must take one of the following forms:
> -    </p>
> -    <ul>
> -      <li>
> -        <p>
> -          <code>ssl:<var>host</var>:<var>port</var></code>
> -        </p>
> -        <p>
> -          The specified SSL <var>port</var> on the give <var>host</var>,
> which
> -          can either be a DNS name (if built with unbound library) or an
> IP
> -          address (IPv4 or IPv6).  If <var>host</var> is an IPv6 address,
> then
> -          wrap <var>host</var> with square brackets, e.g.:
> <code>ssl:[::1]:6640</code>.
> -          The <code>--private-key</code>, <code>--certificate</code> and
> either
> -          of <code>--ca-cert</code> or <code>--bootstrap-ca-cert</code>
> options
> -          are mandatory when this form is used.
> -        </p>
> -      </li>
> -      <li>
> -        <p>
> -          <code>tcp:<var>host</var>:<var>port</var></code>
> -        </p>
> -        <p>
> -          Connect to the given TCP <var>port</var> on <var>host</var>,
> where
> -          <var>host</var> can be a DNS name (if built with unbound
> library) or
> -          IP address (IPv4 or IPv6). If <var>host</var> is an IPv6
> address,
> -          then wrap <var>host</var> with square brackets,
> -          e.g.: <code>tcp:[::1]:6640</code>.
> -        </p>
> -      </li>
> -      <li>
> -        <p>
> -          <code>unix:<var>file</var></code>
> -        </p>
> -        <p>
> -          On POSIX, connect to the Unix domain server socket named
> -          <var>file</var>.
> -        </p>
> -        <p>
> -          On Windows, connect to a localhost TCP port whose value is
> written
> -          in <var>file</var>.
> -        </p>
> -      </li>
> -    </ul>
> -</manpage>
> diff --git a/ovn/controller-vtep/ovn-controller-vtep.c
> b/ovn/controller-vtep/ovn-controller-vtep.c
> deleted file mode 100644
> index 292a3f464..000000000
> --- a/ovn/controller-vtep/ovn-controller-vtep.c
> +++ /dev/null
> @@ -1,272 +0,0 @@
> -/* Copyright (c) 2015, 2016 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 <signal.h>
> -#include <stdlib.h>
> -#include <string.h>
> -
> -#include "command-line.h"
> -#include "compiler.h"
> -#include "daemon.h"
> -#include "dirs.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "fatal-signal.h"
> -#include "openvswitch/poll-loop.h"
> -#include "stream.h"
> -#include "stream-ssl.h"
> -#include "unixctl.h"
> -#include "util.h"
> -#include "openvswitch/vconn.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn/lib/ovn-util.h"
> -#include "vtep/vtep-idl.h"
> -
> -#include "binding.h"
> -#include "gateway.h"
> -#include "vtep.h"
> -#include "ovn-controller-vtep.h"
> -
> -static unixctl_cb_func ovn_controller_vtep_exit;
> -
> -static void parse_options(int argc, char *argv[]);
> -OVS_NO_RETURN static void usage(void);
> -
> -static char *vtep_remote;
> -static char *ovnsb_remote;
> -static char *default_db_;
> -
> -int
> -main(int argc, char *argv[])
> -{
> -    struct unixctl_server *unixctl;
> -    bool exiting;
> -    int retval;
> -
> -    ovs_cmdl_proctitle_init(argc, argv);
> -    set_program_name(argv[0]);
> -    service_start(&argc, &argv);
> -    parse_options(argc, argv);
> -    fatal_ignore_sigpipe();
> -
> -    daemonize_start(false);
> -
> -    retval = unixctl_server_create(NULL, &unixctl);
> -    if (retval) {
> -        exit(EXIT_FAILURE);
> -    }
> -    unixctl_command_register("exit", "", 0, 0, ovn_controller_vtep_exit,
> -                             &exiting);
> -
> -    daemonize_complete();
> -
> -    /* Connect to VTEP database. */
> -    struct ovsdb_idl_loop vtep_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
> -        ovsdb_idl_create(vtep_remote, &vteprec_idl_class, true, true));
> -    ovsdb_idl_get_initial_snapshot(vtep_idl_loop.idl);
> -
> -    /* Connect to OVN SB database. */
> -    struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
> -        ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
> -    ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
> -
> -    /* Main loop. */
> -    exiting = false;
> -    while (!exiting) {
> -        struct controller_vtep_ctx ctx = {
> -            .vtep_idl = vtep_idl_loop.idl,
> -            .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
> -            .ovnsb_idl = ovnsb_idl_loop.idl,
> -            .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
> -        };
> -
> -        gateway_run(&ctx);
> -        binding_run(&ctx);
> -        vtep_run(&ctx);
> -        unixctl_server_run(unixctl);
> -
> -        unixctl_server_wait(unixctl);
> -        if (exiting) {
> -            poll_immediate_wake();
> -        }
> -        ovsdb_idl_loop_commit_and_wait(&vtep_idl_loop);
> -        ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
> -        poll_block();
> -        if (should_service_stop()) {
> -            exiting = true;
> -        }
> -    }
> -
> -    /* It's time to exit.  Clean up the databases. */
> -    bool done = false;
> -    while (!done) {
> -        struct controller_vtep_ctx ctx = {
> -            .vtep_idl = vtep_idl_loop.idl,
> -            .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
> -            .ovnsb_idl = ovnsb_idl_loop.idl,
> -            .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
> -        };
> -
> -        /* Run all of the cleanup functions, even if one of them returns
> false.
> -         * We're done if all of them return true. */
> -        done = binding_cleanup(&ctx);
> -        done = gateway_cleanup(&ctx) && done;
> -        done = vtep_cleanup(&ctx) && done;
> -        if (done) {
> -            poll_immediate_wake();
> -        }
> -
> -        ovsdb_idl_loop_commit_and_wait(&vtep_idl_loop);
> -        ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
> -        poll_block();
> -    }
> -
> -    unixctl_server_destroy(unixctl);
> -
> -    ovsdb_idl_loop_destroy(&vtep_idl_loop);
> -    ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
> -
> -    free(ovnsb_remote);
> -    free(vtep_remote);
> -    free(default_db_);
> -    service_stop();
> -
> -    exit(retval);
> -}
> -
> -static const char *
> -default_db(void)
> -{
> -    if (!default_db_) {
> -        default_db_ = xasprintf("unix:%s/db.sock", ovs_rundir());
> -    }
> -    return default_db_;
> -}
> -
> -static void
> -parse_options(int argc, char *argv[])
> -{
> -    enum {
> -        OPT_PEER_CA_CERT = UCHAR_MAX + 1,
> -        OPT_BOOTSTRAP_CA_CERT,
> -        VLOG_OPTION_ENUMS,
> -        DAEMON_OPTION_ENUMS,
> -        SSL_OPTION_ENUMS,
> -    };
> -
> -    static struct option long_options[] = {
> -        {"ovnsb-db", required_argument, NULL, 'd'},
> -        {"vtep-db", required_argument, NULL, 'D'},
> -        {"help", no_argument, NULL, 'h'},
> -        {"version", no_argument, NULL, 'V'},
> -        VLOG_LONG_OPTIONS,
> -        DAEMON_LONG_OPTIONS,
> -        STREAM_SSL_LONG_OPTIONS,
> -        {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
> -        {"bootstrap-ca-cert", required_argument, NULL,
> OPT_BOOTSTRAP_CA_CERT},
> -        {NULL, 0, NULL, 0}
> -    };
> -    char *short_options =
> ovs_cmdl_long_options_to_short_options(long_options);
> -
> -    for (;;) {
> -        int c;
> -
> -        c = getopt_long(argc, argv, short_options, long_options, NULL);
> -        if (c == -1) {
> -            break;
> -        }
> -
> -        switch (c) {
> -        case 'd':
> -            ovnsb_remote = xstrdup(optarg);
> -            break;
> -
> -        case 'D':
> -            vtep_remote = xstrdup(optarg);
> -            break;
> -
> -        case 'h':
> -            usage();
> -
> -        case 'V':
> -            ovs_print_version(OFP13_VERSION, OFP13_VERSION);
> -            exit(EXIT_SUCCESS);
> -
> -        VLOG_OPTION_HANDLERS
> -        DAEMON_OPTION_HANDLERS
> -        STREAM_SSL_OPTION_HANDLERS
> -
> -        case OPT_PEER_CA_CERT:
> -            stream_ssl_set_peer_ca_cert_file(optarg);
> -            break;
> -
> -        case OPT_BOOTSTRAP_CA_CERT:
> -            stream_ssl_set_ca_cert_file(optarg, true);
> -            break;
> -
> -        case '?':
> -            exit(EXIT_FAILURE);
> -
> -        default:
> -            abort();
> -        }
> -    }
> -    free(short_options);
> -
> -    if (!ovnsb_remote) {
> -        ovnsb_remote = xstrdup(default_sb_db());
> -    }
> -
> -    if (!vtep_remote) {
> -        vtep_remote = xstrdup(default_db());
> -    }
> -}
> -
> -static void
> -usage(void)
> -{
> -    printf("\
> -%s: OVN controller VTEP\n\
> -usage %s [OPTIONS]\n\
> -\n\
> -Options:\n\
> -  --vtep-db=DATABASE        connect to vtep database at DATABASE\n\
> -                            (default: %s)\n\
> -  --ovnsb-db=DATABASE       connect to ovn-sb database at DATABASE\n\
> -                            (default: %s)\n\
> -  -h, --help                display this help message\n\
> -  -o, --options             list available options\n\
> -  -V, --version             display version information\n\
> -", program_name, program_name, default_db(), default_sb_db());
> -    stream_usage("database", true, false, true);
> -    daemon_usage();
> -    vlog_usage();
> -    exit(EXIT_SUCCESS);
> -}
> -
> -
> -static void
> -ovn_controller_vtep_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
> -                       const char *argv[] OVS_UNUSED, void *exiting_)
> -{
> -    bool *exiting = exiting_;
> -    *exiting = true;
> -
> -    unixctl_command_reply(conn, NULL);
> -}
> diff --git a/ovn/controller-vtep/ovn-controller-vtep.h
> b/ovn/controller-vtep/ovn-controller-vtep.h
> deleted file mode 100644
> index 435a730d9..000000000
> --- a/ovn/controller-vtep/ovn-controller-vtep.h
> +++ /dev/null
> @@ -1,51 +0,0 @@
> -/* Copyright (c) 2015 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.
> - */
> -
> -
> -#ifndef OVN_CONTROLLER_VTEP_H
> -#define OVN_CONTROLLER_VTEP_H 1
> -
> -#include "ovn/lib/ovn-sb-idl.h"
> -
> -struct ovsdb_idl;
> -struct ovsdb_idl_txn;
> -
> -struct controller_vtep_ctx {
> -    struct ovsdb_idl *ovnsb_idl;
> -    struct ovsdb_idl_txn *ovnsb_idl_txn;
> -
> -    struct ovsdb_idl *vtep_idl;
> -    struct ovsdb_idl_txn *vtep_idl_txn;
> -};
> -
> -/* VTEP needs what VTEP needs. */
> -#define OVN_SB_ENCAP_TYPE "vxlan"
> -#define VTEP_ENCAP_TYPE "vxlan_over_ipv4"
> -
> -static inline const struct sbrec_chassis *
> -get_chassis_by_name(struct ovsdb_idl *ovnsb_idl, const char *chassis_id)
> -{
> -    const struct sbrec_chassis *chassis_rec;
> -
> -    SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
> -        if (!strcmp(chassis_rec->name, chassis_id)) {
> -            break;
> -        }
> -    }
> -
> -    return chassis_rec;
> -}
> -
> -#endif /* ovn/ovn-controller-vtep.h */
> diff --git a/ovn/controller-vtep/vtep.c b/ovn/controller-vtep/vtep.c
> deleted file mode 100644
> index a72b149eb..000000000
> --- a/ovn/controller-vtep/vtep.c
> +++ /dev/null
> @@ -1,600 +0,0 @@
> -/* Copyright (c) 2015 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 "vtep.h"
> -
> -#include "lib/hash.h"
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/shash.h"
> -#include "lib/smap.h"
> -#include "lib/sset.h"
> -#include "lib/util.h"
> -#include "ovn-controller-vtep.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "vtep/vtep-idl.h"
> -
> -VLOG_DEFINE_THIS_MODULE(vtep);
> -
> -struct vtep_rec_physical_locator_list_entry {
> -    struct ovs_list locators_node;
> -    const struct vteprec_physical_locator *vteprec_ploc;
> -};
> -
> -struct mmr_hash_node_data {
> -    const struct vteprec_mcast_macs_remote *mmr;
> -    struct shash physical_locators;
> -};
> -
> -/*
> - * Scans through the Binding table in ovnsb, and updates the vtep logical
> - * switch tunnel keys and the 'Ucast_Macs_Remote' table in the VTEP
> - * database.
> - *
> - */
> -
> -/* Searches the 'chassis_rec->encaps' for the first vtep tunnel
> - * configuration, returns the 'ip'.  Unless duplicated, the returned
> - * pointer cannot live past current vtep_run() execution. */
> -static const char *
> -get_chassis_vtep_ip(const struct sbrec_chassis *chassis_rec)
> -{
> -    if (chassis_rec) {
> -        size_t i;
> -
> -        for (i = 0; i < chassis_rec->n_encaps; i++) {
> -            if (!strcmp(chassis_rec->encaps[i]->type, "vxlan")) {
> -                return chassis_rec->encaps[i]->ip;
> -            }
> -        }
> -    }
> -
> -    return NULL;
> -}
> -
> -/* Creates a new 'Ucast_Macs_Remote'. */
> -static struct vteprec_ucast_macs_remote *
> -create_umr(struct ovsdb_idl_txn *vtep_idl_txn, const char *mac,
> -           const struct vteprec_logical_switch *vtep_ls)
> -{
> -    struct vteprec_ucast_macs_remote *new_umr =
> -        vteprec_ucast_macs_remote_insert(vtep_idl_txn);
> -
> -    vteprec_ucast_macs_remote_set_MAC(new_umr, mac);
> -    vteprec_ucast_macs_remote_set_logical_switch(new_umr, vtep_ls);
> -
> -    return new_umr;
> -}
> -
> -/* Creates a new 'Physical_Locator'. */
> -static struct vteprec_physical_locator *
> -create_pl(struct ovsdb_idl_txn *vtep_idl_txn, const char *chassis_ip)
> -{
> -    struct vteprec_physical_locator *new_pl =
> -        vteprec_physical_locator_insert(vtep_idl_txn);
> -
> -    vteprec_physical_locator_set_dst_ip(new_pl, chassis_ip);
> -    vteprec_physical_locator_set_encapsulation_type(new_pl,
> VTEP_ENCAP_TYPE);
> -
> -    return new_pl;
> -}
> -
> -/* Creates a new 'Mcast_Macs_Remote'. */
> -static void
> -vtep_create_mmr(struct ovsdb_idl_txn *vtep_idl_txn, const char *mac,
> -                const struct vteprec_logical_switch *vtep_ls,
> -                const struct vteprec_physical_locator_set *ploc_set)
> -{
> -    struct vteprec_mcast_macs_remote *new_mmr =
> -       vteprec_mcast_macs_remote_insert(vtep_idl_txn);
> -
> -    vteprec_mcast_macs_remote_set_MAC(new_mmr, mac);
> -    vteprec_mcast_macs_remote_set_logical_switch(new_mmr, vtep_ls);
> -    vteprec_mcast_macs_remote_set_locator_set(new_mmr, ploc_set);
> -}
> -
> -/* Compares previous and new mmr locator sets and returns true if they
> - * differ and false otherwise. This function also preps a new locator
> - * set for database write.
> - *
> - * 'locators_list' is the new set of locators for the associated
> - * 'Mcast_Macs_Remote' entry passed in and is queried to generate the
> - * new set of locators in vtep database format. */
> -static bool
> -vtep_process_pls(const struct ovs_list *locators_list,
> -                 const struct mmr_hash_node_data *mmr_ext,
> -                 struct vteprec_physical_locator **locators)
> -{
> -    size_t n_locators_prev = 0;
> -    size_t n_locators_new = ovs_list_size(locators_list);
> -    bool locator_lists_differ = false;
> -
> -    if (mmr_ext) {
> -        n_locators_prev = mmr_ext->mmr->locator_set->n_locators;
> -    }
> -    if (n_locators_prev != n_locators_new) {
> -        locator_lists_differ = true;
> -    }
> -
> -    if (n_locators_new) {
> -        int i = 0;
> -        struct vtep_rec_physical_locator_list_entry *ploc_entry;
> -        LIST_FOR_EACH (ploc_entry, locators_node, locators_list) {
> -            locators[i] = (struct vteprec_physical_locator *)
> -                           ploc_entry->vteprec_ploc;
> -            if (mmr_ext && !shash_find_data(&mmr_ext->physical_locators,
> -                                            locators[i]->dst_ip)) {
> -                    locator_lists_differ = true;
> -            }
> -            i++;
> -        }
> -    }
> -
> -    return locator_lists_differ;
> -}
> -
> -/* Creates a new 'Mcast_Macs_Remote' entry if needed and also cleans up
> - * out-dated remote mcast mac entries as needed. */
> -static void
> -vtep_update_mmr(struct ovsdb_idl_txn *vtep_idl_txn,
> -                struct ovs_list *locators_list,
> -                const struct vteprec_logical_switch *vtep_ls,
> -                const struct mmr_hash_node_data *mmr_ext)
> -{
> -    struct vteprec_physical_locator **locators = NULL;
> -    size_t n_locators_new = ovs_list_size(locators_list);
> -    bool mmr_changed;
> -
> -    locators = xmalloc(n_locators_new * sizeof *locators);
> -
> -    mmr_changed = vtep_process_pls(locators_list, mmr_ext, locators);
> -
> -    if (mmr_ext && !n_locators_new) {
> -        vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
> -    } else if ((mmr_ext && mmr_changed) ||
> -               (!mmr_ext && n_locators_new)) {
> -
> -        const struct vteprec_physical_locator_set *ploc_set =
> -            vteprec_physical_locator_set_insert(vtep_idl_txn);
> -
> -        vtep_create_mmr(vtep_idl_txn, "unknown-dst", vtep_ls, ploc_set);
> -
> -        vteprec_physical_locator_set_set_locators(ploc_set, locators,
> -                                                  n_locators_new);
> -    }
> -    free(locators);
> -}
> -
> -/* Updates the vtep Logical_Switch table entries' tunnel keys based
> - * on the port bindings. */
> -static void
> -vtep_lswitch_run(struct shash *vtep_pbs, struct sset *vtep_pswitches,
> -                 struct shash *vtep_lswitches)
> -{
> -    struct sset used_ls = SSET_INITIALIZER(&used_ls);
> -    struct shash_node *node;
> -
> -    /* Collects the logical switch bindings from port binding entries.
> -     * Since the binding module has already guaranteed that each vtep
> -     * logical switch is bound only to one ovn-sb logical datapath,
> -     * we can just iterate and assign tunnel key to vtep logical switch.
> */
> -    SHASH_FOR_EACH (node, vtep_pbs) {
> -        const struct sbrec_port_binding *port_binding_rec = node->data;
> -        const char *pswitch_name = smap_get(&port_binding_rec->options,
> -                                            "vtep-physical-switch");
> -        const char *lswitch_name = smap_get(&port_binding_rec->options,
> -                                            "vtep-logical-switch");
> -        const struct vteprec_logical_switch *vtep_ls;
> -
> -        /* If 'port_binding_rec->chassis' exists then 'pswitch_name'
> -         * and 'lswitch_name' must also exist. */
> -        if (!pswitch_name || !lswitch_name) {
> -            /* This could only happen when someone directly modifies the
> -             * database,  (e.g. using ovn-sbctl). */
> -            VLOG_ERR("logical port (%s) with no 'options:vtep-physical-"
> -                     "switch' or 'options:vtep-logical-switch' specified "
> -                     "is bound to chassis (%s).",
> -                     port_binding_rec->logical_port,
> -                     port_binding_rec->chassis->name);
> -            continue;
> -        }
> -        vtep_ls = shash_find_data(vtep_lswitches, lswitch_name);
> -        /* Also checks 'pswitch_name' since the same 'lswitch_name' could
> -         * exist in multiple vtep database instances and be bound to
> different
> -         * ovn logical networks. */
> -        if (vtep_ls && sset_find(vtep_pswitches, pswitch_name)) {
> -            int64_t tnl_key;
> -
> -            if (sset_find(&used_ls, lswitch_name)) {
> -                continue;
> -            }
> -
> -            tnl_key = port_binding_rec->datapath->tunnel_key;
> -            if (vtep_ls->n_tunnel_key
> -                && vtep_ls->tunnel_key[0] != tnl_key) {
> -                VLOG_DBG("set vtep logical switch (%s) tunnel key from "
> -                         "(%"PRId64") to (%"PRId64")", vtep_ls->name,
> -                         vtep_ls->tunnel_key[0], tnl_key);
> -            }
> -            vteprec_logical_switch_set_tunnel_key(vtep_ls, &tnl_key, 1);
> -
> -            /* OVN is expected to always use source node replication mode,
> -             * hence the replication mode is hard-coded for each logical
> -             * switch in the context of ovn-controller-vtep. */
> -            vteprec_logical_switch_set_replication_mode(vtep_ls,
> "source_node");
> -            sset_add(&used_ls, lswitch_name);
> -        }
> -    }
> -    /* Resets the tunnel keys for unused vtep logical switches. */
> -    SHASH_FOR_EACH (node, vtep_lswitches) {
> -        if (!sset_find(&used_ls, node->name)) {
> -            int64_t tnl_key = 0;
> -            vteprec_logical_switch_set_tunnel_key(node->data, &tnl_key,
> 1);
> -        }
> -    }
> -    sset_destroy(&used_ls);
> -}
> -
> -/* Updates the vtep 'Ucast_Macs_Remote' and 'Mcast_Macs_Remote' tables
> based
> - * on non-vtep port bindings. */
> -static void
> -vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash
> *ucast_macs_rmts,
> -              struct shash *mcast_macs_rmts, struct shash
> *physical_locators,
> -              struct shash *vtep_lswitches, struct shash *non_vtep_pbs)
> -{
> -    struct shash_node *node;
> -    struct hmap ls_map;
> -
> -    /* Maps from ovn logical datapath tunnel key (which is also the vtep
> -     * logical switch tunnel key) to the corresponding vtep logical switch
> -     * instance.  Also, the shash map 'added_macs' is used for checking
> -     * duplicated MAC addresses in the same ovn logical datapath.
> 'mmr_ext'
> -     * is used to track mmr info per LS that needs creation/update and
> -     * 'locators_list' collects the new physical locators to be bound for
> -     * an mmr_ext; 'physical_locators' is used to track existing locators
> and
> -     * filter duplicates per logical switch. */
> -    struct ls_hash_node {
> -        struct hmap_node hmap_node;
> -
> -        const struct vteprec_logical_switch *vtep_ls;
> -        struct shash added_macs;
> -
> -        struct ovs_list locators_list;
> -        struct shash physical_locators;
> -        struct mmr_hash_node_data *mmr_ext;
> -    };
> -
> -    hmap_init(&ls_map);
> -    SHASH_FOR_EACH (node, vtep_lswitches) {
> -        const struct vteprec_logical_switch *vtep_ls = node->data;
> -        struct ls_hash_node *ls_node;
> -
> -        if (!vtep_ls->n_tunnel_key) {
> -            continue;
> -        }
> -        ls_node = xmalloc(sizeof *ls_node);
> -        ls_node->vtep_ls = vtep_ls;
> -        shash_init(&ls_node->added_macs);
> -        shash_init(&ls_node->physical_locators);
> -        ovs_list_init(&ls_node->locators_list);
> -        ls_node->mmr_ext = NULL;
> -        hmap_insert(&ls_map, &ls_node->hmap_node,
> -                    hash_uint64((uint64_t) vtep_ls->tunnel_key[0]));
> -    }
> -
> -    SHASH_FOR_EACH (node, non_vtep_pbs) {
> -        const struct sbrec_port_binding *port_binding_rec = node->data;
> -        const struct sbrec_chassis *chassis_rec;
> -        struct ls_hash_node *ls_node;
> -        const char *chassis_ip;
> -        int64_t tnl_key;
> -        size_t i;
> -
> -        chassis_rec = port_binding_rec->chassis;
> -        if (!chassis_rec) {
> -            continue;
> -        }
> -
> -        tnl_key = port_binding_rec->datapath->tunnel_key;
> -        HMAP_FOR_EACH_WITH_HASH (ls_node, hmap_node,
> -                                 hash_uint64((uint64_t) tnl_key),
> -                                 &ls_map) {
> -            if (ls_node->vtep_ls->tunnel_key[0] == tnl_key) {
> -                break;
> -            }
> -        }
> -        /* If 'ls_node' is NULL, that means no vtep logical switch is
> -         * attached to the corresponding ovn logical datapath, so pass.
> -         */
> -        if (!ls_node) {
> -            continue;
> -        }
> -
> -        chassis_ip = get_chassis_vtep_ip(chassis_rec);
> -        /* Unreachable chassis, continue. */
> -        if (!chassis_ip) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> -            VLOG_INFO_RL(&rl, "VTEP tunnel encap on chassis (%s) not
> found",
> -                         chassis_rec->name);
> -            continue;
> -        }
> -
> -        const struct vteprec_physical_locator *pl =
> -            shash_find_data(physical_locators, chassis_ip);
> -        if (!pl) {
> -            pl = create_pl(vtep_idl_txn, chassis_ip);
> -            shash_add(physical_locators, chassis_ip, pl);
> -        }
> -
> -        const struct vteprec_physical_locator *ls_pl =
> -            shash_find_data(&ls_node->physical_locators, chassis_ip);
> -        if (!ls_pl) {
> -            struct vtep_rec_physical_locator_list_entry *ploc_entry =
> -                xmalloc(sizeof *ploc_entry);
> -            ploc_entry->vteprec_ploc = pl;
> -            ovs_list_push_back(&ls_node->locators_list,
> -                               &ploc_entry->locators_node);
> -            shash_add(&ls_node->physical_locators, chassis_ip, pl);
> -        }
> -
> -        char *mac_tnlkey = xasprintf("%s_%"PRId64, "unknown-dst",
> tnl_key);
> -        ls_node->mmr_ext = shash_find_data(mcast_macs_rmts, mac_tnlkey);
> -
> -        if (ls_node->mmr_ext &&
> -            ls_node->mmr_ext->mmr->logical_switch == ls_node->vtep_ls) {
> -
> -            /* Delete the entry from the hash table so the mmr does not
> get
> -             * removed from the DB later on during stale checking. */
> -            shash_find_and_delete(mcast_macs_rmts, mac_tnlkey);
> -        }
> -        free(mac_tnlkey);
> -
> -        for (i = 0; i < port_binding_rec->n_mac; i++) {
> -            const struct vteprec_ucast_macs_remote *umr;
> -            const struct sbrec_port_binding *conflict;
> -            char *mac = port_binding_rec->mac[i];
> -
> -            /* Checks for duplicate MAC in the same vtep logical switch.
> */
> -            conflict = shash_find_data(&ls_node->added_macs, mac);
> -            if (conflict) {
> -                VLOG_WARN("MAC address (%s) has already been known to be "
> -                          "on logical port (%s) in the same logical "
> -                          "datapath, so just ignore this logical port
> (%s)",
> -                          mac, conflict->logical_port,
> -                          port_binding_rec->logical_port);
> -                continue;
> -            }
> -            shash_add(&ls_node->added_macs, mac, port_binding_rec);
> -
> -            char *mac_ip_tnlkey = xasprintf("%s_%s_%"PRId64, mac,
> chassis_ip,
> -                                            tnl_key);
> -            umr = shash_find_data(ucast_macs_rmts, mac_ip_tnlkey);
> -            /* If finds the 'umr' entry for the mac, ip, and tnl_key,
> deletes
> -             * the entry from shash so that it is not gargage collected.
> -             *
> -             * If not found, creates a new 'umr' entry. */
> -            if (umr && umr->logical_switch == ls_node->vtep_ls) {
> -                shash_find_and_delete(ucast_macs_rmts, mac_ip_tnlkey);
> -            } else {
> -                const struct vteprec_ucast_macs_remote *new_umr;
> -                new_umr = create_umr(vtep_idl_txn, mac, ls_node->vtep_ls);
> -                vteprec_ucast_macs_remote_set_locator(new_umr, pl);
> -            }
> -            free(mac_ip_tnlkey);
> -        }
> -    }
> -
> -    /* Removes all remaining 'umr's, since they do not exist anymore. */
> -    SHASH_FOR_EACH (node, ucast_macs_rmts) {
> -        vteprec_ucast_macs_remote_delete(node->data);
> -    }
> -    struct ls_hash_node *iter, *next;
> -    HMAP_FOR_EACH_SAFE (iter, next, hmap_node, &ls_map) {
> -        struct vtep_rec_physical_locator_list_entry *ploc_entry;
> -        vtep_update_mmr(vtep_idl_txn, &iter->locators_list,
> -                        iter->vtep_ls, iter->mmr_ext);
> -        LIST_FOR_EACH_POP(ploc_entry, locators_node,
> -                          &iter->locators_list) {
> -            free(ploc_entry);
> -        }
> -        hmap_remove(&ls_map, &iter->hmap_node);
> -        shash_destroy(&iter->added_macs);
> -        shash_destroy(&iter->physical_locators);
> -        free(iter);
> -    }
> -    hmap_destroy(&ls_map);
> -
> -    /* Clean stale 'Mcast_Macs_Remote' */
> -    struct mmr_hash_node_data *mmr_ext;
> -    SHASH_FOR_EACH (node, mcast_macs_rmts) {
> -        mmr_ext = node->data;
> -        vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
> -    }
> -}
> -
> -/* Resets all logical switches' 'tunnel_key' to NULL */
> -static bool
> -vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
> -{
> -   const struct vteprec_logical_switch *vtep_ls;
> -    bool done = true;
> -
> -    VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, vtep_idl) {
> -        if (vtep_ls->n_tunnel_key) {
> -            vteprec_logical_switch_set_tunnel_key(vtep_ls, NULL, 0);
> -            done = false;
> -        }
> -    }
> -
> -    return done;
> -}
> -
> -/* Removes all entries in the 'Ucast_Macs_Remote' table in the vtep
> database.
> - * Returns true when all done (i.e. no entry to remove). */
> -static bool
> -vtep_ucast_macs_cleanup(struct ovsdb_idl *vtep_idl)
> -{
> -    const struct vteprec_ucast_macs_remote *umr;
> -
> -    VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, vtep_idl) {
> -        vteprec_ucast_macs_remote_delete(umr);
> -        return false;
> -    }
> -
> -    return true;
> -}
> -
> -/* Removes all entries in the 'Mcast_Macs_Remote' table in vtep database.
> - * Returns true when all done (i.e. no entry to remove). */
> -static bool
> -vtep_mcast_macs_cleanup(struct ovsdb_idl *vtep_idl)
> -{
> -    const struct vteprec_mcast_macs_remote *mmr;
> -
> -    VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, vtep_idl) {
> -        vteprec_mcast_macs_remote_delete(mmr);
> -        return false;
> -    }
> -
> -    return true;
> -}
> -
> -/* Updates vtep logical switch tunnel keys. */
> -void
> -vtep_run(struct controller_vtep_ctx *ctx)
> -{
> -    if (!ctx->vtep_idl_txn) {
> -        return;
> -    }
> -
> -    struct sset vtep_pswitches = SSET_INITIALIZER(&vtep_pswitches);
> -    struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
> -    struct shash ucast_macs_rmts = SHASH_INITIALIZER(&ucast_macs_rmts);
> -    struct shash mcast_macs_rmts = SHASH_INITIALIZER(&mcast_macs_rmts);
> -    struct shash physical_locators =
> SHASH_INITIALIZER(&physical_locators);
> -    struct shash vtep_pbs = SHASH_INITIALIZER(&vtep_pbs);
> -    struct shash non_vtep_pbs = SHASH_INITIALIZER(&non_vtep_pbs);
> -    const struct vteprec_physical_switch *vtep_ps;
> -    const struct vteprec_logical_switch *vtep_ls;
> -    const struct vteprec_ucast_macs_remote *umr;
> -    const struct sbrec_port_binding *port_binding_rec;
> -    const struct vteprec_mcast_macs_remote *mmr;
> -    struct shash_node *node;
> -
> -    /* Collects 'Physical_Switch's. */
> -    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (vtep_ps, ctx->vtep_idl) {
> -        sset_add(&vtep_pswitches, vtep_ps->name);
> -    }
> -
> -    /* Collects 'Logical_Switch's. */
> -    VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, ctx->vtep_idl) {
> -        shash_add(&vtep_lswitches, vtep_ls->name, vtep_ls);
> -    }
> -
> -    /* Collects 'Ucast_Macs_Remote's. */
> -    VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, ctx->vtep_idl) {
> -        char *mac_ip_tnlkey =
> -            xasprintf("%s_%s_%"PRId64, umr->MAC,
> -                      umr->locator ? umr->locator->dst_ip : "",
> -                      umr->logical_switch &&
> umr->logical_switch->n_tunnel_key
> -                          ? umr->logical_switch->tunnel_key[0] :
> INT64_MAX);
> -
> -        shash_add(&ucast_macs_rmts, mac_ip_tnlkey, umr);
> -        free(mac_ip_tnlkey);
> -    }
> -
> -    /* Collects 'Mcast_Macs_Remote's. */
> -    VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, ctx->vtep_idl) {
> -        struct mmr_hash_node_data *mmr_ext = xmalloc(sizeof *mmr_ext);;
> -        char *mac_tnlkey =
> -            xasprintf("%s_%"PRId64, mmr->MAC,
> -                      mmr->logical_switch &&
> mmr->logical_switch->n_tunnel_key
> -                          ? mmr->logical_switch->tunnel_key[0] :
> INT64_MAX);
> -
> -        shash_add(&mcast_macs_rmts, mac_tnlkey, mmr_ext);
> -        mmr_ext->mmr = mmr;
> -
> -        shash_init(&mmr_ext->physical_locators);
> -        for (size_t i = 0; i < mmr->locator_set->n_locators; i++) {
> -            shash_add(&mmr_ext->physical_locators,
> -                      mmr->locator_set->locators[i]->dst_ip,
> -                      mmr->locator_set->locators[i]);
> -        }
> -
> -        free(mac_tnlkey);
> -    }
> -
> -    /* Collects 'Physical_Locator's. */
> -    const struct vteprec_physical_locator *pl;
> -    VTEPREC_PHYSICAL_LOCATOR_FOR_EACH (pl, ctx->vtep_idl) {
> -        shash_add(&physical_locators, pl->dst_ip, pl);
> -    }
> -
> -    /* Collects and classifies 'Port_Binding's. */
> -    SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
> -        struct shash *target =
> -            !strcmp(port_binding_rec->type, "vtep") ? &vtep_pbs :
> &non_vtep_pbs;
> -
> -        if (!port_binding_rec->chassis) {
> -            continue;
> -        }
> -        shash_add(target, port_binding_rec->logical_port,
> port_binding_rec);
> -    }
> -
> -    ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
> -                              "ovn-controller-vtep: update logical switch
> "
> -                              "tunnel keys and 'ucast_macs_remote's");
> -
> -    vtep_lswitch_run(&vtep_pbs, &vtep_pswitches, &vtep_lswitches);
> -    vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts,
> -                  &mcast_macs_rmts, &physical_locators,
> -                  &vtep_lswitches, &non_vtep_pbs);
> -
> -    sset_destroy(&vtep_pswitches);
> -    shash_destroy(&vtep_lswitches);
> -    shash_destroy(&ucast_macs_rmts);
> -    SHASH_FOR_EACH (node, &mcast_macs_rmts) {
> -        struct mmr_hash_node_data *mmr_ext = node->data;
> -        shash_destroy(&mmr_ext->physical_locators);
> -        free(mmr_ext);
> -    }
> -    shash_destroy(&mcast_macs_rmts);
> -    shash_destroy(&physical_locators);
> -    shash_destroy(&vtep_pbs);
> -    shash_destroy(&non_vtep_pbs);
> -}
> -
> -/* Cleans up all related entries in vtep.  Returns true when done (i.e.
> there
> - * is no change made to 'ctx->vtep_idl'), otherwise returns false. */
> -bool
> -vtep_cleanup(struct controller_vtep_ctx *ctx)
> -{
> -    if (!ctx->vtep_idl_txn) {
> -        return false;
> -    }
> -
> -    bool all_done;
> -
> -    ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
> -                              "ovn-controller-vtep: cleaning up vtep "
> -                              "configuration");
> -    all_done = vtep_lswitch_cleanup(ctx->vtep_idl);
> -    all_done = vtep_ucast_macs_cleanup(ctx->vtep_idl) && all_done;
> -    all_done = vtep_mcast_macs_cleanup(ctx->vtep_idl) && all_done;
> -
> -    return all_done;
> -}
> diff --git a/ovn/controller-vtep/vtep.h b/ovn/controller-vtep/vtep.h
> deleted file mode 100644
> index 97c87b7a7..000000000
> --- a/ovn/controller-vtep/vtep.h
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -/* Copyright (c) 2015 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.
> - */
> -
> -
> -#ifndef OVN_VTEP_H
> -#define OVN_VTEP_H 1
> -
> -#include <stdbool.h>
> -
> -struct controller_vtep_ctx;
> -
> -void vtep_run(struct controller_vtep_ctx *);
> -bool vtep_cleanup(struct controller_vtep_ctx *);
> -
> -#endif /* ovn/controller-vtep/vtep.h */
> diff --git a/ovn/controller/.gitignore b/ovn/controller/.gitignore
> deleted file mode 100644
> index 4199a3741..000000000
> --- a/ovn/controller/.gitignore
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -/ovn-controller
> -/ovn-controller.8
> diff --git a/ovn/controller/automake.mk b/ovn/controller/automake.mk
> deleted file mode 100644
> index 193ea690b..000000000
> --- a/ovn/controller/automake.mk
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -bin_PROGRAMS += ovn/controller/ovn-controller
> -ovn_controller_ovn_controller_SOURCES = \
> -       ovn/controller/bfd.c \
> -       ovn/controller/bfd.h \
> -       ovn/controller/binding.c \
> -       ovn/controller/binding.h \
> -       ovn/controller/chassis.c \
> -       ovn/controller/chassis.h \
> -       ovn/controller/encaps.c \
> -       ovn/controller/encaps.h \
> -       ovn/controller/ha-chassis.c \
> -       ovn/controller/ha-chassis.h \
> -       ovn/controller/ip-mcast.c \
> -       ovn/controller/ip-mcast.h \
> -       ovn/controller/lflow.c \
> -       ovn/controller/lflow.h \
> -       ovn/controller/lport.c \
> -       ovn/controller/lport.h \
> -       ovn/controller/ofctrl.c \
> -       ovn/controller/ofctrl.h \
> -       ovn/controller/pinctrl.c \
> -       ovn/controller/pinctrl.h \
> -       ovn/controller/patch.c \
> -       ovn/controller/patch.h \
> -       ovn/controller/ovn-controller.c \
> -       ovn/controller/ovn-controller.h \
> -       ovn/controller/physical.c \
> -       ovn/controller/physical.h
> -ovn_controller_ovn_controller_LDADD = ovn/lib/libovn.la lib/
> libopenvswitch.la
> -man_MANS += ovn/controller/ovn-controller.8
> -EXTRA_DIST += ovn/controller/ovn-controller.8.xml
> -CLEANFILES += ovn/controller/ovn-controller.8
> diff --git a/ovn/controller/bfd.c b/ovn/controller/bfd.c
> deleted file mode 100644
> index 22db00af7..000000000
> --- a/ovn/controller/bfd.c
> +++ /dev/null
> @@ -1,268 +0,0 @@
> -/* Copyright (c) 2017 Red Hat, 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 "bfd.h"
> -#include "encaps.h"
> -#include "lport.h"
> -#include "ovn-controller.h"
> -
> -#include "lib/hash.h"
> -#include "lib/sset.h"
> -#include "lib/util.h"
> -#include "lib/vswitch-idl.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn-controller.h"
> -
> -VLOG_DEFINE_THIS_MODULE(ovn_bfd);
> -
> -void
> -bfd_register_ovs_idl(struct ovsdb_idl *ovs_idl)
> -{
> -    /* NOTE: this assumes that binding.c has added the
> -     * ovsrec_interface table */
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status);
> -}
> -
> -void
> -bfd_calculate_active_tunnels(const struct ovsrec_bridge *br_int,
> -                             struct sset *active_tunnels)
> -{
> -    int i;
> -
> -    if (!br_int) {
> -        /* Nothing to do if integration bridge doesn't exist. */
> -        return;
> -    }
> -
> -    for (i = 0; i < br_int->n_ports; i++) {
> -        const struct ovsrec_port *port_rec = br_int->ports[i];
> -
> -        if (!strcmp(port_rec->name, br_int->name)) {
> -            continue;
> -        }
> -
> -        int j;
> -        for (j = 0; j < port_rec->n_interfaces; j++) {
> -            const struct ovsrec_interface *iface_rec;
> -            iface_rec = port_rec->interfaces[j];
> -
> -            /* Check if this is a tunnel interface. */
> -            if (smap_get(&iface_rec->options, "remote_ip")) {
> -                /* Add ovn-chassis-id if the bfd_status of the tunnel
> -                 * is active */
> -                const char *bfd = smap_get(&iface_rec->bfd, "enable");
> -                if (bfd && !strcmp(bfd, "true")) {
> -                    const char *status = smap_get(&iface_rec->bfd_status,
> -                                                  "state");
> -                    if (status && !strcmp(status, "up")) {
> -                        const char *id = smap_get(&port_rec->external_ids,
> -                                                  "ovn-chassis-id");
> -                        if (id) {
> -                            char *chassis_name = NULL;
> -
> -                            if (encaps_tunnel_id_parse(id, &chassis_name,
> -                                                       NULL)) {
> -                                if (!sset_contains(active_tunnels,
> -                                                   chassis_name)) {
> -                                    sset_add(active_tunnels,
> chassis_name);
> -                                }
> -                                free(chassis_name);
> -                            }
> -                        }
> -                    }
> -                }
> -            }
> -        }
> -    }
> -}
> -
> -/* Loops through the HA chassis groups in the SB DB and returns
> - * the set of chassis which the call can establish the BFD sessions
> - * with.
> - * Eg.
> - * If there are 2 HA chassis groups.
> - * Group name - hapgrp1
> - *   - HA chassis - (HA1, HA2, HA3)
> - *   - ref chassis - (C1, C2)
> - *
> - * Group name - hapgrp2
> - *   - HA chassis - (HA1, HA4, HA5)
> - *   - ref chassis - (C1, C3, C4)
> - *
> - * If 'our_chassis' is HA1 then this function returns
> - *  bfd chassis set - (HA2, HA3, HA4 HA5, C1, C2, C3, C4)
> - *
> - * If 'our_chassis' is C1 then this function returns
> - *  bfd chassis set - (HA1, HA2, HA3, HA4, HA5)
> - *
> - * If 'our_chassis' is HA5 then this function returns
> - *  bfd chassis set - (HA1, HA4, C1, C3, C4)
> - *
> - * If 'our_chassis' is C2 then this function returns
> - *  bfd chassis set - (HA1, HA2, HA3)
> - *
> - * If 'our_chassis' is C5 then this function returns empty bfd set.
> - */
> -static void
> -bfd_calculate_chassis(
> -    const struct sbrec_chassis *our_chassis,
> -    const struct sbrec_ha_chassis_group_table *ha_chassis_grp_table,
> -    struct sset *bfd_chassis)
> -{
> -    const struct sbrec_ha_chassis_group *ha_chassis_grp;
> -    SBREC_HA_CHASSIS_GROUP_TABLE_FOR_EACH (ha_chassis_grp,
> -                                           ha_chassis_grp_table) {
> -        bool is_ha_chassis = false;
> -        struct sset grp_chassis = SSET_INITIALIZER(&grp_chassis);
> -        const struct sbrec_ha_chassis *ha_ch;
> -        bool bfd_setup_required = false;
> -        if (ha_chassis_grp->n_ha_chassis < 2) {
> -            /* No need to consider the chassis group for BFD if
> -             * there is  1 or no chassis in it. */
> -            continue;
> -        }
> -        for (size_t i = 0; i < ha_chassis_grp->n_ha_chassis; i++) {
> -            ha_ch = ha_chassis_grp->ha_chassis[i];
> -            if (!ha_ch->chassis) {
> -                continue;
> -            }
> -            sset_add(&grp_chassis, ha_ch->chassis->name);
> -            if (our_chassis == ha_ch->chassis) {
> -                is_ha_chassis = true;
> -                bfd_setup_required = true;
> -            }
> -        }
> -
> -        if (is_ha_chassis) {
> -            /* It's an HA chassis. So add the ref_chassis to the bfd set.
> */
> -            for (size_t i = 0; i < ha_chassis_grp->n_ref_chassis; i++) {
> -                sset_add(&grp_chassis,
> ha_chassis_grp->ref_chassis[i]->name);
> -            }
> -        } else {
> -            /* This is not an HA chassis. Check if this chassis is present
> -             * in the ref_chassis list. If so add the ha_chassis to the
> -             * sset .*/
> -            for (size_t i = 0; i < ha_chassis_grp->n_ref_chassis; i++) {
> -                if (our_chassis == ha_chassis_grp->ref_chassis[i]) {
> -                    bfd_setup_required = true;
> -                    break;
> -                }
> -            }
> -        }
> -
> -        if (bfd_setup_required) {
> -            const char *name;
> -            SSET_FOR_EACH (name, &grp_chassis) {
> -                sset_add(bfd_chassis, name);
> -            }
> -        }
> -        sset_destroy(&grp_chassis);
> -    }
> -}
> -
> -void
> -bfd_run(const struct ovsrec_interface_table *interface_table,
> -        const struct ovsrec_bridge *br_int,
> -        const struct sbrec_chassis *chassis_rec,
> -        const struct sbrec_ha_chassis_group_table *ha_chassis_grp_table,
> -        const struct sbrec_sb_global_table *sb_global_table)
> -{
> -    if (!chassis_rec) {
> -        return;
> -    }
> -    struct sset bfd_chassis = SSET_INITIALIZER(&bfd_chassis);
> -    bfd_calculate_chassis(chassis_rec, ha_chassis_grp_table,
> -                          &bfd_chassis);
> -
> -    /* Identify tunnels ports(connected to remote chassis id) to enable
> bfd */
> -    struct sset tunnels = SSET_INITIALIZER(&tunnels);
> -    struct sset bfd_ifaces = SSET_INITIALIZER(&bfd_ifaces);
> -    for (size_t k = 0; k < br_int->n_ports; k++) {
> -        const char *tunnel_id = smap_get(&br_int->ports[k]->external_ids,
> -                                          "ovn-chassis-id");
> -        if (tunnel_id) {
> -            char *chassis_name = NULL;
> -            char *port_name = br_int->ports[k]->name;
> -
> -            sset_add(&tunnels, port_name);
> -
> -            if (encaps_tunnel_id_parse(tunnel_id, &chassis_name, NULL)) {
> -                if (sset_contains(&bfd_chassis, chassis_name)) {
> -                    sset_add(&bfd_ifaces, port_name);
> -                }
> -                free(chassis_name);
> -            }
> -        }
> -    }
> -
> -    const struct sbrec_sb_global *sb
> -        = sbrec_sb_global_table_first(sb_global_table);
> -    struct smap bfd = SMAP_INITIALIZER(&bfd);
> -    smap_add(&bfd, "enable", "true");
> -
> -    if (sb) {
> -        const char *min_rx = smap_get(&sb->options, "bfd-min-rx");
> -        const char *decay_min_rx = smap_get(&sb->options,
> "bfd-decay-min-rx");
> -        const char *min_tx = smap_get(&sb->options, "bfd-min-tx");
> -        const char *mult = smap_get(&sb->options, "bfd-mult");
> -        if (min_rx) {
> -            smap_add(&bfd, "min_rx", min_rx);
> -        }
> -        if (decay_min_rx) {
> -            smap_add(&bfd, "decay_min_rx", decay_min_rx);
> -        }
> -        if (min_tx) {
> -            smap_add(&bfd, "min_tx", min_tx);
> -        }
> -        if (mult) {
> -            smap_add(&bfd, "mult", mult);
> -        }
> -    }
> -
> -    /* Enable or disable bfd */
> -    const struct ovsrec_interface *iface;
> -    OVSREC_INTERFACE_TABLE_FOR_EACH (iface, interface_table) {
> -        if (sset_contains(&tunnels, iface->name)) {
> -            if (sset_contains(&bfd_ifaces, iface->name)) {
> -                /* We need to enable BFD for this interface. Configure the
> -                 * BFD params if
> -                 *  - If BFD was disabled earlier
> -                 *  - Or if CMS has updated BFD config options.
> -                 */
> -                if (!smap_equal(&iface->bfd, &bfd)) {
> -                    ovsrec_interface_verify_bfd(iface);
> -                    ovsrec_interface_set_bfd(iface, &bfd);
> -                    VLOG_INFO("Enabled BFD on interface %s", iface->name);
> -                }
> -            } else {
> -                /* We need to disable BFD for this interface if it was
> enabled
> -                 * earlier. */
> -                if (smap_count(&iface->bfd)) {
> -                    ovsrec_interface_verify_bfd(iface);
> -                    ovsrec_interface_set_bfd(iface, NULL);
> -                    VLOG_INFO("Disabled BFD on interface %s",
> iface->name);
> -                }
> -            }
> -        }
> -    }
> -
> -    smap_destroy(&bfd);
> -    sset_destroy(&tunnels);
> -    sset_destroy(&bfd_ifaces);
> -    sset_destroy(&bfd_chassis);
> -}
> diff --git a/ovn/controller/bfd.h b/ovn/controller/bfd.h
> deleted file mode 100644
> index 17fab5323..000000000
> --- a/ovn/controller/bfd.h
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/* Copyright (c) 2017 Red Hat, 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.
> - */
> -
> -#ifndef OVN_BFD_H
> -#define OVN_BFD_H 1
> -
> -struct hmap;
> -struct ovsdb_idl;
> -struct ovsdb_idl_index;
> -struct ovsrec_bridge;
> -struct ovsrec_interface_table;
> -struct ovsrec_open_vswitch_table;
> -struct sbrec_chassis;
> -struct sbrec_sb_global_table;
> -struct sbrec_ha_chassis_group_table;
> -struct sset;
> -
> -void bfd_register_ovs_idl(struct ovsdb_idl *);
> -
> -void bfd_run(const struct ovsrec_interface_table *,
> -             const struct ovsrec_bridge *,
> -             const struct sbrec_chassis *,
> -             const struct sbrec_ha_chassis_group_table *,
> -             const struct sbrec_sb_global_table *);
> -
> -void  bfd_calculate_active_tunnels(const struct ovsrec_bridge *br_int,
> -                                   struct sset *active_tunnels);
> -
> -#endif
> diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
> deleted file mode 100644
> index ace0f811b..000000000
> --- a/ovn/controller/binding.c
> +++ /dev/null
> @@ -1,764 +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 "binding.h"
> -#include "ha-chassis.h"
> -#include "lflow.h"
> -#include "lport.h"
> -
> -#include "lib/bitmap.h"
> -#include "openvswitch/poll-loop.h"
> -#include "lib/sset.h"
> -#include "lib/util.h"
> -#include "lib/netdev.h"
> -#include "lib/vswitch-idl.h"
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/chassis-index.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn-controller.h"
> -
> -VLOG_DEFINE_THIS_MODULE(binding);
> -
> -#define OVN_QOS_TYPE "linux-htb"
> -
> -struct qos_queue {
> -    struct hmap_node node;
> -    uint32_t queue_id;
> -    uint32_t max_rate;
> -    uint32_t burst;
> -};
> -
> -void
> -binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
> -{
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges);
> -
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
> -
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_qos);
> -
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name);
> -    ovsdb_idl_track_add_column(ovs_idl,
> &ovsrec_interface_col_external_ids);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_status);
> -
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_qos);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type);
> -}
> -
> -static void
> -get_local_iface_ids(const struct ovsrec_bridge *br_int,
> -                    struct shash *lport_to_iface,
> -                    struct sset *local_lports,
> -                    struct sset *egress_ifaces)
> -{
> -    int i;
> -
> -    for (i = 0; i < br_int->n_ports; i++) {
> -        const struct ovsrec_port *port_rec = br_int->ports[i];
> -        const char *iface_id;
> -        int j;
> -
> -        if (!strcmp(port_rec->name, br_int->name)) {
> -            continue;
> -        }
> -
> -        for (j = 0; j < port_rec->n_interfaces; j++) {
> -            const struct ovsrec_interface *iface_rec;
> -
> -            iface_rec = port_rec->interfaces[j];
> -            iface_id = smap_get(&iface_rec->external_ids, "iface-id");
> -            int64_t ofport = iface_rec->n_ofport ? *iface_rec->ofport : 0;
> -
> -            if (iface_id && ofport > 0) {
> -                shash_add(lport_to_iface, iface_id, iface_rec);
> -                sset_add(local_lports, iface_id);
> -            }
> -
> -            /* Check if this is a tunnel interface. */
> -            if (smap_get(&iface_rec->options, "remote_ip")) {
> -                const char *tunnel_iface
> -                    = smap_get(&iface_rec->status, "tunnel_egress_iface");
> -                if (tunnel_iface) {
> -                    sset_add(egress_ifaces, tunnel_iface);
> -                }
> -            }
> -        }
> -    }
> -}
> -
> -static void
> -add_local_datapath__(struct ovsdb_idl_index
> *sbrec_datapath_binding_by_key,
> -                     struct ovsdb_idl_index
> *sbrec_port_binding_by_datapath,
> -                     struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                     const struct sbrec_datapath_binding *datapath,
> -                     bool has_local_l3gateway, int depth,
> -                     struct hmap *local_datapaths)
> -{
> -    uint32_t dp_key = datapath->tunnel_key;
> -    struct local_datapath *ld = get_local_datapath(local_datapaths,
> dp_key);
> -    if (ld) {
> -        if (has_local_l3gateway) {
> -            ld->has_local_l3gateway = true;
> -        }
> -        return;
> -    }
> -
> -    ld = xzalloc(sizeof *ld);
> -    hmap_insert(local_datapaths, &ld->hmap_node, dp_key);
> -    ld->datapath = datapath;
> -    ld->localnet_port = NULL;
> -    ld->has_local_l3gateway = has_local_l3gateway;
> -
> -    if (depth >= 100) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> -        VLOG_WARN_RL(&rl, "datapaths nested too deep");
> -        return;
> -    }
> -
> -    struct sbrec_port_binding *target =
> -        sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath);
> -    sbrec_port_binding_index_set_datapath(target, datapath);
> -
> -    const struct sbrec_port_binding *pb;
> -    SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
> -                                       sbrec_port_binding_by_datapath) {
> -        if (!strcmp(pb->type, "patch")) {
> -            const char *peer_name = smap_get(&pb->options, "peer");
> -            if (peer_name) {
> -                const struct sbrec_port_binding *peer;
> -
> -                peer = lport_lookup_by_name(sbrec_port_binding_by_name,
> -                                            peer_name);
> -
> -                if (peer && peer->datapath) {
> -                    add_local_datapath__(sbrec_datapath_binding_by_key,
> -                                         sbrec_port_binding_by_datapath,
> -                                         sbrec_port_binding_by_name,
> -                                         peer->datapath, false,
> -                                         depth + 1, local_datapaths);
> -                    ld->n_peer_ports++;
> -                    ld->peer_ports = xrealloc(ld->peer_ports,
> -                                              ld->n_peer_ports *
> -                                              sizeof *ld->peer_ports);
> -                    ld->peer_ports[ld->n_peer_ports - 1] = peer;
> -                }
> -            }
> -        }
> -    }
> -    sbrec_port_binding_index_destroy_row(target);
> -}
> -
> -static void
> -add_local_datapath(struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> -                   struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> -                   struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                   const struct sbrec_datapath_binding *datapath,
> -                   bool has_local_l3gateway, struct hmap *local_datapaths)
> -{
> -    add_local_datapath__(sbrec_datapath_binding_by_key,
> -                         sbrec_port_binding_by_datapath,
> -                         sbrec_port_binding_by_name,
> -                         datapath, has_local_l3gateway, 0,
> local_datapaths);
> -}
> -
> -static void
> -get_qos_params(const struct sbrec_port_binding *pb, struct hmap
> *queue_map)
> -{
> -    uint32_t max_rate = smap_get_int(&pb->options, "qos_max_rate", 0);
> -    uint32_t burst = smap_get_int(&pb->options, "qos_burst", 0);
> -    uint32_t queue_id = smap_get_int(&pb->options, "qdisc_queue_id", 0);
> -
> -    if ((!max_rate && !burst) || !queue_id) {
> -        /* Qos is not configured for this port. */
> -        return;
> -    }
> -
> -    struct qos_queue *node = xzalloc(sizeof *node);
> -    hmap_insert(queue_map, &node->node, hash_int(queue_id, 0));
> -    node->max_rate = max_rate;
> -    node->burst = burst;
> -    node->queue_id = queue_id;
> -}
> -
> -static const struct ovsrec_qos *
> -get_noop_qos(struct ovsdb_idl_txn *ovs_idl_txn,
> -             const struct ovsrec_qos_table *qos_table)
> -{
> -    const struct ovsrec_qos *qos;
> -    OVSREC_QOS_TABLE_FOR_EACH (qos, qos_table) {
> -        if (!strcmp(qos->type, "linux-noop")) {
> -            return qos;
> -        }
> -    }
> -
> -    if (!ovs_idl_txn) {
> -        return NULL;
> -    }
> -    qos = ovsrec_qos_insert(ovs_idl_txn);
> -    ovsrec_qos_set_type(qos, "linux-noop");
> -    return qos;
> -}
> -
> -static bool
> -set_noop_qos(struct ovsdb_idl_txn *ovs_idl_txn,
> -             const struct ovsrec_port_table *port_table,
> -             const struct ovsrec_qos_table *qos_table,
> -             struct sset *egress_ifaces)
> -{
> -    if (!ovs_idl_txn) {
> -        return false;
> -    }
> -
> -    const struct ovsrec_qos *noop_qos = get_noop_qos(ovs_idl_txn,
> qos_table);
> -    if (!noop_qos) {
> -        return false;
> -    }
> -
> -    const struct ovsrec_port *port;
> -    size_t count = 0;
> -
> -    OVSREC_PORT_TABLE_FOR_EACH (port, port_table) {
> -        if (sset_contains(egress_ifaces, port->name)) {
> -            ovsrec_port_set_qos(port, noop_qos);
> -            count++;
> -        }
> -        if (sset_count(egress_ifaces) == count) {
> -            break;
> -        }
> -    }
> -    return true;
> -}
> -
> -static void
> -set_qos_type(struct netdev *netdev, const char *type)
> -{
> -    int error = netdev_set_qos(netdev, type, NULL);
> -    if (error) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> -        VLOG_WARN_RL(&rl, "%s: could not set qdisc type \"%s\" (%s)",
> -                     netdev_get_name(netdev), type, ovs_strerror(error));
> -    }
> -}
> -
> -static void
> -setup_qos(const char *egress_iface, struct hmap *queue_map)
> -{
> -    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
> -    struct netdev *netdev_phy;
> -
> -    if (!egress_iface) {
> -        /* Queues cannot be configured. */
> -        return;
> -    }
> -
> -    int error = netdev_open(egress_iface, NULL, &netdev_phy);
> -    if (error) {
> -        VLOG_WARN_RL(&rl, "%s: could not open netdev (%s)",
> -                     egress_iface, ovs_strerror(error));
> -        return;
> -    }
> -
> -    /* Check current qdisc. */
> -    const char *qdisc_type;
> -    struct smap qdisc_details;
> -
> -    smap_init(&qdisc_details);
> -    if (netdev_get_qos(netdev_phy, &qdisc_type, &qdisc_details) != 0 ||
> -        qdisc_type[0] == '\0') {
> -        smap_destroy(&qdisc_details);
> -        netdev_close(netdev_phy);
> -        /* Qos is not supported. */
> -        return;
> -    }
> -    smap_destroy(&qdisc_details);
> -
> -    /* If we're not actually being requested to do any QoS:
> -     *
> -     *     - If the current qdisc type is OVN_QOS_TYPE, then we clear the
> qdisc
> -     *       type to "".  Otherwise, it's possible that our own leftover
> qdisc
> -     *       settings could cause strange behavior on egress.  Also, QoS
> is
> -     *       expensive and may waste CPU time even if it's not really in
> use.
> -     *
> -     *       OVN isn't the only software that can configure qdiscs, and
> -     *       physical interfaces are shared resources, so there is some
> risk in
> -     *       this strategy: we could disrupt some other program's QoS.
> -     *       Probably, to entirely avoid this possibility we would need
> to add
> -     *       a configuration setting.
> -     *
> -     *     - Otherwise leave the qdisc alone. */
> -    if (hmap_is_empty(queue_map)) {
> -        if (!strcmp(qdisc_type, OVN_QOS_TYPE)) {
> -            set_qos_type(netdev_phy, "");
> -        }
> -        netdev_close(netdev_phy);
> -        return;
> -    }
> -
> -    /* Configure qdisc. */
> -    if (strcmp(qdisc_type, OVN_QOS_TYPE)) {
> -        set_qos_type(netdev_phy, OVN_QOS_TYPE);
> -    }
> -
> -    /* Check and delete if needed. */
> -    struct netdev_queue_dump dump;
> -    unsigned int queue_id;
> -    struct smap queue_details;
> -    struct qos_queue *sb_info;
> -    struct hmap consistent_queues;
> -
> -    smap_init(&queue_details);
> -    hmap_init(&consistent_queues);
> -    NETDEV_QUEUE_FOR_EACH (&queue_id, &queue_details, &dump, netdev_phy) {
> -        bool is_queue_needed = false;
> -
> -        HMAP_FOR_EACH_WITH_HASH (sb_info, node, hash_int(queue_id, 0),
> -                                 queue_map) {
> -            is_queue_needed = true;
> -            if (sb_info->max_rate ==
> -                smap_get_int(&queue_details, "max-rate", 0)
> -                && sb_info->burst == smap_get_int(&queue_details,
> "burst", 0)) {
> -                /* This queue is consistent. */
> -                hmap_insert(&consistent_queues, &sb_info->node,
> -                            hash_int(queue_id, 0));
> -                break;
> -            }
> -        }
> -
> -        if (!is_queue_needed) {
> -            error = netdev_delete_queue(netdev_phy, queue_id);
> -            if (error) {
> -                VLOG_WARN_RL(&rl, "%s: could not delete queue %u (%s)",
> -                             egress_iface, queue_id, ovs_strerror(error));
> -            }
> -        }
> -    }
> -
> -    /* Create/Update queues. */
> -    HMAP_FOR_EACH (sb_info, node, queue_map) {
> -        if (hmap_contains(&consistent_queues, &sb_info->node)) {
> -            hmap_remove(&consistent_queues, &sb_info->node);
> -            continue;
> -        }
> -
> -        smap_clear(&queue_details);
> -        smap_add_format(&queue_details, "max-rate", "%d",
> sb_info->max_rate);
> -        smap_add_format(&queue_details, "burst", "%d", sb_info->burst);
> -        error = netdev_set_queue(netdev_phy, sb_info->queue_id,
> -                                 &queue_details);
> -        if (error) {
> -            VLOG_WARN_RL(&rl, "%s: could not configure queue %u (%s)",
> -                         egress_iface, sb_info->queue_id,
> ovs_strerror(error));
> -        }
> -    }
> -    smap_destroy(&queue_details);
> -    hmap_destroy(&consistent_queues);
> -    netdev_close(netdev_phy);
> -}
> -
> -static void
> -update_local_lport_ids(struct sset *local_lport_ids,
> -                       const struct sbrec_port_binding *binding_rec)
> -{
> -        char buf[16];
> -        snprintf(buf, sizeof(buf), "%"PRId64"_%"PRId64,
> -                 binding_rec->datapath->tunnel_key,
> -                 binding_rec->tunnel_key);
> -        sset_add(local_lport_ids, buf);
> -}
> -
> -/*
> - * Get the encap from the chassis for this port. The interface
> - * may have an external_ids:encap-ip=<encap-ip> set; if so we
> - * get the corresponding encap from the chassis.
> - * If "encap-ip" external-ids is not set, we'll not bind the port
> - * to any specific encap rec. and we'll pick up a tunnel port based on
> - * the chassis name alone for the port.
> - */
> -static struct sbrec_encap *
> -sbrec_get_port_encap(const struct sbrec_chassis *chassis_rec,
> -                     const struct ovsrec_interface *iface_rec)
> -{
> -
> -    if (!iface_rec) {
> -        return NULL;
> -    }
> -
> -    const char *encap_ip = smap_get(&iface_rec->external_ids, "encap-ip");
> -    if (!encap_ip) {
> -        return NULL;
> -    }
> -
> -    struct sbrec_encap *best_encap = NULL;
> -    uint32_t best_type = 0;
> -    for (int i = 0; i < chassis_rec->n_encaps; i++) {
> -        if (!strcmp(chassis_rec->encaps[i]->ip, encap_ip)) {
> -            uint32_t tun_type =
> get_tunnel_type(chassis_rec->encaps[i]->type);
> -            if (tun_type > best_type) {
> -                best_type = tun_type;
> -                best_encap = chassis_rec->encaps[i];
> -            }
> -        }
> -    }
> -    return best_encap;
> -}
> -
> -static bool
> -is_our_chassis(const struct sbrec_chassis *chassis_rec,
> -               const struct sbrec_port_binding *binding_rec,
> -               const struct sset *active_tunnels,
> -               const struct shash *lport_to_iface,
> -               const struct sset *local_lports)
> -{
> -    const struct ovsrec_interface *iface_rec
> -        = shash_find_data(lport_to_iface, binding_rec->logical_port);
> -
> -    bool our_chassis = false;
> -    if (iface_rec
> -        || (binding_rec->parent_port && binding_rec->parent_port[0] &&
> -            sset_contains(local_lports, binding_rec->parent_port))) {
> -        /* This port is in our chassis unless it is a localport. */
> -        our_chassis = strcmp(binding_rec->type, "localport");
> -    } else if (!strcmp(binding_rec->type, "l2gateway")) {
> -        const char *chassis_id = smap_get(&binding_rec->options,
> -                                          "l2gateway-chassis");
> -        our_chassis = chassis_id && !strcmp(chassis_id,
> chassis_rec->name);
> -    } else if (!strcmp(binding_rec->type, "chassisredirect") ||
> -               !strcmp(binding_rec->type, "external")) {
> -        our_chassis =
> ha_chassis_group_contains(binding_rec->ha_chassis_group,
> -                                                chassis_rec) &&
> -
> ha_chassis_group_is_active(binding_rec->ha_chassis_group,
> -                                                 active_tunnels,
> chassis_rec);
> -    } else if (!strcmp(binding_rec->type, "l3gateway")) {
> -        const char *chassis_id = smap_get(&binding_rec->options,
> -                                          "l3gateway-chassis");
> -        our_chassis = chassis_id && !strcmp(chassis_id,
> chassis_rec->name);
> -    }
> -
> -    return our_chassis;
> -}
> -
> -static void
> -consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                        struct ovsdb_idl_txn *ovs_idl_txn,
> -                        struct ovsdb_idl_index
> *sbrec_datapath_binding_by_key,
> -                        struct ovsdb_idl_index
> *sbrec_port_binding_by_datapath,
> -                        struct ovsdb_idl_index
> *sbrec_port_binding_by_name,
> -                        const struct sset *active_tunnels,
> -                        const struct sbrec_chassis *chassis_rec,
> -                        const struct sbrec_port_binding *binding_rec,
> -                        struct hmap *qos_map,
> -                        struct hmap *local_datapaths,
> -                        struct shash *lport_to_iface,
> -                        struct sset *local_lports,
> -                        struct sset *local_lport_ids)
> -{
> -    const struct ovsrec_interface *iface_rec
> -        = shash_find_data(lport_to_iface, binding_rec->logical_port);
> -
> -    bool our_chassis = is_our_chassis(chassis_rec, binding_rec,
> active_tunnels,
> -                                      lport_to_iface, local_lports);
> -    if (iface_rec
> -        || (binding_rec->parent_port && binding_rec->parent_port[0] &&
> -            sset_contains(local_lports, binding_rec->parent_port))) {
> -        if (binding_rec->parent_port && binding_rec->parent_port[0]) {
> -            /* Add child logical port to the set of all local ports. */
> -            sset_add(local_lports, binding_rec->logical_port);
> -        }
> -        add_local_datapath(sbrec_datapath_binding_by_key,
> -                           sbrec_port_binding_by_datapath,
> -                           sbrec_port_binding_by_name,
> -                           binding_rec->datapath, false, local_datapaths);
> -        if (iface_rec && qos_map && ovs_idl_txn) {
> -            get_qos_params(binding_rec, qos_map);
> -        }
> -    } else if (!strcmp(binding_rec->type, "l2gateway")) {
> -        if (our_chassis) {
> -            sset_add(local_lports, binding_rec->logical_port);
> -            add_local_datapath(sbrec_datapath_binding_by_key,
> -                               sbrec_port_binding_by_datapath,
> -                               sbrec_port_binding_by_name,
> -                               binding_rec->datapath, false,
> local_datapaths);
> -        }
> -    } else if (!strcmp(binding_rec->type, "chassisredirect")) {
> -        if (ha_chassis_group_contains(binding_rec->ha_chassis_group,
> -                                      chassis_rec)) {
> -            add_local_datapath(sbrec_datapath_binding_by_key,
> -                               sbrec_port_binding_by_datapath,
> -                               sbrec_port_binding_by_name,
> -                               binding_rec->datapath, false,
> local_datapaths);
> -        }
> -    } else if (!strcmp(binding_rec->type, "l3gateway")) {
> -        if (our_chassis) {
> -            add_local_datapath(sbrec_datapath_binding_by_key,
> -                               sbrec_port_binding_by_datapath,
> -                               sbrec_port_binding_by_name,
> -                               binding_rec->datapath, true,
> local_datapaths);
> -        }
> -    } else if (!strcmp(binding_rec->type, "localnet")) {
> -        /* Add all localnet ports to local_lports so that we allocate ct
> zones
> -         * for them. */
> -        sset_add(local_lports, binding_rec->logical_port);
> -    } else if (!strcmp(binding_rec->type, "external")) {
> -        if (ha_chassis_group_contains(binding_rec->ha_chassis_group,
> -                                      chassis_rec)) {
> -            add_local_datapath(sbrec_datapath_binding_by_key,
> -                               sbrec_port_binding_by_datapath,
> -                               sbrec_port_binding_by_name,
> -                               binding_rec->datapath, false,
> local_datapaths);
> -        }
> -    }
> -
> -    if (our_chassis
> -        || !strcmp(binding_rec->type, "patch")
> -        || !strcmp(binding_rec->type, "localport")
> -        || !strcmp(binding_rec->type, "vtep")
> -        || !strcmp(binding_rec->type, "localnet")) {
> -        update_local_lport_ids(local_lport_ids, binding_rec);
> -    }
> -
> -    ovs_assert(ovnsb_idl_txn);
> -    if (ovnsb_idl_txn) {
> -        const char *vif_chassis = smap_get(&binding_rec->options,
> -                                           "requested-chassis");
> -        bool can_bind = !vif_chassis || !vif_chassis[0]
> -                        || !strcmp(vif_chassis, chassis_rec->name)
> -                        || !strcmp(vif_chassis, chassis_rec->hostname);
> -
> -        if (can_bind && our_chassis) {
> -            if (binding_rec->chassis != chassis_rec) {
> -                if (binding_rec->chassis) {
> -                    VLOG_INFO("Changing chassis for lport %s from %s to
> %s.",
> -                              binding_rec->logical_port,
> -                              binding_rec->chassis->name,
> -                              chassis_rec->name);
> -                } else {
> -                    VLOG_INFO("Claiming lport %s for this chassis.",
> -                              binding_rec->logical_port);
> -                }
> -                for (int i = 0; i < binding_rec->n_mac; i++) {
> -                    VLOG_INFO("%s: Claiming %s",
> -                              binding_rec->logical_port,
> binding_rec->mac[i]);
> -                }
> -                sbrec_port_binding_set_chassis(binding_rec, chassis_rec);
> -            }
> -            /* Check if the port encap binding, if any, has changed */
> -            struct sbrec_encap *encap_rec = sbrec_get_port_encap(
> -                                            chassis_rec, iface_rec);
> -            if (encap_rec && binding_rec->encap != encap_rec) {
> -                sbrec_port_binding_set_encap(binding_rec, encap_rec);
> -            }
> -        } else if (binding_rec->chassis == chassis_rec) {
> -            VLOG_INFO("Releasing lport %s from this chassis.",
> -                      binding_rec->logical_port);
> -            if (binding_rec->encap)
> -                sbrec_port_binding_set_encap(binding_rec, NULL);
> -            sbrec_port_binding_set_chassis(binding_rec, NULL);
> -        } else if (our_chassis) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -            VLOG_INFO_RL(&rl,
> -                         "Not claiming lport %s, chassis %s "
> -                         "requested-chassis %s",
> -                         binding_rec->logical_port,
> -                         chassis_rec->name,
> -                         vif_chassis);
> -        }
> -    }
> -}
> -
> -static void
> -consider_localnet_port(const struct sbrec_port_binding *binding_rec,
> -                       struct hmap *local_datapaths)
> -{
> -    struct local_datapath *ld
> -        = get_local_datapath(local_datapaths,
> -                             binding_rec->datapath->tunnel_key);
> -    if (!ld) {
> -        return;
> -    }
> -
> -    if (ld->localnet_port && strcmp(ld->localnet_port->logical_port,
> -                                    binding_rec->logical_port)) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -        VLOG_WARN_RL(&rl, "localnet port '%s' already set for datapath "
> -                     "'%"PRId64"', skipping the new port '%s'.",
> -                     ld->localnet_port->logical_port,
> -                     binding_rec->datapath->tunnel_key,
> -                     binding_rec->logical_port);
> -        return;
> -    }
> -    ld->localnet_port = binding_rec;
> -}
> -
> -void
> -binding_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -            struct ovsdb_idl_txn *ovs_idl_txn,
> -            struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> -            struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> -            struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -            const struct ovsrec_port_table *port_table,
> -            const struct ovsrec_qos_table *qos_table,
> -            const struct sbrec_port_binding_table *port_binding_table,
> -            const struct ovsrec_bridge *br_int,
> -            const struct sbrec_chassis *chassis_rec,
> -            const struct sset *active_tunnels,
> -            struct hmap *local_datapaths, struct sset *local_lports,
> -            struct sset *local_lport_ids)
> -{
> -    if (!chassis_rec) {
> -        return;
> -    }
> -
> -    const struct sbrec_port_binding *binding_rec;
> -    struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
> -    struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces);
> -    struct hmap qos_map;
> -
> -    hmap_init(&qos_map);
> -    if (br_int) {
> -        get_local_iface_ids(br_int, &lport_to_iface, local_lports,
> -                            &egress_ifaces);
> -    }
> -
> -    /* Run through each binding record to see if it is resident on this
> -     * chassis and update the binding accordingly.  This includes both
> -     * directly connected logical ports and children of those ports. */
> -    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
> -        consider_local_datapath(ovnsb_idl_txn, ovs_idl_txn,
> -                                sbrec_datapath_binding_by_key,
> -                                sbrec_port_binding_by_datapath,
> -                                sbrec_port_binding_by_name,
> -                                active_tunnels, chassis_rec, binding_rec,
> -                                sset_is_empty(&egress_ifaces) ? NULL :
> -                                &qos_map, local_datapaths,
> &lport_to_iface,
> -                                local_lports, local_lport_ids);
> -
> -    }
> -
> -    /* Run through each binding record to see if it is a localnet port
> -     * on local datapaths discovered from above loop, and update the
> -     * corresponding local datapath accordingly. */
> -    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
> -        if (!strcmp(binding_rec->type, "localnet")) {
> -            consider_localnet_port(binding_rec, local_datapaths);
> -        }
> -    }
> -
> -    if (!sset_is_empty(&egress_ifaces)
> -        && set_noop_qos(ovs_idl_txn, port_table, qos_table,
> &egress_ifaces)) {
> -        const char *entry;
> -        SSET_FOR_EACH (entry, &egress_ifaces) {
> -            setup_qos(entry, &qos_map);
> -        }
> -    }
> -
> -    shash_destroy(&lport_to_iface);
> -    sset_destroy(&egress_ifaces);
> -    hmap_destroy(&qos_map);
> -}
> -
> -/* Returns true if port-binding changes potentially require flow changes
> on
> - * the current chassis. Returns false if we are sure there is no impact.
> */
> -bool
> -binding_evaluate_port_binding_changes(
> -        const struct sbrec_port_binding_table *pb_table,
> -        const struct ovsrec_bridge *br_int,
> -        const struct sbrec_chassis *chassis_rec,
> -        struct sset *active_tunnels,
> -        struct sset *local_lports)
> -{
> -    if (!chassis_rec) {
> -        return true;
> -    }
> -
> -    bool changed = false;
> -
> -    const struct sbrec_port_binding *binding_rec;
> -    struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
> -    struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces);
> -    if (br_int) {
> -        get_local_iface_ids(br_int, &lport_to_iface, local_lports,
> -                            &egress_ifaces);
> -    }
> -    SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (binding_rec, pb_table) {
> -        /* XXX: currently OVSDB change tracking doesn't support getting
> old
> -         * data when the operation is update, so if a port-binding moved
> from
> -         * this chassis to another, there is no easy way to find out the
> -         * change. To workaround this problem, we just makes sure if
> -         * any port *related to* this chassis has any change, then trigger
> -         * recompute.
> -         *
> -         * - If a regular VIF is unbound from this chassis, the local
> ovsdb
> -         *   interface table will be updated, which will trigger
> recompute.
> -         *
> -         * - If the port is not a regular VIF, always trigger recompute.
> */
> -        if (binding_rec->chassis == chassis_rec
> -            || is_our_chassis(chassis_rec, binding_rec,
> -                              active_tunnels, &lport_to_iface,
> local_lports)
> -            || strcmp(binding_rec->type, "")) {
> -            changed = true;
> -            break;
> -        }
> -    }
> -
> -    shash_destroy(&lport_to_iface);
> -    sset_destroy(&egress_ifaces);
> -    return changed;
> -}
> -
> -/* Returns true if the database is all cleaned up, false if more work is
> - * required. */
> -bool
> -binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                const struct sbrec_port_binding_table *port_binding_table,
> -                const struct sbrec_chassis *chassis_rec)
> -{
> -    if (!ovnsb_idl_txn) {
> -        return false;
> -    }
> -    if (!chassis_rec) {
> -        return true;
> -    }
> -
> -    const struct sbrec_port_binding *binding_rec;
> -    bool any_changes = false;
> -    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
> -        if (binding_rec->chassis == chassis_rec) {
> -            if (binding_rec->encap)
> -                sbrec_port_binding_set_encap(binding_rec, NULL);
> -            sbrec_port_binding_set_chassis(binding_rec, NULL);
> -            any_changes = true;
> -        }
> -    }
> -
> -    if (any_changes) {
> -        ovsdb_idl_txn_add_comment(
> -            ovnsb_idl_txn,
> -            "ovn-controller: removing all port bindings for '%s'",
> -            chassis_rec->name);
> -    }
> -
> -    return !any_changes;
> -}
> diff --git a/ovn/controller/binding.h b/ovn/controller/binding.h
> deleted file mode 100644
> index 8d9492630..000000000
> --- a/ovn/controller/binding.h
> +++ /dev/null
> @@ -1,57 +0,0 @@
> -/* Copyright (c) 2015, 2016 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.
> - */
> -
> -
> -#ifndef OVN_BINDING_H
> -#define OVN_BINDING_H 1
> -
> -#include <stdbool.h>
> -
> -struct hmap;
> -struct ovsdb_idl;
> -struct ovsdb_idl_index;
> -struct ovsdb_idl_txn;
> -struct ovsrec_bridge;
> -struct ovsrec_port_table;
> -struct ovsrec_qos_table;
> -struct sbrec_chassis;
> -struct sbrec_port_binding_table;
> -struct sset;
> -
> -void binding_register_ovs_idl(struct ovsdb_idl *);
> -void binding_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                 struct ovsdb_idl_txn *ovs_idl_txn,
> -                 struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> -                 struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> -                 struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                 const struct ovsrec_port_table *,
> -                 const struct ovsrec_qos_table *,
> -                 const struct sbrec_port_binding_table *,
> -                 const struct ovsrec_bridge *br_int,
> -                 const struct sbrec_chassis *,
> -                 const struct sset *active_tunnels,
> -                 struct hmap *local_datapaths,
> -                 struct sset *local_lports, struct sset *local_lport_ids);
> -bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                     const struct sbrec_port_binding_table *,
> -                     const struct sbrec_chassis *);
> -bool binding_evaluate_port_binding_changes(
> -        const struct sbrec_port_binding_table *,
> -        const struct ovsrec_bridge *br_int,
> -        const struct sbrec_chassis *,
> -        struct sset *active_tunnels,
> -        struct sset *local_lports);
> -
> -#endif /* ovn/binding.h */
> diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
> deleted file mode 100644
> index 04b98d86c..000000000
> --- a/ovn/controller/chassis.c
> +++ /dev/null
> @@ -1,671 +0,0 @@
> -/* Copyright (c) 2015, 2016 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 <unistd.h>
> -
> -#include "chassis.h"
> -
> -#include "lib/smap.h"
> -#include "lib/sset.h"
> -#include "lib/vswitch-idl.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "openvswitch/vlog.h"
> -#include "openvswitch/ofp-parse.h"
> -#include "ovn/lib/chassis-index.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn-controller.h"
> -#include "lib/util.h"
> -
> -VLOG_DEFINE_THIS_MODULE(chassis);
> -
> -#ifndef HOST_NAME_MAX
> -/* For windows. */
> -#define HOST_NAME_MAX 255
> -#endif /* HOST_NAME_MAX */
> -
> -/*
> - * Structure to hold chassis specific state (currently just chassis-id)
> - * to avoid database lookups when changes happen while the controller is
> - * running.
> - */
> -struct chassis_info {
> -    /* Last ID we initialized the Chassis SB record with. */
> -    struct ds id;
> -
> -    /* True if Chassis SB record is initialized, false otherwise. */
> -    uint32_t id_inited : 1;
> -};
> -
> -static struct chassis_info chassis_state = {
> -    .id = DS_EMPTY_INITIALIZER,
> -    .id_inited = false,
> -};
> -
> -static void
> -chassis_info_set_id(struct chassis_info *info, const char *id)
> -{
> -    ds_clear(&info->id);
> -    ds_put_cstr(&info->id, id);
> -    info->id_inited = true;
> -}
> -
> -static bool
> -chassis_info_id_inited(const struct chassis_info *info)
> -{
> -    return info->id_inited;
> -}
> -
> -static const char *
> -chassis_info_id(const struct chassis_info *info)
> -{
> -    return ds_cstr_ro(&info->id);
> -}
> -
> -/*
> - * Structure for storing the chassis config parsed from the ovs table.
> - */
> -struct ovs_chassis_cfg {
> -    /* Single string fields parsed from external-ids. */
> -    const char *hostname;
> -    const char *bridge_mappings;
> -    const char *datapath_type;
> -    const char *encap_csum;
> -    const char *cms_options;
> -    const char *chassis_macs;
> -
> -    /* Set of encap types parsed from the 'ovn-encap-type' external-id. */
> -    struct sset encap_type_set;
> -    /* Set of encap IPs parsed from the 'ovn-encap-type' external-id. */
> -    struct sset encap_ip_set;
> -    /* Interface type list formatted in the OVN-SB Chassis required
> format. */
> -    struct ds iface_types;
> -};
> -
> -static void
> -ovs_chassis_cfg_init(struct ovs_chassis_cfg *cfg)
> -{
> -    sset_init(&cfg->encap_type_set);
> -    sset_init(&cfg->encap_ip_set);
> -    ds_init(&cfg->iface_types);
> -}
> -
> -static void
> -ovs_chassis_cfg_destroy(struct ovs_chassis_cfg *cfg)
> -{
> -    sset_destroy(&cfg->encap_type_set);
> -    sset_destroy(&cfg->encap_ip_set);
> -    ds_destroy(&cfg->iface_types);
> -}
> -
> -void
> -chassis_register_ovs_idl(struct ovsdb_idl *ovs_idl)
> -{
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_iface_types);
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_datapath_type);
> -}
> -
> -static const char *
> -get_hostname(const struct smap *ext_ids)
> -{
> -    const char *hostname = smap_get_def(ext_ids, "hostname", "");
> -
> -    if (strlen(hostname) == 0) {
> -        static char hostname_[HOST_NAME_MAX + 1];
> -
> -        if (gethostname(hostname_, sizeof(hostname_))) {
> -            hostname_[0] = 0;
> -        }
> -
> -        return &hostname_[0];
> -    }
> -
> -    return hostname;
> -}
> -
> -static const char *
> -get_bridge_mappings(const struct smap *ext_ids)
> -{
> -    return smap_get_def(ext_ids, "ovn-bridge-mappings", "");
> -}
> -
> -static const char *
> -get_chassis_mac_mappings(const struct smap *ext_ids)
> -{
> -    return smap_get_def(ext_ids, "ovn-chassis-mac-mappings", "");
> -}
> -
> -static const char *
> -get_cms_options(const struct smap *ext_ids)
> -{
> -    return smap_get_def(ext_ids, "ovn-cms-options", "");
> -}
> -
> -static const char *
> -get_encap_csum(const struct smap *ext_ids)
> -{
> -    return smap_get_def(ext_ids, "ovn-encap-csum", "true");
> -}
> -
> -static const char *
> -get_datapath_type(const struct ovsrec_bridge *br_int)
> -{
> -    if (br_int && br_int->datapath_type) {
> -        return br_int->datapath_type;
> -    }
> -
> -    return "";
> -}
> -
> -static void
> -update_chassis_transport_zones(const struct sset *transport_zones,
> -                               const struct sbrec_chassis *chassis_rec)
> -{
> -    struct sset chassis_tzones_set =
> SSET_INITIALIZER(&chassis_tzones_set);
> -    for (int i = 0; i < chassis_rec->n_transport_zones; i++) {
> -        sset_add(&chassis_tzones_set, chassis_rec->transport_zones[i]);
> -    }
> -
> -    /* Only update the transport zones if something changed */
> -    if (!sset_equals(transport_zones, &chassis_tzones_set)) {
> -        const char **ls_arr = sset_array(transport_zones);
> -        sbrec_chassis_set_transport_zones(chassis_rec, ls_arr,
> -                                          sset_count(transport_zones));
> -        free(ls_arr);
> -    }
> -
> -    sset_destroy(&chassis_tzones_set);
> -}
> -
> -/*
> - * Parse an ovs 'encap_type' string and stores the resulting types in the
> - * 'encap_type_set' string set.
> - */
> -static bool
> -chassis_parse_ovs_encap_type(const char *encap_type,
> -                             struct sset *encap_type_set)
> -{
> -    sset_from_delimited_string(encap_type_set, encap_type, ",");
> -
> -    const char *type;
> -
> -    SSET_FOR_EACH (type, encap_type_set) {
> -        if (!get_tunnel_type(type)) {
> -            VLOG_INFO("Unknown tunnel type: %s", type);
> -        }
> -    }
> -
> -    return true;
> -}
> -
> -/*
> - * Parse an ovs 'encap_ip' string and stores the resulting IP
> representations
> - * in the 'encap_ip_set' string set.
> - */
> -static bool
> -chassis_parse_ovs_encap_ip(const char *encap_ip, struct sset
> *encap_ip_set)
> -{
> -    sset_from_delimited_string(encap_ip_set, encap_ip, ",");
> -    return true;
> -}
> -
> -/*
> - * Parse the ovs 'iface_types' and store them in the format required by
> the
> - * Chassis record.
> - */
> -static bool
> -chassis_parse_ovs_iface_types(char **iface_types, size_t n_iface_types,
> -                              struct ds *iface_types_str)
> -{
> -    for (size_t i = 0; i < n_iface_types; i++) {
> -        ds_put_format(iface_types_str, "%s,", iface_types[i]);
> -    }
> -    ds_chomp(iface_types_str, ',');
> -    return true;
> -}
> -
> -/*
> - * Parse the 'ovs_table' entry and populate 'ovs_cfg'.
> - */
> -static bool
> -chassis_parse_ovs_config(const struct ovsrec_open_vswitch_table
> *ovs_table,
> -                         const struct ovsrec_bridge *br_int,
> -                         struct ovs_chassis_cfg *ovs_cfg)
> -{
> -    const struct ovsrec_open_vswitch *cfg =
> -        ovsrec_open_vswitch_table_first(ovs_table);
> -
> -    if (!cfg) {
> -        VLOG_INFO("No Open_vSwitch row defined.");
> -        return false;
> -    }
> -
> -    const char *encap_type = smap_get(&cfg->external_ids,
> "ovn-encap-type");
> -    const char *encap_ips = smap_get(&cfg->external_ids, "ovn-encap-ip");
> -    if (!encap_type || !encap_ips) {
> -        VLOG_INFO("Need to specify an encap type and ip");
> -        return false;
> -    }
> -
> -    ovs_cfg->hostname = get_hostname(&cfg->external_ids);
> -    ovs_cfg->bridge_mappings = get_bridge_mappings(&cfg->external_ids);
> -    ovs_cfg->datapath_type = get_datapath_type(br_int);
> -    ovs_cfg->encap_csum = get_encap_csum(&cfg->external_ids);
> -    ovs_cfg->cms_options = get_cms_options(&cfg->external_ids);
> -    ovs_cfg->chassis_macs = get_chassis_mac_mappings(&cfg->external_ids);
> -
> -    if (!chassis_parse_ovs_encap_type(encap_type,
> &ovs_cfg->encap_type_set)) {
> -        return false;
> -    }
> -
> -    if (!chassis_parse_ovs_encap_ip(encap_ips, &ovs_cfg->encap_ip_set)) {
> -        sset_destroy(&ovs_cfg->encap_type_set);
> -        return false;
> -    }
> -
> -    if (!chassis_parse_ovs_iface_types(cfg->iface_types,
> -                                       cfg->n_iface_types,
> -                                       &ovs_cfg->iface_types)) {
> -        sset_destroy(&ovs_cfg->encap_type_set);
> -        sset_destroy(&ovs_cfg->encap_ip_set);
> -    }
> -
> -    return true;
> -}
> -
> -static void
> -chassis_build_external_ids(struct smap *ext_ids, const char
> *bridge_mappings,
> -                           const char *datapath_type, const char
> *cms_options,
> -                           const char *chassis_macs, const char
> *iface_types)
> -{
> -    smap_replace(ext_ids, "ovn-bridge-mappings", bridge_mappings);
> -    smap_replace(ext_ids, "datapath-type", datapath_type);
> -    smap_replace(ext_ids, "ovn-cms-options", cms_options);
> -    smap_replace(ext_ids, "iface-types", iface_types);
> -    smap_replace(ext_ids, "ovn-chassis-mac-mappings", chassis_macs);
> -}
> -
> -/*
> - * Returns true if any external-id doesn't match the values in
> 'chassis-rec'.
> - */
> -static bool
> -chassis_external_ids_changed(const char *bridge_mappings,
> -                             const char *datapath_type,
> -                             const char *cms_options,
> -                             const char *chassis_macs,
> -                             const struct ds *iface_types,
> -                             const struct sbrec_chassis *chassis_rec)
> -{
> -    const char *chassis_bridge_mappings =
> -        get_bridge_mappings(&chassis_rec->external_ids);
> -
> -    if (strcmp(bridge_mappings, chassis_bridge_mappings)) {
> -        return true;
> -    }
> -
> -    const char *chassis_datapath_type =
> -        smap_get_def(&chassis_rec->external_ids, "datapath-type", "");
> -
> -    if (strcmp(datapath_type, chassis_datapath_type)) {
> -        return true;
> -    }
> -
> -    const char *chassis_cms_options =
> -        get_cms_options(&chassis_rec->external_ids);
> -
> -    if (strcmp(cms_options, chassis_cms_options)) {
> -        return true;
> -    }
> -
> -    const char *chassis_mac_mappings =
> -        get_chassis_mac_mappings(&chassis_rec->external_ids);
> -    if (strcmp(chassis_macs, chassis_mac_mappings)) {
> -        return true;
> -    }
> -
> -    const char *chassis_iface_types =
> -        smap_get_def(&chassis_rec->external_ids, "iface-types", "");
> -
> -    if (strcmp(ds_cstr_ro(iface_types), chassis_iface_types)) {
> -        return true;
> -    }
> -
> -    return false;
> -}
> -
> -/*
> - * Returns true if the tunnel config obtained by combining
> 'encap_type_set'
> - * with 'encap_ip_set' and 'encap_csum' doesn't match the values in
> - * 'chassis-rec'.
> - */
> -static bool
> -chassis_tunnels_changed(const struct sset *encap_type_set,
> -                        const struct sset *encap_ip_set,
> -                        const char *encap_csum,
> -                        const struct sbrec_chassis *chassis_rec)
> -{
> -    size_t encap_type_count = 0;
> -
> -    for (int i = 0; i < chassis_rec->n_encaps; i++) {
> -        if (strcmp(chassis_rec->name,
> chassis_rec->encaps[i]->chassis_name)) {
> -            return true;
> -        }
> -
> -        if (!sset_contains(encap_type_set, chassis_rec->encaps[i]->type))
> {
> -            return true;
> -        }
> -        encap_type_count++;
> -
> -        if (!sset_contains(encap_ip_set, chassis_rec->encaps[i]->ip)) {
> -            return true;
> -        }
> -
> -        if (strcmp(smap_get_def(&chassis_rec->encaps[i]->options, "csum",
> ""),
> -                   encap_csum)) {
> -            return true;
> -        }
> -    }
> -
> -    size_t tunnel_count =
> -        sset_count(encap_type_set) * sset_count(encap_ip_set);
> -
> -    if (tunnel_count != chassis_rec->n_encaps) {
> -        return true;
> -    }
> -
> -    if (sset_count(encap_type_set) != encap_type_count) {
> -        return true;
> -    }
> -
> -    return false;
> -}
> -
> -/*
> - * Build the new encaps config (full mesh of 'encap_type_set' and
> - * 'encap_ip_set'). Allocates and stores the new 'n_encap' Encap records
> in
> - * 'encaps'.
> - */
> -static struct sbrec_encap **
> -chassis_build_encaps(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                     const struct sset *encap_type_set,
> -                     const struct sset *encap_ip_set,
> -                     const char *chassis_id,
> -                     const char *encap_csum,
> -                     size_t *n_encap)
> -{
> -    size_t tunnel_count = 0;
> -
> -    struct sbrec_encap **encaps =
> -        xmalloc(sset_count(encap_type_set) * sset_count(encap_ip_set) *
> -                sizeof(*encaps));
> -    const struct smap options = SMAP_CONST1(&options, "csum", encap_csum);
> -
> -    const char *encap_ip;
> -    const char *encap_type;
> -
> -    SSET_FOR_EACH (encap_ip, encap_ip_set) {
> -        SSET_FOR_EACH (encap_type, encap_type_set) {
> -            struct sbrec_encap *encap = sbrec_encap_insert(ovnsb_idl_txn);
> -
> -            sbrec_encap_set_type(encap, encap_type);
> -            sbrec_encap_set_ip(encap, encap_ip);
> -            sbrec_encap_set_options(encap, &options);
> -            sbrec_encap_set_chassis_name(encap, chassis_id);
> -
> -            encaps[tunnel_count] = encap;
> -            tunnel_count++;
> -        }
> -    }
> -
> -    *n_encap = tunnel_count;
> -    return encaps;
> -}
> -
> -/*
> - * Returns a pointer to a chassis record from 'chassis_table' that
> - * matches at least one tunnel config.
> - */
> -static const struct sbrec_chassis *
> -chassis_get_stale_record(const struct sbrec_chassis_table *chassis_table,
> -                         const struct ovs_chassis_cfg *ovs_cfg,
> -                         const char *chassis_id)
> -{
> -    const struct sbrec_chassis *chassis_rec;
> -
> -    SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) {
> -        for (size_t i = 0; i < chassis_rec->n_encaps; i++) {
> -            if (sset_contains(&ovs_cfg->encap_type_set,
> -                              chassis_rec->encaps[i]->type) &&
> -                    sset_contains(&ovs_cfg->encap_ip_set,
> -                                  chassis_rec->encaps[i]->ip)) {
> -                return chassis_rec;
> -            }
> -            if (strcmp(chassis_rec->name, chassis_id) == 0) {
> -                return chassis_rec;
> -            }
> -        }
> -    }
> -
> -    return NULL;
> -}
> -
> -/* If this is a chassis config update after we initialized the record once
> - * then we should always be able to find it with the ID we saved in
> - * chassis_state.
> - * Otherwise (i.e., first time we create the record) then we check if
> there's
> - * a stale record from a previous controller run that didn't end
> gracefully
> - * and reuse it. If not then we create a new record.
> - */
> -static const struct sbrec_chassis *
> -chassis_get_record(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                   struct ovsdb_idl_index *sbrec_chassis_by_name,
> -                   const struct sbrec_chassis_table *chassis_table,
> -                   const struct ovs_chassis_cfg *ovs_cfg,
> -                   const char *chassis_id)
> -{
> -    const struct sbrec_chassis *chassis_rec;
> -
> -    if (chassis_info_id_inited(&chassis_state)) {
> -        chassis_rec = chassis_lookup_by_name(sbrec_chassis_by_name,
> -
>  chassis_info_id(&chassis_state));
> -        if (!chassis_rec) {
> -            VLOG_WARN("Could not find Chassis : stored (%s) ovs (%s)",
> -                      chassis_info_id(&chassis_state), chassis_id);
> -        }
> -    } else {
> -        chassis_rec =
> -            chassis_get_stale_record(chassis_table, ovs_cfg, chassis_id);
> -
> -        if (!chassis_rec && ovnsb_idl_txn) {
> -            chassis_rec = sbrec_chassis_insert(ovnsb_idl_txn);
> -        }
> -    }
> -    return chassis_rec;
> -}
> -
> -/* Update a Chassis record based on the config in the ovs config. */
> -static void
> -chassis_update(const struct sbrec_chassis *chassis_rec,
> -               struct ovsdb_idl_txn *ovnsb_idl_txn,
> -               const struct ovs_chassis_cfg *ovs_cfg,
> -               const char *chassis_id,
> -               const struct sset *transport_zones)
> -{
> -    if (strcmp(chassis_id, chassis_rec->name)) {
> -        sbrec_chassis_set_name(chassis_rec, chassis_id);
> -    }
> -
> -    if (strcmp(ovs_cfg->hostname, chassis_rec->hostname)) {
> -        sbrec_chassis_set_hostname(chassis_rec, ovs_cfg->hostname);
> -    }
> -
> -    if (chassis_external_ids_changed(ovs_cfg->bridge_mappings,
> -                                     ovs_cfg->datapath_type,
> -                                     ovs_cfg->cms_options,
> -                                     ovs_cfg->chassis_macs,
> -                                     &ovs_cfg->iface_types,
> -                                     chassis_rec)) {
> -        struct smap ext_ids;
> -
> -        smap_clone(&ext_ids, &chassis_rec->external_ids);
> -        chassis_build_external_ids(&ext_ids, ovs_cfg->bridge_mappings,
> -                                   ovs_cfg->datapath_type,
> -                                   ovs_cfg->cms_options,
> -                                   ovs_cfg->chassis_macs,
> -                                   ds_cstr_ro(&ovs_cfg->iface_types));
> -        sbrec_chassis_verify_external_ids(chassis_rec);
> -        sbrec_chassis_set_external_ids(chassis_rec, &ext_ids);
> -        smap_destroy(&ext_ids);
> -    }
> -
> -    update_chassis_transport_zones(transport_zones, chassis_rec);
> -
> -    /* If any of the encaps should change, update them. */
> -    bool tunnels_changed =
> -        chassis_tunnels_changed(&ovs_cfg->encap_type_set,
> -                                &ovs_cfg->encap_ip_set,
> ovs_cfg->encap_csum,
> -                                chassis_rec);
> -    if (!tunnels_changed) {
> -        return;
> -    }
> -
> -    struct sbrec_encap **encaps;
> -    size_t n_encap;
> -
> -    encaps =
> -        chassis_build_encaps(ovnsb_idl_txn, &ovs_cfg->encap_type_set,
> -                             &ovs_cfg->encap_ip_set, chassis_id,
> -                             ovs_cfg->encap_csum, &n_encap);
> -    sbrec_chassis_set_encaps(chassis_rec, encaps, n_encap);
> -    free(encaps);
> -}
> -
> -/* Returns this chassis's Chassis record, if it is available. */
> -const struct sbrec_chassis *
> -chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -            struct ovsdb_idl_index *sbrec_chassis_by_name,
> -            const struct ovsrec_open_vswitch_table *ovs_table,
> -            const struct sbrec_chassis_table *chassis_table,
> -            const char *chassis_id,
> -            const struct ovsrec_bridge *br_int,
> -            const struct sset *transport_zones)
> -{
> -    struct ovs_chassis_cfg ovs_cfg;
> -
> -    /* Get the chassis config from the ovs table. */
> -    ovs_chassis_cfg_init(&ovs_cfg);
> -    if (!chassis_parse_ovs_config(ovs_table, br_int, &ovs_cfg)) {
> -        return NULL;
> -    }
> -
> -    const struct sbrec_chassis *chassis_rec =
> -        chassis_get_record(ovnsb_idl_txn, sbrec_chassis_by_name,
> -                           chassis_table, &ovs_cfg, chassis_id);
> -
> -    /* If we found (or created) a record, update it with the correct
> config
> -     * and store the current chassis_id for fast lookup in case it gets
> -     * modified in the ovs table.
> -     */
> -    if (chassis_rec && ovnsb_idl_txn) {
> -        chassis_update(chassis_rec, ovnsb_idl_txn, &ovs_cfg, chassis_id,
> -                       transport_zones);
> -        chassis_info_set_id(&chassis_state, chassis_id);
> -        ovsdb_idl_txn_add_comment(ovnsb_idl_txn,
> -                                  "ovn-controller: registering chassis
> '%s'",
> -                                  chassis_id);
> -    }
> -
> -    ovs_chassis_cfg_destroy(&ovs_cfg);
> -    return chassis_rec;
> -}
> -
> -bool
> -chassis_get_mac(const struct sbrec_chassis *chassis_rec,
> -                const char *bridge_mapping,
> -                struct eth_addr *chassis_mac)
> -{
> -    const char *tokens
> -        = get_chassis_mac_mappings(&chassis_rec->external_ids);
> -    if (!tokens[0]) {
> -       return false;
> -    }
> -
> -    char *save_ptr = NULL;
> -    bool ret = false;
> -    char *tokstr = xstrdup(tokens);
> -
> -    /* Format for a chassis mac configuration is:
> -     * ovn-chassis-mac-mappings="bridge-name1:MAC1,bridge-name2:MAC2"
> -     */
> -    for (char *token = strtok_r(tokstr, ",", &save_ptr);
> -         token != NULL;
> -         token = strtok_r(NULL, ",", &save_ptr)) {
> -        char *save_ptr2 = NULL;
> -        char *chassis_mac_bridge = strtok_r(token, ":", &save_ptr2);
> -        char *chassis_mac_str = strtok_r(NULL, "", &save_ptr2);
> -
> -        if (!strcmp(chassis_mac_bridge, bridge_mapping)) {
> -            struct eth_addr temp_mac;
> -
> -            /* Return the first chassis mac. */
> -            char *err_str = str_to_mac(chassis_mac_str, &temp_mac);
> -            if (err_str) {
> -                free(err_str);
> -                continue;
> -            }
> -
> -            ret = true;
> -            *chassis_mac = temp_mac;
> -            break;
> -        }
> -    }
> -
> -    free(tokstr);
> -    return ret;
> -}
> -
> -/* Returns true if the database is all cleaned up, false if more work is
> - * required. */
> -bool
> -chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                const struct sbrec_chassis *chassis_rec)
> -{
> -    if (!chassis_rec) {
> -        return true;
> -    }
> -    if (ovnsb_idl_txn) {
> -        ovsdb_idl_txn_add_comment(ovnsb_idl_txn,
> -                                  "ovn-controller: unregistering chassis
> '%s'",
> -                                  chassis_rec->name);
> -        sbrec_chassis_delete(chassis_rec);
> -    }
> -    return false;
> -}
> -
> -/*
> - * Returns the last initialized chassis-id.
> - */
> -const char *
> -chassis_get_id(void)
> -{
> -    if (chassis_info_id_inited(&chassis_state)) {
> -        return chassis_info_id(&chassis_state);
> -    }
> -
> -    return NULL;
> -}
> diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h
> deleted file mode 100644
> index 16a131a3b..000000000
> --- a/ovn/controller/chassis.h
> +++ /dev/null
> @@ -1,46 +0,0 @@
> -/* Copyright (c) 2015, 2016 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.
> - */
> -
> -#ifndef OVN_CHASSIS_H
> -#define OVN_CHASSIS_H 1
> -
> -#include <stdbool.h>
> -
> -struct ovsdb_idl;
> -struct ovsdb_idl_index;
> -struct ovsdb_idl_txn;
> -struct ovsrec_bridge;
> -struct ovsrec_open_vswitch_table;
> -struct sbrec_chassis;
> -struct sbrec_chassis_table;
> -struct sset;
> -struct eth_addr;
> -
> -void chassis_register_ovs_idl(struct ovsdb_idl *);
> -const struct sbrec_chassis *chassis_run(
> -    struct ovsdb_idl_txn *ovnsb_idl_txn,
> -    struct ovsdb_idl_index *sbrec_chassis_by_name,
> -    const struct ovsrec_open_vswitch_table *,
> -    const struct sbrec_chassis_table *,
> -    const char *chassis_id, const struct ovsrec_bridge *br_int,
> -    const struct sset *transport_zones);
> -bool chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                     const struct sbrec_chassis *);
> -bool chassis_get_mac(const struct sbrec_chassis *chassis,
> -                     const char *bridge_mapping,
> -                     struct eth_addr *chassis_mac);
> -const char *chassis_get_id(void);
> -
> -#endif /* ovn/chassis.h */
> diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c
> deleted file mode 100644
> index d4a436df3..000000000
> --- a/ovn/controller/encaps.c
> +++ /dev/null
> @@ -1,409 +0,0 @@
> -/* Copyright (c) 2015, 2016 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 "encaps.h"
> -
> -#include "lib/hash.h"
> -#include "lib/sset.h"
> -#include "lib/util.h"
> -#include "lib/vswitch-idl.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn-controller.h"
> -
> -VLOG_DEFINE_THIS_MODULE(encaps);
> -
> -/*
> - * Given there could be multiple tunnels with different IPs to the same
> - * chassis we annotate the ovn-chassis-id with
> - * <chassis_name>OVN_MVTEP_CHASSISID_DELIM<IP>.
> - */
> -#define        OVN_MVTEP_CHASSISID_DELIM '@'
> -
> -void
> -encaps_register_ovs_idl(struct ovsdb_idl *ovs_idl)
> -{
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
> -    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_external_ids);
> -    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_type);
> -    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options);
> -}
> -
> -/* Enough context to create a new tunnel, using tunnel_add(). */
> -struct tunnel_ctx {
> -    /* Maps from a chassis name to "struct chassis_node *". */
> -    struct shash chassis;
> -
> -    /* Names of all ports in the bridge, to allow checking uniqueness when
> -     * adding a new tunnel. */
> -    struct sset port_names;
> -
> -    struct ovsdb_idl_txn *ovs_txn;
> -    const struct ovsrec_bridge *br_int;
> -};
> -
> -struct chassis_node {
> -    const struct ovsrec_port *port;
> -    const struct ovsrec_bridge *bridge;
> -};
> -
> -static char *
> -tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id)
> -{
> -    int i;
> -
> -    for (i = 0; i < UINT16_MAX; i++) {
> -        char *port_name;
> -        port_name = xasprintf("ovn-%.6s-%x", chassis_id, i);
> -
> -        if (!sset_contains(&tc->port_names, port_name)) {
> -            return port_name;
> -        }
> -
> -        free(port_name);
> -    }
> -
> -    return NULL;
> -}
> -
> -/*
> - * Returns a tunnel-id of the form 'chassis_id'-delimiter-'encap_ip'.
> - */
> -char *
> -encaps_tunnel_id_create(const char *chassis_id, const char *encap_ip)
> -{
> -    return xasprintf("%s%c%s", chassis_id, OVN_MVTEP_CHASSISID_DELIM,
> -                     encap_ip);
> -}
> -
> -/*
> - * Parses a 'tunnel_id' of the form <chassis_name><delimiter><IP>.
> - * If the 'chassis_id' argument is not NULL the function will allocate
> memory
> - * and store the chassis-id part of the tunnel-id at '*chassis_id'.
> - * If the 'encap_ip' argument is not NULL the function will allocate
> memory
> - * and store the encapsulation IP part of the tunnel-id at '*encap_ip'.
> - */
> -bool
> -encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> -                       char **encap_ip)
> -{
> -    /* Find the delimiter.  Fail if there is no delimiter or if
> <chassis_name>
> -     * or <IP> is the empty string.*/
> -    const char *d = strchr(tunnel_id, OVN_MVTEP_CHASSISID_DELIM);
> -    if (d == tunnel_id || !d || !d[1]) {
> -        return false;
> -    }
> -
> -    if (chassis_id) {
> -        *chassis_id = xmemdup0(tunnel_id, d - tunnel_id);
> -    }
> -    if (encap_ip) {
> -        *encap_ip = xstrdup(d + 1);
> -    }
> -    return true;
> -}
> -
> -/*
> - * Returns true if 'tunnel_id' contains 'chassis_id' and, if specified,
> the
> - * given 'encap_ip'. Returns false otherwise.
> - */
> -bool
> -encaps_tunnel_id_match(const char *tunnel_id, const char *chassis_id,
> -                       const char *encap_ip)
> -{
> -    while (*tunnel_id == *chassis_id) {
> -        if (!*tunnel_id) {
> -            /* 'tunnel_id' and 'chassis_id' are equal strings.  This is a
> -             * mismatch because 'tunnel_id' is missing the delimiter and
> IP. */
> -            return false;
> -        }
> -        tunnel_id++;
> -        chassis_id++;
> -    }
> -
> -    /* We found the first byte that disagrees between 'tunnel_id' and
> -     * 'chassis_id'.  If we consumed all of 'chassis_id' and arrived at
> the
> -     * delimiter in 'tunnel_id' (and if 'encap_ip' is correct, if it was
> -     * supplied), it's a match. */
> -    return (*tunnel_id == OVN_MVTEP_CHASSISID_DELIM
> -            && *chassis_id == '\0'
> -            && (!encap_ip || !strcmp(tunnel_id + 1, encap_ip)));
> -}
> -
> -static void
> -tunnel_add(struct tunnel_ctx *tc, const struct sbrec_sb_global *sbg,
> -           const char *new_chassis_id, const struct sbrec_encap *encap)
> -{
> -    struct smap options = SMAP_INITIALIZER(&options);
> -    smap_add(&options, "remote_ip", encap->ip);
> -    smap_add(&options, "key", "flow");
> -    const char *dst_port = smap_get(&encap->options, "dst_port");
> -    const char *csum = smap_get(&encap->options, "csum");
> -    char *tunnel_entry_id = NULL;
> -
> -    /*
> -     * Since a chassis may have multiple encap-ip, we can't just add the
> -     * chassis name as as the "ovn-chassis-id" for the port; we use the
> -     * combination of the chassis_name and the encap-ip to identify
> -     * a specific tunnel to the chassis.
> -     */
> -    tunnel_entry_id = encaps_tunnel_id_create(new_chassis_id, encap->ip);
> -    if (csum && (!strcmp(csum, "true") || !strcmp(csum, "false"))) {
> -        smap_add(&options, "csum", csum);
> -    }
> -    if (dst_port) {
> -        smap_add(&options, "dst_port", dst_port);
> -    }
> -
> -    /* Add auth info if ipsec is enabled. */
> -    if (sbg->ipsec) {
> -        smap_add(&options, "remote_name", new_chassis_id);
> -    }
> -
> -    /* If there's an existing chassis record that does not need any
> change,
> -     * keep it.  Otherwise, create a new record (if there was an existing
> -     * record, the new record will supplant it and encaps_run() will
> delete
> -     * it). */
> -    struct chassis_node *chassis = shash_find_data(&tc->chassis,
> -                                                   tunnel_entry_id);
> -    if (chassis
> -        && chassis->port->n_interfaces == 1
> -        && !strcmp(chassis->port->interfaces[0]->type, encap->type)
> -        && smap_equal(&chassis->port->interfaces[0]->options, &options)) {
> -        shash_find_and_delete(&tc->chassis, tunnel_entry_id);
> -        free(chassis);
> -        goto exit;
> -    }
> -
> -    /* Choose a name for the new port.  If we're replacing an old port,
> reuse
> -     * its name, otherwise generate a new, unique name. */
> -    char *port_name = (chassis
> -                       ? xstrdup(chassis->port->name)
> -                       : tunnel_create_name(tc, new_chassis_id));
> -    if (!port_name) {
> -        VLOG_WARN("Unable to allocate unique name for '%s' tunnel",
> -                  new_chassis_id);
> -        goto exit;
> -    }
> -
> -    struct ovsrec_interface *iface = ovsrec_interface_insert(tc->ovs_txn);
> -    ovsrec_interface_set_name(iface, port_name);
> -    ovsrec_interface_set_type(iface, encap->type);
> -    ovsrec_interface_set_options(iface, &options);
> -
> -    struct ovsrec_port *port = ovsrec_port_insert(tc->ovs_txn);
> -    ovsrec_port_set_name(port, port_name);
> -    ovsrec_port_set_interfaces(port, &iface, 1);
> -    const struct smap id = SMAP_CONST1(&id, "ovn-chassis-id",
> tunnel_entry_id);
> -    ovsrec_port_set_external_ids(port, &id);
> -
> -    ovsrec_bridge_update_ports_addvalue(tc->br_int, port);
> -
> -    sset_add_and_free(&tc->port_names, port_name);
> -
> -exit:
> -    free(tunnel_entry_id);
> -    smap_destroy(&options);
> -}
> -
> -struct sbrec_encap *
> -preferred_encap(const struct sbrec_chassis *chassis_rec)
> -{
> -    struct sbrec_encap *best_encap = NULL;
> -    uint32_t best_type = 0;
> -
> -    for (int i = 0; i < chassis_rec->n_encaps; i++) {
> -        uint32_t tun_type = get_tunnel_type(chassis_rec->encaps[i]->type);
> -        if (tun_type > best_type) {
> -            best_type = tun_type;
> -            best_encap = chassis_rec->encaps[i];
> -        }
> -    }
> -
> -    return best_encap;
> -}
> -
> -/*
> - * For each peer chassis, get a preferred tunnel type and create as many
> tunnels
> - * as there are VTEP of that type (differentiated by remote_ip) on that
> chassis.
> - */
> -static int
> -chassis_tunnel_add(const struct sbrec_chassis *chassis_rec, const struct
> sbrec_sb_global *sbg, struct tunnel_ctx *tc)
> -{
> -    struct sbrec_encap *encap = preferred_encap(chassis_rec);
> -    int tuncnt = 0;
> -
> -    if (!encap) {
> -        VLOG_INFO("chassis_tunnel_add: No supported encaps for '%s'",
> chassis_rec->name);
> -        return tuncnt;
> -    }
> -
> -    uint32_t pref_type = get_tunnel_type(encap->type);
> -    for (int i = 0; i < chassis_rec->n_encaps; i++) {
> -        uint32_t tun_type = get_tunnel_type(chassis_rec->encaps[i]->type);
> -        if (tun_type != pref_type) {
> -            continue;
> -        }
> -        tunnel_add(tc, sbg, chassis_rec->name, chassis_rec->encaps[i]);
> -        tuncnt++;
> -    }
> -    return tuncnt;
> -}
> -
> -/*
> -* Returns true if transport_zones and chassis_rec->transport_zones
> -* have at least one common transport zone.
> -*/
> -static bool
> -chassis_tzones_overlap(const struct sset *transport_zones,
> -                       const struct sbrec_chassis *chassis_rec)
> -{
> -    /* If neither Chassis belongs to any transport zones, return true to
> -     * form a tunnel between them */
> -    if (!chassis_rec->n_transport_zones &&
> sset_is_empty(transport_zones)) {
> -        return true;
> -    }
> -
> -    for (int i = 0; i < chassis_rec->n_transport_zones; i++) {
> -        if (sset_contains(transport_zones,
> chassis_rec->transport_zones[i])) {
> -            return true;
> -        }
> -    }
> -    return false;
> -}
> -
> -void
> -encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
> -           const struct ovsrec_bridge_table *bridge_table,
> -           const struct ovsrec_bridge *br_int,
> -           const struct sbrec_chassis_table *chassis_table,
> -           const char *chassis_id,
> -           const struct sbrec_sb_global *sbg,
> -           const struct sset *transport_zones)
> -{
> -    if (!ovs_idl_txn || !br_int) {
> -        return;
> -    }
> -
> -    const struct sbrec_chassis *chassis_rec;
> -    const struct ovsrec_bridge *br;
> -
> -    struct tunnel_ctx tc = {
> -        .chassis = SHASH_INITIALIZER(&tc.chassis),
> -        .port_names = SSET_INITIALIZER(&tc.port_names),
> -        .br_int = br_int
> -    };
> -
> -    tc.ovs_txn = ovs_idl_txn;
> -    ovsdb_idl_txn_add_comment(tc.ovs_txn,
> -                              "ovn-controller: modifying OVS tunnels
> '%s'",
> -                              chassis_id);
> -
> -    /* Collect all port names into tc.port_names.
> -     *
> -     * Collect all the OVN-created tunnels into tc.tunnel_hmap. */
> -    OVSREC_BRIDGE_TABLE_FOR_EACH (br, bridge_table) {
> -        for (size_t i = 0; i < br->n_ports; i++) {
> -            const struct ovsrec_port *port = br->ports[i];
> -            sset_add(&tc.port_names, port->name);
> -
> -            /*
> -             * note that the id here is not just the chassis name, but the
> -             * combination of <chassis_name><delim><encap_ip>
> -             */
> -            const char *id = smap_get(&port->external_ids,
> "ovn-chassis-id");
> -            if (id) {
> -                if (!shash_find(&tc.chassis, id)) {
> -                    struct chassis_node *chassis = xzalloc(sizeof
> *chassis);
> -                    chassis->bridge = br;
> -                    chassis->port = port;
> -                    shash_add_assert(&tc.chassis, id, chassis);
> -                } else {
> -                    /* Duplicate port for ovn-chassis-id.  Arbitrarily
> choose
> -                     * to delete this one. */
> -                    ovsrec_bridge_update_ports_delvalue(br, port);
> -                }
> -            }
> -        }
> -    }
> -
> -    SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) {
> -        if (strcmp(chassis_rec->name, chassis_id)) {
> -            /* Create tunnels to the other Chassis belonging to the
> -             * same transport zone */
> -            if (!chassis_tzones_overlap(transport_zones, chassis_rec)) {
> -                VLOG_DBG("Skipping encap creation for Chassis '%s'
> because "
> -                         "it belongs to different transport zones",
> -                         chassis_rec->name);
> -                continue;
> -            }
> -
> -            if (chassis_tunnel_add(chassis_rec, sbg, &tc) == 0) {
> -                VLOG_INFO("Creating encap for '%s' failed",
> chassis_rec->name);
> -                continue;
> -            }
> -        }
> -    }
> -
> -    /* Delete any existing OVN tunnels that were not still around. */
> -    struct shash_node *node, *next_node;
> -    SHASH_FOR_EACH_SAFE (node, next_node, &tc.chassis) {
> -        struct chassis_node *chassis = node->data;
> -        ovsrec_bridge_update_ports_delvalue(chassis->bridge,
> chassis->port);
> -        shash_delete(&tc.chassis, node);
> -        free(chassis);
> -    }
> -    shash_destroy(&tc.chassis);
> -    sset_destroy(&tc.port_names);
> -}
> -
> -/* Returns true if the database is all cleaned up, false if more work is
> - * required. */
> -bool
> -encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn,
> -               const struct ovsrec_bridge *br_int)
> -{
> -    if (!br_int) {
> -        return true;
> -    }
> -
> -    /* Delete all the OVS-created tunnels from the integration bridge. */
> -    struct ovsrec_port **ports
> -        = xmalloc(sizeof *br_int->ports * br_int->n_ports);
> -    size_t n = 0;
> -    for (size_t i = 0; i < br_int->n_ports; i++) {
> -        if (!smap_get(&br_int->ports[i]->external_ids, "ovn-chassis-id"))
> {
> -            ports[n++] = br_int->ports[i];
> -        }
> -    }
> -
> -    bool any_changes = n != br_int->n_ports;
> -    if (any_changes && ovs_idl_txn) {
> -        ovsdb_idl_txn_add_comment(ovs_idl_txn,
> -                                  "ovn-controller: destroying tunnels");
> -        ovsrec_bridge_verify_ports(br_int);
> -        ovsrec_bridge_set_ports(br_int, ports, n);
> -    }
> -    free(ports);
> -
> -    return !any_changes;
> -}
> diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h
> deleted file mode 100644
> index afa41830a..000000000
> --- a/ovn/controller/encaps.h
> +++ /dev/null
> @@ -1,48 +0,0 @@
> -/* Copyright (c) 2015 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.
> - */
> -
> -#ifndef OVN_ENCAPS_H
> -#define OVN_ENCAPS_H 1
> -
> -#include <stdbool.h>
> -
> -struct ovsdb_idl;
> -struct ovsdb_idl_txn;
> -struct ovsrec_bridge;
> -struct ovsrec_bridge_table;
> -struct sbrec_chassis_table;
> -struct sbrec_sb_global;
> -struct ovsrec_open_vswitch_table;
> -struct sset;
> -
> -void encaps_register_ovs_idl(struct ovsdb_idl *);
> -void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
> -                const struct ovsrec_bridge_table *,
> -                const struct ovsrec_bridge *br_int,
> -                const struct sbrec_chassis_table *,
> -                const char *chassis_id,
> -                const struct sbrec_sb_global *,
> -                const struct sset *transport_zones);
> -
> -bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn,
> -                    const struct ovsrec_bridge *br_int);
> -
> -char *encaps_tunnel_id_create(const char *chassis_id, const char
> *encap_ip);
> -bool  encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> -                             char **encap_ip);
> -bool  encaps_tunnel_id_match(const char *tunnel_id, const char
> *chassis_id,
> -                             const char *encap_ip);
> -
> -#endif /* ovn/encaps.h */
> diff --git a/ovn/controller/ha-chassis.c b/ovn/controller/ha-chassis.c
> deleted file mode 100644
> index 498e5ce5a..000000000
> --- a/ovn/controller/ha-chassis.c
> +++ /dev/null
> @@ -1,203 +0,0 @@
> -/* Copyright (c) 2019 Red Hat, 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 "ha-chassis.h"
> -#include "lib/sset.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -
> -VLOG_DEFINE_THIS_MODULE(ha_chassis);
> -
> -static int
> -compare_chassis_prio_(const void *a_, const void *b_)
> -{
> -    const struct sbrec_ha_chassis *ch_a = a_;
> -    const struct sbrec_ha_chassis *ch_b = b_;
> -    int prio_diff = ch_b->priority - ch_a->priority;
> -    if (!prio_diff) {
> -        return strcmp(ch_b->chassis->name, ch_a->chassis->name);
> -    }
> -    return prio_diff;
> -}
> -
> -/* Returns the ordered HA chassis list in the HA chassis group.
> - * Eg. If an HA chassis group has 3 HA chassis
> - *   - HA1 - pri 30
> - *   - HA2 - pri 40 and
> - *   - HA3 - pri 20
> - * and the ref_chassis of HA chassis group is set to - C1 and C2.
> - *
> - * If active_tunnels is NULL, then it returns the ordered list
> - *   -  (HA2, HA1, HA3)
> - *
> - * If active_tunnels is set to - (HA1, HA2, C1, C2) and
> - * local_chassis is HA3, then it returns the ordered list
> - *  - (HA2, HA1, HA3)
> - *
> - * If active_tunnels is set to - (HA1, C1, C2) and
> - * local_chassis is HA3, then it returns the ordered list
> - *  - (HA1, HA3)
> - *
> - * If active_tunnels is set to - (C1, C2) and
> - * local_chassis is HA3, then it returns the ordered list
> - *  - (HA3)
> - *
> - * If active_tunnels is set is empty and local_chassis is HA3,
> - * then it returns NULL.
> - */
> -static struct ha_chassis_ordered *
> -get_ordered_ha_chassis_list(const struct sbrec_ha_chassis_group
> *ha_ch_grp,
> -                            const struct sset *active_tunnels,
> -                            const struct sbrec_chassis *local_chassis)
> -{
> -    struct sbrec_ha_chassis *ha_ch_order =
> -        xzalloc(sizeof *ha_ch_order * ha_ch_grp->n_ha_chassis);
> -
> -    size_t n_ha_ch = 0;
> -
> -    for (size_t i = 0; i < ha_ch_grp->n_ha_chassis; i++) {
> -        if (!ha_ch_grp->ha_chassis[i]->chassis) {
> -            continue;
> -        }
> -
> -        /* Don't add it to the list for ordering if it is not active. */
> -        if (ha_ch_grp->ha_chassis[i]->chassis != local_chassis &&
> -            active_tunnels &&
> -            !sset_contains(active_tunnels,
> -                           ha_ch_grp->ha_chassis[i]->chassis->name)) {
> -            continue;
> -        }
> -
> -        ha_ch_order[n_ha_ch].chassis = ha_ch_grp->ha_chassis[i]->chassis;
> -        ha_ch_order[n_ha_ch].priority =
> ha_ch_grp->ha_chassis[i]->priority;
> -        n_ha_ch++;
> -    }
> -
> -    if (!n_ha_ch) {
> -        free(ha_ch_order);
> -        return NULL;
> -    }
> -
> -    struct ha_chassis_ordered *ordered_ha_ch;
> -    if (n_ha_ch == 1) {
> -        if (active_tunnels) {
> -            /* If n_ha_ch is 1, it means only the local chassis is in the
> -            * ha_ch_order list. Check if this local chassis has active
> -            * bfd session with any of the referenced chassis. If so,
> -            * then the local chassis can be active. Otherwise it can't.
> -            * This can happen in the following scenario.
> -            * Lets say we have chassis HA1 (prioirty 20) and HA2
> (priority 10)
> -            * in the ha_chasis_group and compute chassis C1 and C2 are in
> the
> -            * reference chassis list. If HA1 chassis has lost the link and
> -            * when this function is called for HA2 we need to consider
> -            * HA2 as active since it has active BFD sessions with C1 and
> C2.
> -            * On HA1 chassis, this function won't be called since
> -            * active_tunnels set will be empty.
> -            * */
> -            bool can_local_chassis_be_active = false;
> -            for (size_t i = 0; i < ha_ch_grp->n_ref_chassis; i++) {
> -                if (sset_contains(active_tunnels,
> -                                ha_ch_grp->ref_chassis[i]->name)) {
> -                    can_local_chassis_be_active = true;
> -                    break;
> -                }
> -            }
> -            if (!can_local_chassis_be_active) {
> -                free(ha_ch_order);
> -                return NULL;
> -            }
> -        }
> -    } else {
> -        qsort(ha_ch_order, n_ha_ch, sizeof *ha_ch_order,
> -              compare_chassis_prio_);
> -    }
> -
> -    ordered_ha_ch = xmalloc(sizeof *ordered_ha_ch);
> -    ordered_ha_ch->ha_ch = ha_ch_order;
> -    ordered_ha_ch->n_ha_ch = n_ha_ch;
> -
> -    return ordered_ha_ch;
> -}
> -
> -void
> -ha_chassis_destroy_ordered(struct ha_chassis_ordered *ordered_ha_ch)
> -{
> -    if (ordered_ha_ch) {
> -        free(ordered_ha_ch->ha_ch);
> -        free(ordered_ha_ch);
> -    }
> -}
> -
> -
> -/* Returns true if the local_chassis is the master of
> - * the HA chassis group, false otherwise. */
> -bool
> -ha_chassis_group_is_active(
> -    const struct sbrec_ha_chassis_group *ha_ch_grp,
> -    const struct sset *active_tunnels,
> -    const struct sbrec_chassis *local_chassis)
> -{
> -    if (!ha_ch_grp || !ha_ch_grp->n_ha_chassis) {
> -        return false;
> -    }
> -
> -    if (ha_ch_grp->n_ha_chassis == 1) {
> -        return (ha_ch_grp->ha_chassis[0]->chassis == local_chassis);
> -    }
> -
> -    if (sset_is_empty(active_tunnels)) {
> -        /* If active tunnel sset is empty, it means it has lost
> -         * connectivity with other chassis. */
> -        return false;
> -    }
> -
> -    struct ha_chassis_ordered *ordered_ha_ch =
> -        get_ordered_ha_chassis_list(ha_ch_grp, active_tunnels,
> local_chassis);
> -    if (!ordered_ha_ch) {
> -        return false;
> -    }
> -
> -    struct sbrec_chassis *active_ch = ordered_ha_ch->ha_ch[0].chassis;
> -    ha_chassis_destroy_ordered(ordered_ha_ch);
> -
> -    return (active_ch == local_chassis);
> -}
> -
> -bool
> -ha_chassis_group_contains(
> -    const struct sbrec_ha_chassis_group *ha_chassis_grp,
> -    const struct sbrec_chassis *chassis)
> -{
> -    if (ha_chassis_grp && chassis) {
> -        for (size_t i = 0; i < ha_chassis_grp->n_ha_chassis; i++) {
> -            if (ha_chassis_grp->ha_chassis[i]->chassis == chassis) {
> -                return true;
> -            }
> -        }
> -    }
> -    return false;
> -}
> -
> -struct ha_chassis_ordered *
> -ha_chassis_get_ordered(const struct sbrec_ha_chassis_group
> *ha_chassis_grp)
> -{
> -    if (!ha_chassis_grp || !ha_chassis_grp->n_ha_chassis) {
> -        return NULL;
> -    }
> -
> -    return get_ordered_ha_chassis_list(ha_chassis_grp, NULL, NULL);
> -}
> diff --git a/ovn/controller/ha-chassis.h b/ovn/controller/ha-chassis.h
> deleted file mode 100644
> index 3768c2a5c..000000000
> --- a/ovn/controller/ha-chassis.h
> +++ /dev/null
> @@ -1,50 +0,0 @@
> -/* Copyright (c) 2019 Red Hat, 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.
> - */
> -
> -#ifndef OVN_HA_CHASSIS_H
> -#define OVN_HA_CHASSIS_H 1
> -
> -#include <stdint.h>
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/list.h"
> -
> -struct sbrec_chassis;
> -struct sbrec_ha_chassis_group;
> -struct sset;
> -
> -struct ha_chassis_ordered {
> -    struct sbrec_ha_chassis *ha_ch;
> -    size_t n_ha_ch;
> -};
> -
> -/* Returns true if the local chassis is the active gateway among a set
> - * of gateway_chassis.  Return false if the local chassis is currently a
> - * backup in a set of multiple gateway_chassis. */
> -bool ha_chassis_group_is_active(
> -    const struct sbrec_ha_chassis_group *ha_chassis_grp,
> -    const struct sset *active_tunnels,
> -    const struct sbrec_chassis *local_chassis);
> -
> -bool ha_chassis_group_contains(
> -    const struct sbrec_ha_chassis_group *ha_chassis_grp,
> -    const struct sbrec_chassis *chassis);
> -
> -struct ha_chassis_ordered *ha_chassis_get_ordered(
> -    const struct sbrec_ha_chassis_group *ha_chassis_grp);
> -
> -void ha_chassis_destroy_ordered(
> -    struct ha_chassis_ordered *ordered_ha_ch);
> -
> -#endif /* OVN_HA_CHASSIS_H */
> diff --git a/ovn/controller/ip-mcast.c b/ovn/controller/ip-mcast.c
> deleted file mode 100644
> index ef36be2ca..000000000
> --- a/ovn/controller/ip-mcast.c
> +++ /dev/null
> @@ -1,164 +0,0 @@
> -/* Copyright (c) 2019, Red Hat, 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 "ip-mcast.h"
> -#include "lport.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -
> -/*
> - * Used for (faster) updating of IGMP_Group ports.
> - */
> -struct igmp_group_port {
> -    struct hmap_node hmap_node;
> -    const struct sbrec_port_binding *port;
> -};
> -
> -struct ovsdb_idl_index *
> -igmp_group_index_create(struct ovsdb_idl *idl)
> -{
> -    const struct ovsdb_idl_index_column cols[] = {
> -        { .column = &sbrec_igmp_group_col_address },
> -        { .column = &sbrec_igmp_group_col_datapath },
> -        { .column = &sbrec_igmp_group_col_chassis },
> -    };
> -
> -    return ovsdb_idl_index_create(idl, cols, ARRAY_SIZE(cols));
> -}
> -
> -/* Looks up an IGMP group based on an IPv4 (mapped in IPv6) or IPv6
> 'address'
> - * and 'datapath'.
> - */
> -const struct sbrec_igmp_group *
> -igmp_group_lookup(struct ovsdb_idl_index *igmp_groups,
> -                  const struct in6_addr *address,
> -                  const struct sbrec_datapath_binding *datapath,
> -                  const struct sbrec_chassis *chassis)
> -{
> -    char addr_str[INET6_ADDRSTRLEN];
> -
> -    if (!ipv6_string_mapped(addr_str, address)) {
> -        return NULL;
> -    }
> -
> -    struct sbrec_igmp_group *target =
> -        sbrec_igmp_group_index_init_row(igmp_groups);
> -
> -    sbrec_igmp_group_index_set_address(target, addr_str);
> -    sbrec_igmp_group_index_set_datapath(target, datapath);
> -    sbrec_igmp_group_index_set_chassis(target, chassis);
> -
> -    const struct sbrec_igmp_group *g =
> -        sbrec_igmp_group_index_find(igmp_groups, target);
> -    sbrec_igmp_group_index_destroy_row(target);
> -    return g;
> -}
> -
> -/* Creates and returns a new IGMP group based on an IPv4 (mapped in IPv6)
> or
> - * IPv6 'address', 'datapath' and 'chassis'.
> - */
> -struct sbrec_igmp_group *
> -igmp_group_create(struct ovsdb_idl_txn *idl_txn,
> -                  const struct in6_addr *address,
> -                  const struct sbrec_datapath_binding *datapath,
> -                  const struct sbrec_chassis *chassis)
> -{
> -    char addr_str[INET6_ADDRSTRLEN];
> -
> -    if (!ipv6_string_mapped(addr_str, address)) {
> -        return NULL;
> -    }
> -
> -    struct sbrec_igmp_group *g = sbrec_igmp_group_insert(idl_txn);
> -
> -    sbrec_igmp_group_set_address(g, addr_str);
> -    sbrec_igmp_group_set_datapath(g, datapath);
> -    sbrec_igmp_group_set_chassis(g, chassis);
> -
> -    return g;
> -}
> -
> -void
> -igmp_group_update_ports(const struct sbrec_igmp_group *g,
> -                        struct ovsdb_idl_index *datapaths,
> -                        struct ovsdb_idl_index *port_bindings,
> -                        const struct mcast_snooping *ms OVS_UNUSED,
> -                        const struct mcast_group *mc_group)
> -    OVS_REQ_RDLOCK(ms->rwlock)
> -{
> -    struct igmp_group_port *old_ports_storage =
> -        (g->n_ports ? xmalloc(g->n_ports * sizeof *old_ports_storage) :
> NULL);
> -
> -    struct hmap old_ports = HMAP_INITIALIZER(&old_ports);
> -
> -    for (size_t i = 0; i < g->n_ports; i++) {
> -        struct igmp_group_port *old_port = &old_ports_storage[i];
> -
> -        old_port->port = g->ports[i];
> -        hmap_insert(&old_ports, &old_port->hmap_node,
> -                    old_port->port->tunnel_key);
> -    }
> -
> -    struct mcast_group_bundle *bundle;
> -    uint64_t dp_key = g->datapath->tunnel_key;
> -
> -    LIST_FOR_EACH (bundle, bundle_node, &mc_group->bundle_lru) {
> -        uint32_t port_key = (uintptr_t)bundle->port;
> -        const struct sbrec_port_binding *sbrec_port =
> -            lport_lookup_by_key(datapaths, port_bindings, dp_key,
> port_key);
> -        if (!sbrec_port) {
> -            continue;
> -        }
> -
> -        struct hmap_node *node = hmap_first_with_hash(&old_ports,
> port_key);
> -        if (!node) {
> -            sbrec_igmp_group_update_ports_addvalue(g, sbrec_port);
> -        } else {
> -            hmap_remove(&old_ports, node);
> -        }
> -    }
> -
> -    struct igmp_group_port *igmp_port;
> -    HMAP_FOR_EACH_POP (igmp_port, hmap_node, &old_ports) {
> -        sbrec_igmp_group_update_ports_delvalue(g, igmp_port->port);
> -    }
> -
> -    free(old_ports_storage);
> -    hmap_destroy(&old_ports);
> -}
> -
> -void
> -igmp_group_delete(const struct sbrec_igmp_group *g)
> -{
> -    sbrec_igmp_group_delete(g);
> -}
> -
> -bool
> -igmp_group_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                   struct ovsdb_idl_index *igmp_groups)
> -{
> -    const struct sbrec_igmp_group *g;
> -
> -    if (!ovnsb_idl_txn) {
> -        return true;
> -    }
> -
> -    SBREC_IGMP_GROUP_FOR_EACH_BYINDEX (g, igmp_groups) {
> -        igmp_group_delete(g);
> -    }
> -
> -    return true;
> -}
> diff --git a/ovn/controller/ip-mcast.h b/ovn/controller/ip-mcast.h
> deleted file mode 100644
> index 6014f43d5..000000000
> --- a/ovn/controller/ip-mcast.h
> +++ /dev/null
> @@ -1,52 +0,0 @@
> -/* Copyright (c) 2019, Red Hat, 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.
> - */
> -
> -#ifndef OVN_IP_MCAST_H
> -#define OVN_IP_MCAST_H 1
> -
> -#include "mcast-snooping.h"
> -
> -struct ovsdb_idl;
> -struct ovsdb_idl_txn;
> -
> -struct sbrec_chassis;
> -struct sbrec_datapath_binding;
> -
> -struct ovsdb_idl_index *igmp_group_index_create(struct ovsdb_idl *);
> -const struct sbrec_igmp_group *igmp_group_lookup(
> -    struct ovsdb_idl_index *igmp_groups,
> -    const struct in6_addr *address,
> -    const struct sbrec_datapath_binding *datapath,
> -    const struct sbrec_chassis *chassis);
> -
> -struct sbrec_igmp_group *igmp_group_create(
> -    struct ovsdb_idl_txn *idl_txn,
> -    const struct in6_addr *address,
> -    const struct sbrec_datapath_binding *datapath,
> -    const struct sbrec_chassis *chassis);
> -
> -void igmp_group_update_ports(const struct sbrec_igmp_group *g,
> -                             struct ovsdb_idl_index *datapaths,
> -                             struct ovsdb_idl_index *port_bindings,
> -                             const struct mcast_snooping *ms,
> -                             const struct mcast_group *mc_group)
> -    OVS_REQ_RDLOCK(ms->rwlock);
> -
> -void igmp_group_delete(const struct sbrec_igmp_group *g);
> -
> -bool igmp_group_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> -                        struct ovsdb_idl_index *igmp_groups);
> -
> -#endif /* ovn/controller/ip-mcast.h */
> diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
> deleted file mode 100644
> index 1aafafb33..000000000
> --- a/ovn/controller/lflow.c
> +++ /dev/null
> @@ -1,898 +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 "lflow.h"
> -#include "coverage.h"
> -#include "ha-chassis.h"
> -#include "lport.h"
> -#include "ofctrl.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "openvswitch/ofp-actions.h"
> -#include "openvswitch/ofpbuf.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn-controller.h"
> -#include "ovn/actions.h"
> -#include "ovn/expr.h"
> -#include "ovn/lib/ovn-l7.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -#include "ovn/lib/extend-table.h"
> -#include "packets.h"
> -#include "physical.h"
> -#include "simap.h"
> -#include "sset.h"
> -
> -VLOG_DEFINE_THIS_MODULE(lflow);
> -
> -COVERAGE_DEFINE(lflow_run);
> -
> -/* Symbol table. */
> -
> -/* Contains "struct expr_symbol"s for fields supported by OVN lflows. */
> -static struct shash symtab;
> -
> -void
> -lflow_init(void)
> -{
> -    ovn_init_symtab(&symtab);
> -}
> -
> -struct lookup_port_aux {
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath;
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name;
> -    const struct sbrec_datapath_binding *dp;
> -};
> -
> -struct condition_aux {
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name;
> -    const struct sbrec_chassis *chassis;
> -    const struct sset *active_tunnels;
> -};
> -
> -static bool consider_logical_flow(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_logical_flow *,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *,
> -    struct hmap *dhcp_opts,
> -    struct hmap *dhcpv6_opts,
> -    struct hmap *nd_ra_opts,
> -    struct controller_event_options *controller_event_opts,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *lfrr,
> -    uint32_t *conj_id_ofs);
> -
> -static bool
> -lookup_port_cb(const void *aux_, const char *port_name, unsigned int
> *portp)
> -{
> -    const struct lookup_port_aux *aux = aux_;
> -
> -    const struct sbrec_port_binding *pb
> -        = lport_lookup_by_name(aux->sbrec_port_binding_by_name,
> port_name);
> -    if (pb && pb->datapath == aux->dp) {
> -        *portp = pb->tunnel_key;
> -        return true;
> -    }
> -
> -    const struct sbrec_multicast_group *mg = mcgroup_lookup_by_dp_name(
> -        aux->sbrec_multicast_group_by_name_datapath, aux->dp, port_name);
> -    if (mg) {
> -        *portp = mg->tunnel_key;
> -        return true;
> -    }
> -
> -    return false;
> -}
> -
> -static bool
> -is_chassis_resident_cb(const void *c_aux_, const char *port_name)
> -{
> -    const struct condition_aux *c_aux = c_aux_;
> -
> -    const struct sbrec_port_binding *pb
> -        = lport_lookup_by_name(c_aux->sbrec_port_binding_by_name,
> port_name);
> -    if (!pb) {
> -        return false;
> -    }
> -    if (strcmp(pb->type, "chassisredirect")) {
> -        /* for non-chassisredirect ports */
> -        return pb->chassis && pb->chassis == c_aux->chassis;
> -    } else {
> -        if (ha_chassis_group_contains(pb->ha_chassis_group,
> -                                      c_aux->chassis)) {
> -            bool active = ha_chassis_group_is_active(pb->ha_chassis_group,
> -
>  c_aux->active_tunnels,
> -                                                     c_aux->chassis);
> -            return active;
> -        }
> -        return false;
> -    }
> -}
> -
> -static bool
> -is_switch(const struct sbrec_datapath_binding *ldp)
> -{
> -    return smap_get(&ldp->external_ids, "logical-switch") != NULL;
> -
> -}
> -
> -void
> -lflow_resource_init(struct lflow_resource_ref *lfrr)
> -{
> -    hmap_init(&lfrr->ref_lflow_table);
> -    hmap_init(&lfrr->lflow_ref_table);
> -}
> -
> -void
> -lflow_resource_destroy(struct lflow_resource_ref *lfrr)
> -{
> -    struct ref_lflow_node *rlfn, *rlfn_next;
> -    HMAP_FOR_EACH_SAFE (rlfn, rlfn_next, node, &lfrr->ref_lflow_table) {
> -        free(rlfn->ref_name);
> -        struct lflow_ref_list_node *lrln, *next;
> -        LIST_FOR_EACH_SAFE (lrln, next, ref_list, &rlfn->ref_lflow_head) {
> -            ovs_list_remove(&lrln->ref_list);
> -            ovs_list_remove(&lrln->lflow_list);
> -            free(lrln);
> -        }
> -        hmap_remove(&lfrr->ref_lflow_table, &rlfn->node);
> -        free(rlfn);
> -    }
> -    hmap_destroy(&lfrr->ref_lflow_table);
> -
> -    struct lflow_ref_node *lfrn, *lfrn_next;
> -    HMAP_FOR_EACH_SAFE (lfrn, lfrn_next, node, &lfrr->lflow_ref_table) {
> -        hmap_remove(&lfrr->lflow_ref_table, &lfrn->node);
> -        free(lfrn);
> -    }
> -    hmap_destroy(&lfrr->lflow_ref_table);
> -}
> -
> -void
> -lflow_resource_clear(struct lflow_resource_ref *lfrr)
> -{
> -    lflow_resource_destroy(lfrr);
> -    lflow_resource_init(lfrr);
> -}
> -
> -static struct ref_lflow_node*
> -ref_lflow_lookup(struct hmap *ref_lflow_table,
> -                 enum ref_type type, const char *ref_name)
> -{
> -    struct ref_lflow_node *rlfn;
> -
> -    HMAP_FOR_EACH_WITH_HASH (rlfn, node, hash_string(ref_name, type),
> -                             ref_lflow_table) {
> -        if (rlfn->type == type && !strcmp(rlfn->ref_name, ref_name)) {
> -            return rlfn;
> -        }
> -    }
> -    return NULL;
> -}
> -
> -static struct lflow_ref_node*
> -lflow_ref_lookup(struct hmap *lflow_ref_table,
> -                 const struct uuid *lflow_uuid)
> -{
> -    struct lflow_ref_node *lfrn;
> -
> -    HMAP_FOR_EACH_WITH_HASH (lfrn, node, uuid_hash(lflow_uuid),
> -                             lflow_ref_table) {
> -        if (uuid_equals(&lfrn->lflow_uuid, lflow_uuid)) {
> -            return lfrn;
> -        }
> -    }
> -    return NULL;
> -}
> -
> -static void
> -lflow_resource_add(struct lflow_resource_ref *lfrr, enum ref_type type,
> -                   const char *ref_name, const struct uuid *lflow_uuid)
> -{
> -    struct ref_lflow_node *rlfn = ref_lflow_lookup(&lfrr->ref_lflow_table,
> -                                                   type, ref_name);
> -    if (!rlfn) {
> -        rlfn = xzalloc(sizeof *rlfn);
> -        rlfn->node.hash = hash_string(ref_name, type);
> -        rlfn->type = type;
> -        rlfn->ref_name = xstrdup(ref_name);
> -        ovs_list_init(&rlfn->ref_lflow_head);
> -        hmap_insert(&lfrr->ref_lflow_table, &rlfn->node, rlfn->node.hash);
> -    }
> -
> -    struct lflow_ref_node *lfrn = lflow_ref_lookup(&lfrr->lflow_ref_table,
> -                                                   lflow_uuid);
> -    if (!lfrn) {
> -        lfrn = xzalloc(sizeof *lfrn);
> -        lfrn->node.hash = uuid_hash(lflow_uuid);
> -        lfrn->lflow_uuid = *lflow_uuid;
> -        ovs_list_init(&lfrn->lflow_ref_head);
> -        hmap_insert(&lfrr->lflow_ref_table, &lfrn->node, lfrn->node.hash);
> -    }
> -
> -    struct lflow_ref_list_node *lrln = xzalloc(sizeof *lrln);
> -    lrln->type = type;
> -    lrln->ref_name = xstrdup(ref_name);
> -    lrln->lflow_uuid = *lflow_uuid;
> -    ovs_list_push_back(&rlfn->ref_lflow_head, &lrln->ref_list);
> -    ovs_list_push_back(&lfrn->lflow_ref_head, &lrln->lflow_list);
> -}
> -
> -static void
> -lflow_resource_destroy_lflow(struct lflow_resource_ref *lfrr,
> -                            const struct uuid *lflow_uuid)
> -{
> -    struct lflow_ref_node *lfrn = lflow_ref_lookup(&lfrr->lflow_ref_table,
> -                                                   lflow_uuid);
> -    if (!lfrn) {
> -        return;
> -    }
> -
> -    hmap_remove(&lfrr->lflow_ref_table, &lfrn->node);
> -    struct lflow_ref_list_node *lrln, *next;
> -    LIST_FOR_EACH_SAFE (lrln, next, lflow_list, &lfrn->lflow_ref_head) {
> -        ovs_list_remove(&lrln->ref_list);
> -        ovs_list_remove(&lrln->lflow_list);
> -        free(lrln);
> -    }
> -    free(lfrn);
> -}
> -
> -/* Adds the logical flows from the Logical_Flow table to flow tables. */
> -static void
> -add_logical_flows(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_dhcp_options_table *dhcp_options_table,
> -    const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
> -    const struct sbrec_logical_flow_table *logical_flow_table,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *chassis,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *flow_table,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *lfrr,
> -    uint32_t *conj_id_ofs)
> -{
> -    const struct sbrec_logical_flow *lflow;
> -
> -    struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts);
> -    struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts);
> -    const struct sbrec_dhcp_options *dhcp_opt_row;
> -    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row, dhcp_options_table) {
> -        dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
> -                     dhcp_opt_row->type);
> -    }
> -
> -
> -    const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
> -    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> -                                         dhcpv6_options_table) {
> -       dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> -                    dhcpv6_opt_row->type);
> -    }
> -
> -    struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
> -    nd_ra_opts_init(&nd_ra_opts);
> -
> -    struct controller_event_options controller_event_opts;
> -    controller_event_opts_init(&controller_event_opts);
> -
> -    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow, logical_flow_table) {
> -        if (!consider_logical_flow(sbrec_multicast_group_by_name_datapath,
> -                                   sbrec_port_binding_by_name,
> -                                   lflow, local_datapaths,
> -                                   chassis, &dhcp_opts, &dhcpv6_opts,
> -                                   &nd_ra_opts, &controller_event_opts,
> -                                   addr_sets, port_groups,
> -                                   active_tunnels, local_lport_ids,
> -                                   flow_table, group_table, meter_table,
> -                                   lfrr, conj_id_ofs)) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
> -            VLOG_ERR_RL(&rl, "Conjunction id overflow when processing
> lflow "
> -                        UUID_FMT, UUID_ARGS(&lflow->header_.uuid));
> -        }
> -    }
> -
> -    dhcp_opts_destroy(&dhcp_opts);
> -    dhcp_opts_destroy(&dhcpv6_opts);
> -    nd_ra_opts_destroy(&nd_ra_opts);
> -    controller_event_opts_destroy(&controller_event_opts);
> -}
> -
> -bool
> -lflow_handle_changed_flows(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_dhcp_options_table *dhcp_options_table,
> -    const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
> -    const struct sbrec_logical_flow_table *logical_flow_table,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *chassis,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *flow_table,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *lfrr,
> -    uint32_t *conj_id_ofs)
> -{
> -    bool ret = true;
> -    const struct sbrec_logical_flow *lflow;
> -
> -    struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts);
> -    struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts);
> -    const struct sbrec_dhcp_options *dhcp_opt_row;
> -    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row, dhcp_options_table) {
> -        dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
> -                     dhcp_opt_row->type);
> -    }
> -
> -
> -    const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
> -    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> -                                         dhcpv6_options_table) {
> -       dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> -                    dhcpv6_opt_row->type);
> -    }
> -
> -    struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
> -    nd_ra_opts_init(&nd_ra_opts);
> -
> -    /* Handle removed flows first, and then other flows, so that when
> -     * the flows being added and removed have same match conditions
> -     * can be processed in the proper order */
> -    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table)
> {
> -        /* Remove any flows that should be removed. */
> -        if (sbrec_logical_flow_is_deleted(lflow)) {
> -            VLOG_DBG("handle deleted lflow "UUID_FMT,
> -                     UUID_ARGS(&lflow->header_.uuid));
> -            ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
> -            /* Delete entries from lflow resource reference. */
> -            lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> -        }
> -    }
> -
> -    struct controller_event_options controller_event_opts;
> -    controller_event_opts_init(&controller_event_opts);
> -
> -    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table)
> {
> -        if (!sbrec_logical_flow_is_deleted(lflow)) {
> -            /* Now, add/modify existing flows. If the logical
> -             * flow is a modification, just remove the flows
> -             * for this row, and then add new flows. */
> -            if (!sbrec_logical_flow_is_new(lflow)) {
> -                VLOG_DBG("handle updated lflow "UUID_FMT,
> -                         UUID_ARGS(&lflow->header_.uuid));
> -                ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
> -                /* Delete entries from lflow resource reference. */
> -                lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> -            }
> -            VLOG_DBG("handle new lflow "UUID_FMT,
> -                     UUID_ARGS(&lflow->header_.uuid));
> -            if
> (!consider_logical_flow(sbrec_multicast_group_by_name_datapath,
> -                                       sbrec_port_binding_by_name,
> -                                       lflow, local_datapaths,
> -                                       chassis, &dhcp_opts, &dhcpv6_opts,
> -                                       &nd_ra_opts,
> &controller_event_opts,
> -                                       addr_sets, port_groups,
> -                                       active_tunnels, local_lport_ids,
> -                                       flow_table, group_table,
> meter_table,
> -                                       lfrr, conj_id_ofs)) {
> -                ret = false;
> -                break;
> -            }
> -        }
> -    }
> -    dhcp_opts_destroy(&dhcp_opts);
> -    dhcp_opts_destroy(&dhcpv6_opts);
> -    nd_ra_opts_destroy(&nd_ra_opts);
> -    controller_event_opts_destroy(&controller_event_opts);
> -    return ret;
> -}
> -
> -bool
> -lflow_handle_changed_ref(
> -    enum ref_type ref_type,
> -    const char *ref_name,
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_dhcp_options_table *dhcp_options_table,
> -    const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
> -    const struct sbrec_logical_flow_table *logical_flow_table,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *chassis,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *flow_table,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *lfrr,
> -    uint32_t *conj_id_ofs,
> -    bool *changed)
> -{
> -    struct ref_lflow_node *rlfn = ref_lflow_lookup(&lfrr->ref_lflow_table,
> -                                                   ref_type, ref_name);
> -    if (!rlfn) {
> -        *changed = false;
> -        return true;
> -    }
> -    VLOG_DBG("Handle changed lflow reference for resource type: %d,"
> -             " name: %s.", ref_type, ref_name);
> -    *changed = false;
> -    bool ret = true;
> -
> -    hmap_remove(&lfrr->ref_lflow_table, &rlfn->node);
> -
> -    struct lflow_ref_list_node *lrln, *next;
> -    /* Detach the rlfn->ref_lflow_head nodes from the lfrr table and clean
> -     * up all other nodes related to the lflows that uses the resource,
> -     * so that the old nodes won't interfere with updating the lfrr table
> -     * when reparsing the lflows. */
> -    LIST_FOR_EACH (lrln, ref_list, &rlfn->ref_lflow_head) {
> -        ovs_list_remove(&lrln->lflow_list);
> -        lflow_resource_destroy_lflow(lfrr, &lrln->lflow_uuid);
> -    }
> -
> -    struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts);
> -    struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts);
> -    const struct sbrec_dhcp_options *dhcp_opt_row;
> -    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row, dhcp_options_table) {
> -        dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
> -                     dhcp_opt_row->type);
> -    }
> -
> -    const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
> -    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH(dhcpv6_opt_row,
> dhcpv6_options_table) {
> -       dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> -                    dhcpv6_opt_row->type);
> -    }
> -
> -    struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
> -    nd_ra_opts_init(&nd_ra_opts);
> -
> -    struct controller_event_options controller_event_opts;
> -    controller_event_opts_init(&controller_event_opts);
> -
> -    /* Re-parse the related lflows. */
> -    LIST_FOR_EACH (lrln, ref_list, &rlfn->ref_lflow_head) {
> -        const struct sbrec_logical_flow *lflow =
> -            sbrec_logical_flow_table_get_for_uuid(logical_flow_table,
> -                                                  &lrln->lflow_uuid);
> -        if (!lflow) {
> -            VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d,"
> -                     " name: %s - not found.",
> -                     UUID_ARGS(&lrln->lflow_uuid),
> -                     ref_type, ref_name);
> -            continue;
> -        }
> -        VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d,"
> -                 " name: %s.",
> -                 UUID_ARGS(&lrln->lflow_uuid),
> -                 ref_type, ref_name);
> -        ofctrl_remove_flows(flow_table, &lrln->lflow_uuid);
> -
> -        if (!consider_logical_flow(sbrec_multicast_group_by_name_datapath,
> -                                   sbrec_port_binding_by_name,
> -                                   lflow, local_datapaths,
> -                                   chassis, &dhcp_opts, &dhcpv6_opts,
> -                                   &nd_ra_opts, &controller_event_opts,
> -                                   addr_sets, port_groups,
> -                                   active_tunnels, local_lport_ids,
> -                                   flow_table, group_table, meter_table,
> -                                   lfrr, conj_id_ofs)) {
> -            ret = false;
> -            break;
> -        }
> -        *changed = true;
> -    }
> -
> -    LIST_FOR_EACH_SAFE (lrln, next, ref_list, &rlfn->ref_lflow_head) {
> -        ovs_list_remove(&lrln->ref_list);
> -        free(lrln);
> -    }
> -    free(rlfn);
> -
> -    dhcp_opts_destroy(&dhcp_opts);
> -    dhcp_opts_destroy(&dhcpv6_opts);
> -    nd_ra_opts_destroy(&nd_ra_opts);
> -    controller_event_opts_destroy(&controller_event_opts);
> -    return ret;
> -}
> -
> -static bool
> -update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs)
> -{
> -    if (*conj_id_ofs + n_conjs < *conj_id_ofs) {
> -        /* overflow */
> -        return false;
> -    }
> -    *conj_id_ofs += n_conjs;
> -    return true;
> -}
> -
> -static bool
> -consider_logical_flow(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_logical_flow *lflow,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *chassis,
> -    struct hmap *dhcp_opts,
> -    struct hmap *dhcpv6_opts,
> -    struct hmap *nd_ra_opts,
> -    struct controller_event_options *controller_event_opts,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *flow_table,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *lfrr,
> -    uint32_t *conj_id_ofs)
> -{
> -    /* Determine translation of logical table IDs to physical table IDs.
> */
> -    bool ingress = !strcmp(lflow->pipeline, "ingress");
> -
> -    const struct sbrec_datapath_binding *ldp = lflow->logical_datapath;
> -    if (!ldp) {
> -        VLOG_DBG("lflow "UUID_FMT" has no datapath binding, skip",
> -                 UUID_ARGS(&lflow->header_.uuid));
> -        return true;
> -    }
> -    if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) {
> -        VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip",
> -                 UUID_ARGS(&lflow->header_.uuid));
> -        return true;
> -    }
> -
> -    /* Determine translation of logical table IDs to physical table IDs.
> */
> -    uint8_t first_ptable = (ingress
> -                            ? OFTABLE_LOG_INGRESS_PIPELINE
> -                            : OFTABLE_LOG_EGRESS_PIPELINE);
> -    uint8_t ptable = first_ptable + lflow->table_id;
> -    uint8_t output_ptable = (ingress
> -                             ? OFTABLE_REMOTE_OUTPUT
> -                             : OFTABLE_SAVE_INPORT);
> -
> -    /* Parse OVN logical actions.
> -     *
> -     * XXX Deny changes to 'outport' in egress pipeline. */
> -    uint64_t ovnacts_stub[1024 / 8];
> -    struct ofpbuf ovnacts = OFPBUF_STUB_INITIALIZER(ovnacts_stub);
> -    struct ovnact_parse_params pp = {
> -        .symtab = &symtab,
> -        .dhcp_opts = dhcp_opts,
> -        .dhcpv6_opts = dhcpv6_opts,
> -        .nd_ra_opts = nd_ra_opts,
> -        .controller_event_opts = controller_event_opts,
> -
> -        .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
> -        .n_tables = LOG_PIPELINE_LEN,
> -        .cur_ltable = lflow->table_id,
> -    };
> -    struct expr *prereqs;
> -    char *error;
> -
> -    error = ovnacts_parse_string(lflow->actions, &pp, &ovnacts, &prereqs);
> -    if (error) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> -        VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s",
> -                     lflow->actions, error);
> -        free(error);
> -        ovnacts_free(ovnacts.data, ovnacts.size);
> -        ofpbuf_uninit(&ovnacts);
> -        return true;
> -    }
> -
> -    /* Translate OVN match into table of OpenFlow matches. */
> -    struct hmap matches;
> -    struct expr *expr;
> -
> -    struct sset addr_sets_ref = SSET_INITIALIZER(&addr_sets_ref);
> -    expr = expr_parse_string(lflow->match, &symtab, addr_sets,
> port_groups,
> -                             &addr_sets_ref, &error);
> -    const char *addr_set_name;
> -    SSET_FOR_EACH (addr_set_name, &addr_sets_ref) {
> -        lflow_resource_add(lfrr, REF_TYPE_ADDRSET, addr_set_name,
> -                           &lflow->header_.uuid);
> -    }
> -    sset_destroy(&addr_sets_ref);
> -
> -    if (!error) {
> -        if (prereqs) {
> -            expr = expr_combine(EXPR_T_AND, expr, prereqs);
> -            prereqs = NULL;
> -        }
> -        expr = expr_annotate(expr, &symtab, &error);
> -    }
> -    if (error) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> -        VLOG_WARN_RL(&rl, "error parsing match \"%s\": %s",
> -                     lflow->match, error);
> -        expr_destroy(prereqs);
> -        free(error);
> -        ovnacts_free(ovnacts.data, ovnacts.size);
> -        ofpbuf_uninit(&ovnacts);
> -        return true;
> -    }
> -
> -    struct lookup_port_aux aux = {
> -        .sbrec_multicast_group_by_name_datapath
> -            = sbrec_multicast_group_by_name_datapath,
> -        .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
> -        .dp = lflow->logical_datapath
> -    };
> -    struct condition_aux cond_aux = {
> -        .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
> -        .chassis = chassis,
> -        .active_tunnels = active_tunnels,
> -    };
> -    expr = expr_simplify(expr, is_chassis_resident_cb, &cond_aux);
> -    expr = expr_normalize(expr);
> -    uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
> -                                       &matches);
> -    expr_destroy(expr);
> -
> -    if (hmap_is_empty(&matches)) {
> -        VLOG_DBG("lflow "UUID_FMT" matches are empty, skip",
> -                 UUID_ARGS(&lflow->header_.uuid));
> -        ovnacts_free(ovnacts.data, ovnacts.size);
> -        ofpbuf_uninit(&ovnacts);
> -        expr_matches_destroy(&matches);
> -        return true;
> -    }
> -
> -    /* Encode OVN logical actions into OpenFlow. */
> -    uint64_t ofpacts_stub[1024 / 8];
> -    struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
> -    struct ovnact_encode_params ep = {
> -        .lookup_port = lookup_port_cb,
> -        .aux = &aux,
> -        .is_switch = is_switch(ldp),
> -        .group_table = group_table,
> -        .meter_table = meter_table,
> -        .lflow_uuid = lflow->header_.uuid,
> -
> -        .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
> -        .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE,
> -        .egress_ptable = OFTABLE_LOG_EGRESS_PIPELINE,
> -        .output_ptable = output_ptable,
> -        .mac_bind_ptable = OFTABLE_MAC_BINDING,
> -    };
> -    ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts);
> -    ovnacts_free(ovnacts.data, ovnacts.size);
> -    ofpbuf_uninit(&ovnacts);
> -
> -    /* Prepare the OpenFlow matches for adding to the flow table. */
> -    struct expr_match *m;
> -    HMAP_FOR_EACH (m, hmap_node, &matches) {
> -        match_set_metadata(&m->match,
> -                           htonll(lflow->logical_datapath->tunnel_key));
> -        if (m->match.wc.masks.conj_id) {
> -            m->match.flow.conj_id += *conj_id_ofs;
> -        }
> -        if (is_switch(ldp)) {
> -            unsigned int reg_index
> -                = (ingress ? MFF_LOG_INPORT : MFF_LOG_OUTPORT) - MFF_REG0;
> -            int64_t port_id = m->match.flow.regs[reg_index];
> -            if (port_id) {
> -                int64_t dp_id = lflow->logical_datapath->tunnel_key;
> -                char buf[16];
> -                snprintf(buf, sizeof(buf), "%"PRId64"_%"PRId64, dp_id,
> port_id);
> -                if (!sset_contains(local_lport_ids, buf)) {
> -                    VLOG_DBG("lflow "UUID_FMT
> -                             " port %s in match is not local, skip",
> -                             UUID_ARGS(&lflow->header_.uuid),
> -                             buf);
> -                    continue;
> -                }
> -            }
> -        }
> -        if (!m->n) {
> -            ofctrl_add_flow(flow_table, ptable, lflow->priority,
> -                            lflow->header_.uuid.parts[0], &m->match,
> &ofpacts,
> -                            &lflow->header_.uuid);
> -        } else {
> -            uint64_t conj_stubs[64 / 8];
> -            struct ofpbuf conj;
> -
> -            ofpbuf_use_stub(&conj, conj_stubs, sizeof conj_stubs);
> -            for (int i = 0; i < m->n; i++) {
> -                const struct cls_conjunction *src = &m->conjunctions[i];
> -                struct ofpact_conjunction *dst;
> -
> -                dst = ofpact_put_CONJUNCTION(&conj);
> -                dst->id = src->id + *conj_id_ofs;
> -                dst->clause = src->clause;
> -                dst->n_clauses = src->n_clauses;
> -            }
> -            ofctrl_add_flow(flow_table, ptable, lflow->priority, 0,
> &m->match,
> -                            &conj, &lflow->header_.uuid);
> -            ofpbuf_uninit(&conj);
> -        }
> -    }
> -
> -    /* Clean up. */
> -    expr_matches_destroy(&matches);
> -    ofpbuf_uninit(&ofpacts);
> -    return update_conj_id_ofs(conj_id_ofs, n_conjs);
> -}
> -
> -static void
> -put_load(const uint8_t *data, size_t len,
> -         enum mf_field_id dst, int ofs, int n_bits,
> -         struct ofpbuf *ofpacts)
> -{
> -    struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts,
> -                                                       mf_from_id(dst),
> NULL,
> -                                                       NULL);
> -    bitwise_copy(data, len, 0, sf->value, sf->field->n_bytes, ofs,
> n_bits);
> -    bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, ofs,
> n_bits);
> -}
> -
> -static void
> -consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                       const struct sbrec_mac_binding *b,
> -                       struct ovn_desired_flow_table *flow_table)
> -{
> -    const struct sbrec_port_binding *pb
> -        = lport_lookup_by_name(sbrec_port_binding_by_name,
> b->logical_port);
> -    if (!pb) {
> -        return;
> -    }
> -
> -    struct eth_addr mac;
> -    if (!eth_addr_from_string(b->mac, &mac)) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -        VLOG_WARN_RL(&rl, "bad 'mac' %s", b->mac);
> -        return;
> -    }
> -
> -    struct match match = MATCH_CATCHALL_INITIALIZER;
> -    if (strchr(b->ip, '.')) {
> -        ovs_be32 ip;
> -        if (!ip_parse(b->ip, &ip)) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -            VLOG_WARN_RL(&rl, "bad 'ip' %s", b->ip);
> -            return;
> -        }
> -        match_set_reg(&match, 0, ntohl(ip));
> -    } else {
> -        struct in6_addr ip6;
> -        if (!ipv6_parse(b->ip, &ip6)) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -            VLOG_WARN_RL(&rl, "bad 'ip' %s", b->ip);
> -            return;
> -        }
> -        ovs_be128 value;
> -        memcpy(&value, &ip6, sizeof(value));
> -        match_set_xxreg(&match, 0, ntoh128(value));
> -    }
> -
> -    match_set_metadata(&match, htonll(pb->datapath->tunnel_key));
> -    match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, pb->tunnel_key);
> -
> -    uint64_t stub[1024 / 8];
> -    struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
> -    put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts);
> -    ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, 0, &match,
> &ofpacts,
> -                    &b->header_.uuid);
> -    ofpbuf_uninit(&ofpacts);
> -}
> -
> -/* Adds an OpenFlow flow to flow tables for each MAC binding in the OVN
> - * southbound database. */
> -static void
> -add_neighbor_flows(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                   const struct sbrec_mac_binding_table
> *mac_binding_table,
> -                   struct ovn_desired_flow_table *flow_table)
> -{
> -    const struct sbrec_mac_binding *b;
> -    SBREC_MAC_BINDING_TABLE_FOR_EACH (b, mac_binding_table) {
> -        consider_neighbor_flow(sbrec_port_binding_by_name, b, flow_table);
> -    }
> -}
> -
> -/* Handles neighbor changes in mac_binding table. */
> -void
> -lflow_handle_changed_neighbors(
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_mac_binding_table *mac_binding_table,
> -    struct ovn_desired_flow_table *flow_table)
> -{
> -
> -    const struct sbrec_mac_binding *mb;
> -    /* Handle deleted mac_bindings first, to avoid *duplicated flow*
> problem
> -     * when same flow needs to be added. */
> -    SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (mb, mac_binding_table) {
> -        /* Remove any flows that should be removed. */
> -        if (sbrec_mac_binding_is_deleted(mb)) {
> -            VLOG_DBG("handle deleted mac_binding "UUID_FMT,
> -                     UUID_ARGS(&mb->header_.uuid));
> -            ofctrl_remove_flows(flow_table, &mb->header_.uuid);
> -        }
> -    }
> -    SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (mb, mac_binding_table) {
> -        if (!sbrec_mac_binding_is_deleted(mb)) {
> -            if (!sbrec_mac_binding_is_new(mb)) {
> -                VLOG_DBG("handle updated mac_binding "UUID_FMT,
> -                         UUID_ARGS(&mb->header_.uuid));
> -                ofctrl_remove_flows(flow_table, &mb->header_.uuid);
> -            }
> -            VLOG_DBG("handle new mac_binding "UUID_FMT,
> -                     UUID_ARGS(&mb->header_.uuid));
> -            consider_neighbor_flow(sbrec_port_binding_by_name, mb,
> flow_table);
> -        }
> -    }
> -}
> -
> -
> -/* Translates logical flows in the Logical_Flow table in the OVN_SB
> database
> - * into OpenFlow flows.  See ovn-architecture(7) for more information. */
> -void
> -lflow_run(struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -          struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -          const struct sbrec_dhcp_options_table *dhcp_options_table,
> -          const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
> -          const struct sbrec_logical_flow_table *logical_flow_table,
> -          const struct sbrec_mac_binding_table *mac_binding_table,
> -          const struct sbrec_chassis *chassis,
> -          const struct hmap *local_datapaths,
> -          const struct shash *addr_sets,
> -          const struct shash *port_groups,
> -          const struct sset *active_tunnels,
> -          const struct sset *local_lport_ids,
> -          struct ovn_desired_flow_table *flow_table,
> -          struct ovn_extend_table *group_table,
> -          struct ovn_extend_table *meter_table,
> -          struct lflow_resource_ref *lfrr,
> -          uint32_t *conj_id_ofs)
> -{
> -    COVERAGE_INC(lflow_run);
> -
> -    add_logical_flows(sbrec_multicast_group_by_name_datapath,
> -                      sbrec_port_binding_by_name, dhcp_options_table,
> -                      dhcpv6_options_table, logical_flow_table,
> -                      local_datapaths, chassis, addr_sets, port_groups,
> -                      active_tunnels, local_lport_ids, flow_table,
> group_table,
> -                      meter_table, lfrr, conj_id_ofs);
> -    add_neighbor_flows(sbrec_port_binding_by_name, mac_binding_table,
> -                       flow_table);
> -}
> -
> -void
> -lflow_destroy(void)
> -{
> -    expr_symtab_destroy(&symtab);
> -    shash_destroy(&symtab);
> -    ovn_destroy_ovnfields();
> -}
> diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
> deleted file mode 100644
> index 4e1086eb6..000000000
> --- a/ovn/controller/lflow.h
> +++ /dev/null
> @@ -1,184 +0,0 @@
> -/* Copyright (c) 2015, 2016 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.
> - */
> -
> -#ifndef OVN_LFLOW_H
> -#define OVN_LFLOW_H 1
> -
> -#include "ovn/logical-fields.h"
> -
> -/* Logical_Flow table translation to OpenFlow
> - * ==========================================
> - *
> - * The Logical_Flow table obtained from the OVN_Southbound database works
> in
> - * terms of logical entities, that is, logical flows among logical
> datapaths
> - * and logical ports.  This code translates these logical flows into
> OpenFlow
> - * flows that, again, work in terms of logical entities implemented
> through
> - * OpenFlow extensions (e.g. registers represent the logical input and
> output
> - * ports).
> - *
> - * Physical-to-logical and logical-to-physical translation are
> implemented in
> - * physical.[ch] as separate OpenFlow tables that run before and after,
> - * respectively, the logical pipeline OpenFlow tables.
> - */
> -
> -#include <stdint.h>
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/uuid.h"
> -#include "openvswitch/list.h"
> -
> -struct ovn_extend_table;
> -struct ovsdb_idl_index;
> -struct ovn_desired_flow_table;
> -struct hmap;
> -struct hmap_node;
> -struct sbrec_chassis;
> -struct sbrec_dhcp_options_table;
> -struct sbrec_dhcpv6_options_table;
> -struct sbrec_logical_flow_table;
> -struct sbrec_mac_binding_table;
> -struct simap;
> -struct sset;
> -struct uuid;
> -
> -/* OpenFlow table numbers.
> - *
> - * These are heavily documented in ovn-architecture(7), please update it
> if
> - * you make any changes. */
> -#define OFTABLE_PHY_TO_LOG            0
> -#define OFTABLE_LOG_INGRESS_PIPELINE  8 /* First of LOG_PIPELINE_LEN
> tables. */
> -#define OFTABLE_REMOTE_OUTPUT        32
> -#define OFTABLE_LOCAL_OUTPUT         33
> -#define OFTABLE_CHECK_LOOPBACK       34
> -#define OFTABLE_LOG_EGRESS_PIPELINE  40 /* First of LOG_PIPELINE_LEN
> tables. */
> -#define OFTABLE_SAVE_INPORT          64
> -#define OFTABLE_LOG_TO_PHY           65
> -#define OFTABLE_MAC_BINDING          66
> -
> -/* The number of tables for the ingress and egress pipelines. */
> -#define LOG_PIPELINE_LEN 24
> -
> -enum ref_type {
> -    REF_TYPE_ADDRSET,
> -    REF_TYPE_PORTGROUP
> -};
> -
> -/* Maintains the relationship for a pair of named resource and
> - * a lflow, indexed by both ref_lflow_table and lflow_ref_table. */
> -struct lflow_ref_list_node {
> -    struct ovs_list lflow_list; /* list for same lflow */
> -    struct ovs_list ref_list; /* list for same ref */
> -    enum ref_type type;
> -    char *ref_name;
> -    struct uuid lflow_uuid;
> -};
> -
> -struct ref_lflow_node {
> -    struct hmap_node node;
> -    enum ref_type type; /* key */
> -    char *ref_name; /* key */
> -    struct ovs_list ref_lflow_head;
> -};
> -
> -struct lflow_ref_node {
> -    struct hmap_node node;
> -    struct uuid lflow_uuid; /* key */
> -    struct ovs_list lflow_ref_head;
> -};
> -
> -struct lflow_resource_ref {
> -    /* A map from a referenced resource type & name (e.g. address_set AS1)
> -     * to a list of lflows that are referencing the named resource. Data
> -     * type of each node in this hmap is struct ref_lflow_node. The
> -     * ref_lflow_head in each node points to a list of
> -     * lflow_ref_list_node.ref_list. */
> -    struct hmap ref_lflow_table;
> -
> -    /* A map from a lflow uuid to a list of named resources that are
> -     * referenced by the lflow. Data type of each node in this hmap is
> -     * struct lflow_ref_node. The lflow_ref_head in each node points to
> -     * a list of lflow_ref_list_node.lflow_list. */
> -    struct hmap lflow_ref_table;
> -};
> -
> -void lflow_resource_init(struct lflow_resource_ref *);
> -void lflow_resource_destroy(struct lflow_resource_ref *);
> -void lflow_resource_clear(struct lflow_resource_ref *);
> -
> -void lflow_init(void);
> -void lflow_run(struct ovsdb_idl_index
> *sbrec_multicast_group_by_name_datapath,
> -               struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -               const struct sbrec_dhcp_options_table *,
> -               const struct sbrec_dhcpv6_options_table *,
> -               const struct sbrec_logical_flow_table *,
> -               const struct sbrec_mac_binding_table *,
> -               const struct sbrec_chassis *chassis,
> -               const struct hmap *local_datapaths,
> -               const struct shash *addr_sets,
> -               const struct shash *port_groups,
> -               const struct sset *active_tunnels,
> -               const struct sset *local_lport_ids,
> -               struct ovn_desired_flow_table *,
> -               struct ovn_extend_table *group_table,
> -               struct ovn_extend_table *meter_table,
> -               struct lflow_resource_ref *,
> -               uint32_t *conj_id_ofs);
> -
> -bool lflow_handle_changed_flows(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_dhcp_options_table *,
> -    const struct sbrec_dhcpv6_options_table *,
> -    const struct sbrec_logical_flow_table *,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *,
> -    uint32_t *conj_id_ofs);
> -
> -bool lflow_handle_changed_ref(
> -    enum ref_type,
> -    const char *ref_name,
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_dhcp_options_table *,
> -    const struct sbrec_dhcpv6_options_table *,
> -    const struct sbrec_logical_flow_table *,
> -    const struct hmap *local_datapaths,
> -    const struct sbrec_chassis *,
> -    const struct shash *addr_sets,
> -    const struct shash *port_groups,
> -    const struct sset *active_tunnels,
> -    const struct sset *local_lport_ids,
> -    struct ovn_desired_flow_table *,
> -    struct ovn_extend_table *group_table,
> -    struct ovn_extend_table *meter_table,
> -    struct lflow_resource_ref *,
> -    uint32_t *conj_id_ofs,
> -    bool *changed);
> -
> -void lflow_handle_changed_neighbors(
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const struct sbrec_mac_binding_table *,
> -    struct ovn_desired_flow_table *);
> -
> -void lflow_destroy(void);
> -
> -#endif /* ovn/lflow.h */
> diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c
> deleted file mode 100644
> index cc5c5fbb2..000000000
> --- a/ovn/controller/lport.c
> +++ /dev/null
> @@ -1,102 +0,0 @@
> -/* Copyright (c) 2015, 2016 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 "lib/sset.h"
> -#include "lport.h"
> -#include "hash.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn/lib/ovn-sb-idl.h"
> -VLOG_DEFINE_THIS_MODULE(lport);
> -
> -const struct sbrec_port_binding *
> -lport_lookup_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                     const char *name)
> -{
> -    struct sbrec_port_binding *pb = sbrec_port_binding_index_init_row(
> -        sbrec_port_binding_by_name);
> -    sbrec_port_binding_index_set_logical_port(pb, name);
> -
> -    const struct sbrec_port_binding *retval =
> sbrec_port_binding_index_find(
> -        sbrec_port_binding_by_name, pb);
> -
> -    sbrec_port_binding_index_destroy_row(pb);
> -
> -    return retval;
> -}
> -
> -const struct sbrec_port_binding *
> -lport_lookup_by_key(struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> -                    struct ovsdb_idl_index *sbrec_port_binding_by_key,
> -                    uint64_t dp_key, uint64_t port_key)
> -{
> -    /* Lookup datapath corresponding to dp_key. */
> -    const struct sbrec_datapath_binding *db = datapath_lookup_by_key(
> -        sbrec_datapath_binding_by_key, dp_key);
> -    if (!db) {
> -        return NULL;
> -    }
> -
> -    /* Build key for an indexed lookup. */
> -    struct sbrec_port_binding *pb = sbrec_port_binding_index_init_row(
> -        sbrec_port_binding_by_key);
> -    sbrec_port_binding_index_set_datapath(pb, db);
> -    sbrec_port_binding_index_set_tunnel_key(pb, port_key);
> -
> -    const struct sbrec_port_binding *retval =
> sbrec_port_binding_index_find(
> -        sbrec_port_binding_by_key, pb);
> -
> -    sbrec_port_binding_index_destroy_row(pb);
> -
> -    return retval;
> -}
> -
> -const struct sbrec_datapath_binding *
> -datapath_lookup_by_key(struct ovsdb_idl_index
> *sbrec_datapath_binding_by_key,
> -                       uint64_t dp_key)
> -{
> -    struct sbrec_datapath_binding *db =
> sbrec_datapath_binding_index_init_row(
> -        sbrec_datapath_binding_by_key);
> -    sbrec_datapath_binding_index_set_tunnel_key(db, dp_key);
> -
> -    const struct sbrec_datapath_binding *retval
> -        = sbrec_datapath_binding_index_find(sbrec_datapath_binding_by_key,
> -                                            db);
> -
> -    sbrec_datapath_binding_index_destroy_row(db);
> -
> -    return retval;
> -}
> -
> -const struct sbrec_multicast_group *
> -mcgroup_lookup_by_dp_name(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    const struct sbrec_datapath_binding *db, const char *name)
> -{
> -    /* Build key for an indexed lookup. */
> -    struct sbrec_multicast_group *mc =
> sbrec_multicast_group_index_init_row(
> -        sbrec_multicast_group_by_name_datapath);
> -    sbrec_multicast_group_index_set_name(mc, name);
> -    sbrec_multicast_group_index_set_datapath(mc, db);
> -
> -    const struct sbrec_multicast_group *retval
> -        = sbrec_multicast_group_index_find(
> -            sbrec_multicast_group_by_name_datapath, mc);
> -
> -    sbrec_multicast_group_index_destroy_row(mc);
> -
> -    return retval;
> -}
> diff --git a/ovn/controller/lport.h b/ovn/controller/lport.h
> deleted file mode 100644
> index 7dcd5bee0..000000000
> --- a/ovn/controller/lport.h
> +++ /dev/null
> @@ -1,52 +0,0 @@
> -/* Copyright (c) 2015, 2016 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.
> - */
> -
> -#ifndef OVN_LPORT_H
> -#define OVN_LPORT_H 1
> -
> -#include <stdint.h>
> -
> -struct ovsdb_idl_index;
> -struct sbrec_chassis;
> -struct sbrec_datapath_binding;
> -struct sbrec_multicast_group;
> -struct sbrec_port_binding;
> -
> -
> -/* Database indexes.
> - * =================
> - *
> - * If the database IDL were a little smarter, it would allow us to
> directly
> - * look up data based on values of its fields.  It's not that smart
> (yet), so
> - * instead we define our own indexes.
> - */
> -
> -const struct sbrec_port_binding *lport_lookup_by_name(
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -    const char *name);
> -
> -const struct sbrec_port_binding *lport_lookup_by_key(
> -    struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> -    struct ovsdb_idl_index *sbrec_port_binding_by_key,
> -    uint64_t dp_key, uint64_t port_key);
> -
> -const struct sbrec_datapath_binding *datapath_lookup_by_key(
> -    struct ovsdb_idl_index *sbrec_datapath_binding_by_key, uint64_t
> dp_key);
> -
> -const struct sbrec_multicast_group *mcgroup_lookup_by_dp_name(
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
> -    const struct sbrec_datapath_binding *, const char *name);
> -
> -#endif /* ovn/lport.h */
> diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c
> deleted file mode 100644
> index 043abd69d..000000000
> --- a/ovn/controller/ofctrl.c
> +++ /dev/null
> @@ -1,1393 +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 "bitmap.h"
> -#include "byte-order.h"
> -#include "dirs.h"
> -#include "dp-packet.h"
> -#include "flow.h"
> -#include "hash.h"
> -#include "hindex.h"
> -#include "lflow.h"
> -#include "ofctrl.h"
> -#include "openflow/openflow.h"
> -#include "openvswitch/dynamic-string.h"
> -#include "openvswitch/hmap.h"
> -#include "openvswitch/list.h"
> -#include "openvswitch/match.h"
> -#include "openvswitch/ofp-actions.h"
> -#include "openvswitch/ofp-flow.h"
> -#include "openvswitch/ofp-group.h"
> -#include "openvswitch/ofp-match.h"
> -#include "openvswitch/ofp-msgs.h"
> -#include "openvswitch/ofp-meter.h"
> -#include "openvswitch/ofp-packet.h"
> -#include "openvswitch/ofp-print.h"
> -#include "openvswitch/ofp-util.h"
> -#include "openvswitch/ofpbuf.h"
> -#include "openvswitch/vlog.h"
> -#include "ovn-controller.h"
> -#include "ovn/actions.h"
> -#include "ovn/lib/extend-table.h"
> -#include "openvswitch/poll-loop.h"
> -#include "physical.h"
> -#include "openvswitch/rconn.h"
> -#include "socket-util.h"
> -#include "util.h"
> -#include "vswitch-idl.h"
> -
> -VLOG_DEFINE_THIS_MODULE(ofctrl);
> -
> -/* An OpenFlow flow. */
> -struct ovn_flow {
> -    struct hmap_node match_hmap_node; /* For match based hashing. */
> -    struct hindex_node uuid_hindex_node; /* For uuid based hashing. */
> -    struct ovs_list list_node; /* For handling lists of flows. */
> -
> -    /* Key. */
> -    uint8_t table_id;
> -    uint16_t priority;
> -    struct minimatch match;
> -
> -    /* Data. */
> -    struct uuid sb_uuid;
> -    struct ofpact *ofpacts;
> -    size_t ofpacts_len;
> -    uint64_t cookie;
> -};
> -
> -static uint32_t ovn_flow_match_hash(const struct ovn_flow *);
> -static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table,
> -                                        const struct ovn_flow *target,
> -                                        bool cmp_sb_uuid);
> -static char *ovn_flow_to_string(const struct ovn_flow *);
> -static void ovn_flow_log(const struct ovn_flow *, const char *action);
> -static void ovn_flow_destroy(struct ovn_flow *);
> -
> -/* OpenFlow connection to the switch. */
> -static struct rconn *swconn;
> -
> -/* Symbol table for OVN expressions. */
> -static struct shash symtab;
> -
> -/* Last seen sequence number for 'swconn'.  When this differs from
> - * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
> -static unsigned int seqno;
> -
> -/* Connection state machine. */
> -#define STATES                                  \
> -    STATE(S_NEW)                                \
> -    STATE(S_TLV_TABLE_REQUESTED)                \
> -    STATE(S_TLV_TABLE_MOD_SENT)                 \
> -    STATE(S_CLEAR_FLOWS)                        \
> -    STATE(S_UPDATE_FLOWS)
> -enum ofctrl_state {
> -#define STATE(NAME) NAME,
> -    STATES
> -#undef STATE
> -};
> -
> -/* An in-flight update to the switch's flow table.
> - *
> - * When we receive a barrier reply from the switch with the given 'xid',
> we
> - * know that the switch is caught up to northbound database sequence
> number
> - * 'nb_cfg' (and make that available to the client via
> ofctrl_get_cur_cfg(), so
> - * that it can store it into our Chassis record's nb_cfg column). */
> -struct ofctrl_flow_update {
> -    struct ovs_list list_node;  /* In 'flow_updates'. */
> -    ovs_be32 xid;               /* OpenFlow transaction ID for barrier. */
> -    int64_t nb_cfg;             /* Northbound database sequence number. */
> -};
> -
> -static struct ofctrl_flow_update *
> -ofctrl_flow_update_from_list_node(const struct ovs_list *list_node)
> -{
> -    return CONTAINER_OF(list_node, struct ofctrl_flow_update, list_node);
> -}
> -
> -/* Currently in-flight updates. */
> -static struct ovs_list flow_updates;
> -
> -/* nb_cfg of latest committed flow update. */
> -static int64_t cur_cfg;
> -
> -/* Current state. */
> -static enum ofctrl_state state;
> -
> -/* Transaction IDs for messages in flight to the switch. */
> -static ovs_be32 xid, xid2;
> -
> -/* Counter for in-flight OpenFlow messages on 'swconn'.  We only send a
> new
> - * round of flow table modifications to the switch when the counter falls
> to
> - * zero, to avoid unbounded buffering. */
> -static struct rconn_packet_counter *tx_counter;
> -
> -/* Flow table of "struct ovn_flow"s, that holds the flow table currently
> - * installed in the switch. */
> -static struct hmap installed_flows;
> -
> -/* A reference to the group_table. */
> -static struct ovn_extend_table *groups;
> -
> -/* A reference to the meter_table. */
> -static struct ovn_extend_table *meters;
> -
> -/* MFF_* field ID for our Geneve option.  In S_TLV_TABLE_MOD_SENT, this is
> - * the option we requested (we don't know whether we obtained it yet).  In
> - * S_CLEAR_FLOWS or S_UPDATE_FLOWS, this is really the option we have. */
> -static enum mf_field_id mff_ovn_geneve;
> -
> -/* Indicates if flows need to be reinstalled for scenarios when ovs
> - * is restarted, even if there is no change in the desired flow table. */
> -static bool need_reinstall_flows;
> -
> -static ovs_be32 queue_msg(struct ofpbuf *);
> -
> -static struct ofpbuf *encode_flow_mod(struct ofputil_flow_mod *);
> -
> -static struct ofpbuf *encode_group_mod(const struct ofputil_group_mod *);
> -
> -static struct ofpbuf *encode_meter_mod(const struct ofputil_meter_mod *);
> -
> -static void ovn_installed_flow_table_clear(void);
> -static void ovn_installed_flow_table_destroy(void);
> -
> -static void ofctrl_recv(const struct ofp_header *, enum ofptype);
> -
> -void
> -ofctrl_init(struct ovn_extend_table *group_table,
> -            struct ovn_extend_table *meter_table,
> -            int inactivity_probe_interval)
> -{
> -    swconn = rconn_create(inactivity_probe_interval, 0,
> -                          DSCP_DEFAULT, 1 << OFP13_VERSION);
> -    tx_counter = rconn_packet_counter_create();
> -    hmap_init(&installed_flows);
> -    ovs_list_init(&flow_updates);
> -    ovn_init_symtab(&symtab);
> -    groups = group_table;
> -    meters = meter_table;
> -}
> -
> -/* S_NEW, for a new connection.
> - *
> - * Sends NXT_TLV_TABLE_REQUEST and transitions to
> - * S_TLV_TABLE_REQUESTED. */
> -
> -static void
> -run_S_NEW(void)
> -{
> -    struct ofpbuf *buf = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_REQUEST,
> -                                      rconn_get_version(swconn), 0);
> -    xid = queue_msg(buf);
> -    state = S_TLV_TABLE_REQUESTED;
> -}
> -
> -static void
> -recv_S_NEW(const struct ofp_header *oh OVS_UNUSED,
> -           enum ofptype type OVS_UNUSED,
> -           struct shash *pending_ct_zones OVS_UNUSED)
> -{
> -    OVS_NOT_REACHED();
> -}
> -
> -/* S_TLV_TABLE_REQUESTED, when NXT_TLV_TABLE_REQUEST has been sent
> - * and we're waiting for a reply.
> - *
> - * If we receive an NXT_TLV_TABLE_REPLY:
> - *
> - *     - If it contains our tunnel metadata option, assign its field ID to
> - *       mff_ovn_geneve and transition to S_CLEAR_FLOWS.
> - *
> - *     - Otherwise, if there is an unused tunnel metadata field ID, send
> - *       NXT_TLV_TABLE_MOD and OFPT_BARRIER_REQUEST, and transition to
> - *       S_TLV_TABLE_MOD_SENT.
> - *
> - *     - Otherwise, log an error, disable Geneve, and transition to
> - *       S_CLEAR_FLOWS.
> - *
> - * If we receive an OFPT_ERROR:
> - *
> - *     - Log an error, disable Geneve, and transition to S_CLEAR_FLOWS. */
> -
> -static void
> -run_S_TLV_TABLE_REQUESTED(void)
> -{
> -}
> -
> -static bool
> -process_tlv_table_reply(const struct ofputil_tlv_table_reply *reply)
> -{
> -    const struct ofputil_tlv_map *map;
> -    uint64_t md_free = UINT64_MAX;
> -    BUILD_ASSERT(TUN_METADATA_NUM_OPTS == 64);
> -
> -    LIST_FOR_EACH (map, list_node, &reply->mappings) {
> -        if (map->option_class == OVN_GENEVE_CLASS
> -            && map->option_type == OVN_GENEVE_TYPE
> -            && map->option_len == OVN_GENEVE_LEN) {
> -            if (map->index >= TUN_METADATA_NUM_OPTS) {
> -                VLOG_ERR("desired Geneve tunnel option 0x%"PRIx16","
> -                         "%"PRIu8",%"PRIu8" already in use with "
> -                         "unsupported index %"PRIu16,
> -                         map->option_class, map->option_type,
> -                         map->option_len, map->index);
> -                return false;
> -            } else {
> -                mff_ovn_geneve = MFF_TUN_METADATA0 + map->index;
> -                state = S_CLEAR_FLOWS;
> -                return true;
> -            }
> -        }
> -
> -        if (map->index < TUN_METADATA_NUM_OPTS) {
> -            md_free &= ~(UINT64_C(1) << map->index);
> -        }
> -    }
> -
> -    VLOG_DBG("OVN Geneve option not found");
> -    if (!md_free) {
> -        VLOG_ERR("no Geneve options free for use by OVN");
> -        return false;
> -    }
> -
> -    unsigned int index = rightmost_1bit_idx(md_free);
> -    mff_ovn_geneve = MFF_TUN_METADATA0 + index;
> -    struct ofputil_tlv_map tm;
> -    tm.option_class = OVN_GENEVE_CLASS;
> -    tm.option_type = OVN_GENEVE_TYPE;
> -    tm.option_len = OVN_GENEVE_LEN;
> -    tm.index = index;
> -
> -    struct ofputil_tlv_table_mod ttm;
> -    ttm.command = NXTTMC_ADD;
> -    ovs_list_init(&ttm.mappings);
> -    ovs_list_push_back(&ttm.mappings, &tm.list_node);
> -
> -    xid = queue_msg(ofputil_encode_tlv_table_mod(OFP13_VERSION, &ttm));
> -    xid2 = queue_msg(ofputil_encode_barrier_request(OFP13_VERSION));
> -    state = S_TLV_TABLE_MOD_SENT;
> -
> -    return true;
> -}
> -
> -static void
> -recv_S_TLV_TABLE_REQUESTED(const struct ofp_header *oh, enum ofptype type,
> -                           struct shash *pending_ct_zones OVS_UNUSED)
> -{
> -    if (oh->xid != xid) {
> -        ofctrl_recv(oh, type);
> -        return;
> -    } else if (type == OFPTYPE_NXT_TLV_TABLE_REPLY) {
> -        struct ofputil_tlv_table_reply reply;
> -        enum ofperr error = ofputil_decode_tlv_table_reply(oh, &reply);
> -        if (!error) {
> -            bool ok = process_tlv_table_reply(&reply);
> -            ofputil_uninit_tlv_table(&reply.mappings);
> -            if (ok) {
> -                return;
> -            }
> -        } else {
> -            VLOG_ERR("failed to decode TLV table request (%s)",
> -                     ofperr_to_string(error));
> -        }
> -    } else if (type == OFPTYPE_ERROR) {
> -        VLOG_ERR("switch refused to allocate Geneve option (%s)",
> -                 ofperr_to_string(ofperr_decode_msg(oh, NULL)));
> -    } else {
> -        char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1);
> -        VLOG_ERR("unexpected reply to TLV table request (%s)", s);
> -        free(s);
> -    }
> -
> -    /* Error path. */
> -    mff_ovn_geneve = 0;
> -    state = S_CLEAR_FLOWS;
> -}
> -
> -/* S_TLV_TABLE_MOD_SENT, when NXT_TLV_TABLE_MOD and OFPT_BARRIER_REQUEST
> - * have been sent and we're waiting for a reply to one or the other.
> - *
> - * If we receive an OFPT_ERROR:
> - *
> - *     - If the error is NXTTMFC_ALREADY_MAPPED or NXTTMFC_DUP_ENTRY, we
> - *       raced with some other controller.  Transition to S_NEW.
> - *
> - *     - Otherwise, log an error, disable Geneve, and transition to
> - *       S_CLEAR_FLOWS.
> - *
> - * If we receive OFPT_BARRIER_REPLY:
> - *
> - *     - Set the tunnel metadata field ID to the one that we requested.
> - *       Transition to S_CLEAR_FLOWS.
> - */
> -
> -static void
> -run_S_TLV_TABLE_MOD_SENT(void)
> -{
> -}
> -
> -static void
> -recv_S_TLV_TABLE_MOD_SENT(const struct ofp_header *oh, enum ofptype type,
> -                          struct shash *pending_ct_zones OVS_UNUSED)
> -{
> -    if (oh->xid != xid && oh->xid != xid2) {
> -        ofctrl_recv(oh, type);
> -    } else if (oh->xid == xid2 && type == OFPTYPE_BARRIER_REPLY) {
> -        state = S_CLEAR_FLOWS;
> -    } else if (oh->xid == xid && type == OFPTYPE_ERROR) {
> -        enum ofperr error = ofperr_decode_msg(oh, NULL);
> -        if (error == OFPERR_NXTTMFC_ALREADY_MAPPED ||
> -            error == OFPERR_NXTTMFC_DUP_ENTRY) {
> -            VLOG_INFO("raced with another controller adding "
> -                      "Geneve option (%s); trying again",
> -                      ofperr_to_string(error));
> -            state = S_NEW;
> -        } else {
> -            VLOG_ERR("error adding Geneve option (%s)",
> -                     ofperr_to_string(error));
> -            goto error;
> -        }
> -    } else {
> -        char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1);
> -        VLOG_ERR("unexpected reply to Geneve option allocation request
> (%s)",
> -                 s);
> -        free(s);
> -        goto error;
> -    }
> -    return;
> -
> -error:
> -    state = S_CLEAR_FLOWS;
> -}
> -
> -/* S_CLEAR_FLOWS, after we've established a Geneve metadata field ID and
> it's
> - * time to set up some flows.
> - *
> - * Sends an OFPT_TABLE_MOD to clear all flows, then transitions to
> - * S_UPDATE_FLOWS. */
> -
> -static void
> -run_S_CLEAR_FLOWS(void)
> -{
> -    VLOG_DBG("clearing all flows");
> -
> -    need_reinstall_flows = true;
> -    /* Send a flow_mod to delete all flows. */
> -    struct ofputil_flow_mod fm = {
> -        .table_id = OFPTT_ALL,
> -        .command = OFPFC_DELETE,
> -    };
> -    minimatch_init_catchall(&fm.match);
> -    queue_msg(encode_flow_mod(&fm));
> -    minimatch_destroy(&fm.match);
> -
> -    /* Send a group_mod to delete all groups. */
> -    struct ofputil_group_mod gm;
> -    memset(&gm, 0, sizeof gm);
> -    gm.command = OFPGC11_DELETE;
> -    gm.group_id = OFPG_ALL;
> -    gm.command_bucket_id = OFPG15_BUCKET_ALL;
> -    ovs_list_init(&gm.buckets);
> -    queue_msg(encode_group_mod(&gm));
> -    ofputil_uninit_group_mod(&gm);
> -
> -    /* Clear installed_flows, to match the state of the switch. */
> -    ovn_installed_flow_table_clear();
> -
> -    /* Clear existing groups, to match the state of the switch. */
> -    if (groups) {
> -        ovn_extend_table_clear(groups, true);
> -    }
> -
> -    /* Send a meter_mod to delete all meters. */
> -    struct ofputil_meter_mod mm;
> -    memset(&mm, 0, sizeof mm);
> -    mm.command = OFPMC13_DELETE;
> -    mm.meter.meter_id = OFPM13_ALL;
> -    queue_msg(encode_meter_mod(&mm));
> -
> -    /* Clear existing meters, to match the state of the switch. */
> -    if (meters) {
> -        ovn_extend_table_clear(meters, true);
> -    }
> -
> -    /* All flow updates are irrelevant now. */
> -    struct ofctrl_flow_update *fup, *next;
> -    LIST_FOR_EACH_SAFE (fup, next, list_node, &flow_updates) {
> -        ovs_list_remove(&fup->list_node);
> -        free(fup);
> -    }
> -
> -    state = S_UPDATE_FLOWS;
> -}
> -
> -static void
> -recv_S_CLEAR_FLOWS(const struct ofp_header *oh, enum ofptype type,
> -                   struct shash *pending_ct_zones OVS_UNUSED)
> -{
> -    ofctrl_recv(oh, type);
> -}
> -
> -/* S_UPDATE_FLOWS, for maintaining the flow table over time.
> - *
> - * Compare the installed flows to the ones we want.  Send OFPT_FLOW_MOD as
> - * necessary.
> - *
> - * This is a terminal state.  We only transition out of it if the
>