diff --git a/controller/controller-utils.c b/controller/controller-utils.c
index 2ec4df1ac..a74600d0b 100644
--- a/controller/controller-utils.c
+++ b/controller/controller-utils.c
@@ -17,6 +17,12 @@
 
 #include "ovn-controller.h"
 #include "lib/vswitch-idl.h"
+#include "lib/stream.h"
+#include "lib/stream-ssl.h"
+#include "lib/sset.h"
+
+#define DEFAULT_BRIDGE_NAME "br-int"
+#define DEFAULT_PROBE_INTERVAL_MSEC 5000
 
 struct local_datapath *
 get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key)
@@ -52,3 +58,163 @@ get_bridge(const struct ovsrec_bridge_table *bridge_table, const char *br_name)
     }
     return NULL;
 }
+
+const char *
+br_int_name(const struct ovsrec_open_vswitch *cfg)
+{
+    return smap_get_def(&cfg->external_ids, "ovn-bridge", DEFAULT_BRIDGE_NAME);
+}
+
+const struct ovsrec_bridge *
+get_br_int(const struct ovsrec_bridge_table *bridge_table,
+           const struct ovsrec_open_vswitch_table *ovs_table)
+{
+    const struct ovsrec_open_vswitch *cfg;
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
+    if (!cfg) {
+        return NULL;
+    }
+
+    return get_bridge(bridge_table, br_int_name(cfg));
+}
+
+/* Retrieves the pointer to the OVN Southbound database from 'ovs_idl' and
+ * updates 'sbdb_idl' with that pointer. */
+void
+update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl)
+{
+    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
+
+    /* Set remote based on user configuration. */
+    const char *remote = NULL;
+    if (cfg) {
+        remote = smap_get(&cfg->external_ids, "ovn-remote");
+    }
+    ovsdb_idl_set_remote(ovnsb_idl, remote, true);
+
+    /* Set probe interval, based on user configuration and the remote. */
+    int default_interval = (remote && !stream_or_pstream_needs_probes(remote)
+                            ? 0 : DEFAULT_PROBE_INTERVAL_MSEC);
+    int interval = smap_get_int(&cfg->external_ids,
+                                "ovn-remote-probe-interval", default_interval);
+    ovsdb_idl_set_probe_interval(ovnsb_idl, interval);
+}
+
+void
+update_ssl_config(const struct ovsrec_ssl_table *ssl_table)
+{
+    const struct ovsrec_ssl *ssl = ovsrec_ssl_table_first(ssl_table);
+
+    if (ssl) {
+        stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
+        stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
+    }
+}
+
+const char *
+get_ovs_chassis_id(const struct ovsrec_open_vswitch_table *ovs_table)
+{
+    const struct ovsrec_open_vswitch *cfg
+        = ovsrec_open_vswitch_table_first(ovs_table);
+    return cfg ? smap_get(&cfg->external_ids, "system-id")
+                                 : NULL;
+}
+
+void
+update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
+                   const struct sbrec_chassis *chassis,
+                   const struct sset *local_ifaces,
+                   struct hmap *local_datapaths)
+{
+    /* Monitor Port_Bindings rows for local interfaces and local datapaths.
+     *
+     * Monitor Logical_Flow, MAC_Binding, Multicast_Group, and DNS tables for
+     * local datapaths.
+     *
+     * Monitor Controller_Event rows for local chassis.
+     *
+     * Monitor IP_Multicast for local datapaths.
+     *
+     * Monitor IGMP_Groups for local chassis.
+     *
+     * We always monitor patch ports because they allow us to see the linkages
+     * between related logical datapaths.  That way, when we know that we have
+     * a VIF on a particular logical switch, we immediately know to monitor all
+     * the connected logical routers and logical switches. */
+    struct ovsdb_idl_condition pb = OVSDB_IDL_CONDITION_INIT(&pb);
+    struct ovsdb_idl_condition lf = OVSDB_IDL_CONDITION_INIT(&lf);
+    struct ovsdb_idl_condition mb = OVSDB_IDL_CONDITION_INIT(&mb);
+    struct ovsdb_idl_condition mg = OVSDB_IDL_CONDITION_INIT(&mg);
+    struct ovsdb_idl_condition dns = OVSDB_IDL_CONDITION_INIT(&dns);
+    struct ovsdb_idl_condition ce =  OVSDB_IDL_CONDITION_INIT(&ce);
+    struct ovsdb_idl_condition ip_mcast = OVSDB_IDL_CONDITION_INIT(&ip_mcast);
+    struct ovsdb_idl_condition igmp = OVSDB_IDL_CONDITION_INIT(&igmp);
+    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "patch");
+    /* XXX: We can optimize this, if we find a way to only monitor
+     * ports that have a Gateway_Chassis that point's to our own
+     * chassis */
+    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "chassisredirect");
+    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "external");
+    if (chassis) {
+        /* This should be mostly redundant with the other clauses for port
+         * bindings, but it allows us to catch any ports that are assigned to
+         * us but should not be.  That way, we can clear their chassis
+         * assignments. */
+        sbrec_port_binding_add_clause_chassis(&pb, OVSDB_F_EQ,
+                                              &chassis->header_.uuid);
+
+        /* Ensure that we find out about l2gateway and l3gateway ports that
+         * should be present on this chassis.  Otherwise, we might never find
+         * out about those ports, if their datapaths don't otherwise have a VIF
+         * in this chassis. */
+        const char *id = chassis->name;
+        const struct smap l2 = SMAP_CONST1(&l2, "l2gateway-chassis", id);
+        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l2);
+        const struct smap l3 = SMAP_CONST1(&l3, "l3gateway-chassis", id);
+        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l3);
+
+        sbrec_controller_event_add_clause_chassis(&ce, OVSDB_F_EQ,
+                                                  &chassis->header_.uuid);
+        sbrec_igmp_group_add_clause_chassis(&igmp, OVSDB_F_EQ,
+                                            &chassis->header_.uuid);
+    }
+    if (local_ifaces) {
+        const char *name;
+        SSET_FOR_EACH (name, local_ifaces) {
+            sbrec_port_binding_add_clause_logical_port(&pb, OVSDB_F_EQ, name);
+            sbrec_port_binding_add_clause_parent_port(&pb, OVSDB_F_EQ, name);
+        }
+    }
+    if (local_datapaths) {
+        const struct local_datapath *ld;
+        HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
+            struct uuid *uuid = CONST_CAST(struct uuid *,
+                                           &ld->datapath->header_.uuid);
+            sbrec_port_binding_add_clause_datapath(&pb, OVSDB_F_EQ, uuid);
+            sbrec_logical_flow_add_clause_logical_datapath(&lf, OVSDB_F_EQ,
+                                                           uuid);
+            sbrec_mac_binding_add_clause_datapath(&mb, OVSDB_F_EQ, uuid);
+            sbrec_multicast_group_add_clause_datapath(&mg, OVSDB_F_EQ, uuid);
+            sbrec_dns_add_clause_datapaths(&dns, OVSDB_F_INCLUDES, &uuid, 1);
+            sbrec_ip_multicast_add_clause_datapath(&ip_mcast, OVSDB_F_EQ,
+                                                   uuid);
+        }
+    }
+    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
+    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
+    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
+    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
+    sbrec_dns_set_condition(ovnsb_idl, &dns);
+    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
+    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
+    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
+    ovsdb_idl_condition_destroy(&pb);
+    ovsdb_idl_condition_destroy(&lf);
+    ovsdb_idl_condition_destroy(&mb);
+    ovsdb_idl_condition_destroy(&mg);
+    ovsdb_idl_condition_destroy(&dns);
+    ovsdb_idl_condition_destroy(&ce);
+    ovsdb_idl_condition_destroy(&ip_mcast);
+    ovsdb_idl_condition_destroy(&igmp);
+}
+
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 532a9a482..5a323f9aa 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -73,8 +73,6 @@ static unixctl_cb_func group_table_list;
 static unixctl_cb_func inject_pkt;
 static unixctl_cb_func ovn_controller_conn_show;
 
-#define DEFAULT_BRIDGE_NAME "br-int"
-#define DEFAULT_PROBE_INTERVAL_MSEC 5000
 #define OFCTRL_DEFAULT_PROBE_INTERVAL_SEC 5
 
 #define CONTROLLER_LOOP_STOPWATCH_NAME "ovn-controller-flow-generation"
@@ -89,110 +87,6 @@ struct pending_pkt {
     char *flow_s;
 };
 
-static void
-update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
-                   const struct sbrec_chassis *chassis,
-                   const struct sset *local_ifaces,
-                   struct hmap *local_datapaths)
-{
-    /* Monitor Port_Bindings rows for local interfaces and local datapaths.
-     *
-     * Monitor Logical_Flow, MAC_Binding, Multicast_Group, and DNS tables for
-     * local datapaths.
-     *
-     * Monitor Controller_Event rows for local chassis.
-     *
-     * Monitor IP_Multicast for local datapaths.
-     *
-     * Monitor IGMP_Groups for local chassis.
-     *
-     * We always monitor patch ports because they allow us to see the linkages
-     * between related logical datapaths.  That way, when we know that we have
-     * a VIF on a particular logical switch, we immediately know to monitor all
-     * the connected logical routers and logical switches. */
-    struct ovsdb_idl_condition pb = OVSDB_IDL_CONDITION_INIT(&pb);
-    struct ovsdb_idl_condition lf = OVSDB_IDL_CONDITION_INIT(&lf);
-    struct ovsdb_idl_condition mb = OVSDB_IDL_CONDITION_INIT(&mb);
-    struct ovsdb_idl_condition mg = OVSDB_IDL_CONDITION_INIT(&mg);
-    struct ovsdb_idl_condition dns = OVSDB_IDL_CONDITION_INIT(&dns);
-    struct ovsdb_idl_condition ce =  OVSDB_IDL_CONDITION_INIT(&ce);
-    struct ovsdb_idl_condition ip_mcast = OVSDB_IDL_CONDITION_INIT(&ip_mcast);
-    struct ovsdb_idl_condition igmp = OVSDB_IDL_CONDITION_INIT(&igmp);
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "patch");
-    /* XXX: We can optimize this, if we find a way to only monitor
-     * ports that have a Gateway_Chassis that point's to our own
-     * chassis */
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "chassisredirect");
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "external");
-    if (chassis) {
-        /* This should be mostly redundant with the other clauses for port
-         * bindings, but it allows us to catch any ports that are assigned to
-         * us but should not be.  That way, we can clear their chassis
-         * assignments. */
-        sbrec_port_binding_add_clause_chassis(&pb, OVSDB_F_EQ,
-                                              &chassis->header_.uuid);
-
-        /* Ensure that we find out about l2gateway and l3gateway ports that
-         * should be present on this chassis.  Otherwise, we might never find
-         * out about those ports, if their datapaths don't otherwise have a VIF
-         * in this chassis. */
-        const char *id = chassis->name;
-        const struct smap l2 = SMAP_CONST1(&l2, "l2gateway-chassis", id);
-        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l2);
-        const struct smap l3 = SMAP_CONST1(&l3, "l3gateway-chassis", id);
-        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l3);
-
-        sbrec_controller_event_add_clause_chassis(&ce, OVSDB_F_EQ,
-                                                  &chassis->header_.uuid);
-        sbrec_igmp_group_add_clause_chassis(&igmp, OVSDB_F_EQ,
-                                            &chassis->header_.uuid);
-    }
-    if (local_ifaces) {
-        const char *name;
-        SSET_FOR_EACH (name, local_ifaces) {
-            sbrec_port_binding_add_clause_logical_port(&pb, OVSDB_F_EQ, name);
-            sbrec_port_binding_add_clause_parent_port(&pb, OVSDB_F_EQ, name);
-        }
-    }
-    if (local_datapaths) {
-        const struct local_datapath *ld;
-        HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
-            struct uuid *uuid = CONST_CAST(struct uuid *,
-                                           &ld->datapath->header_.uuid);
-            sbrec_port_binding_add_clause_datapath(&pb, OVSDB_F_EQ, uuid);
-            sbrec_logical_flow_add_clause_logical_datapath(&lf, OVSDB_F_EQ,
-                                                           uuid);
-            sbrec_mac_binding_add_clause_datapath(&mb, OVSDB_F_EQ, uuid);
-            sbrec_multicast_group_add_clause_datapath(&mg, OVSDB_F_EQ, uuid);
-            sbrec_dns_add_clause_datapaths(&dns, OVSDB_F_INCLUDES, &uuid, 1);
-            sbrec_ip_multicast_add_clause_datapath(&ip_mcast, OVSDB_F_EQ,
-                                                   uuid);
-        }
-    }
-    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
-    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
-    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
-    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
-    sbrec_dns_set_condition(ovnsb_idl, &dns);
-    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
-    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
-    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
-    ovsdb_idl_condition_destroy(&pb);
-    ovsdb_idl_condition_destroy(&lf);
-    ovsdb_idl_condition_destroy(&mb);
-    ovsdb_idl_condition_destroy(&mg);
-    ovsdb_idl_condition_destroy(&dns);
-    ovsdb_idl_condition_destroy(&ce);
-    ovsdb_idl_condition_destroy(&ip_mcast);
-    ovsdb_idl_condition_destroy(&igmp);
-}
-
-static const char *
-br_int_name(const struct ovsrec_open_vswitch *cfg)
-{
-    return smap_get_def(&cfg->external_ids, "ovn-bridge", DEFAULT_BRIDGE_NAME);
-}
-
 static const struct ovsrec_bridge *
 create_br_int(struct ovsdb_idl_txn *ovs_idl_txn,
               const struct ovsrec_open_vswitch_table *ovs_table)
@@ -241,19 +135,6 @@ create_br_int(struct ovsdb_idl_txn *ovs_idl_txn,
     return bridge;
 }
 
-static const struct ovsrec_bridge *
-get_br_int(const struct ovsrec_bridge_table *bridge_table,
-           const struct ovsrec_open_vswitch_table *ovs_table)
-{
-    const struct ovsrec_open_vswitch *cfg;
-    cfg = ovsrec_open_vswitch_table_first(ovs_table);
-    if (!cfg) {
-        return NULL;
-    }
-
-    return get_bridge(bridge_table, br_int_name(cfg));
-}
-
 static const struct ovsrec_bridge *
 process_br_int(struct ovsdb_idl_txn *ovs_idl_txn,
                const struct ovsrec_bridge_table *bridge_table,
@@ -279,22 +160,6 @@ process_br_int(struct ovsdb_idl_txn *ovs_idl_txn,
     return br_int;
 }
 
-static const char *
-get_ovs_chassis_id(const struct ovsrec_open_vswitch_table *ovs_table)
-{
-    const struct ovsrec_open_vswitch *cfg
-        = ovsrec_open_vswitch_table_first(ovs_table);
-    const char *chassis_id = cfg ? smap_get(&cfg->external_ids, "system-id")
-                                 : NULL;
-
-    if (!chassis_id) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
-        VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing.");
-    }
-
-    return chassis_id;
-}
-
 /* Iterate address sets in the southbound database.  Create and update the
  * corresponding symtab entries as necessary. */
 static void
@@ -369,17 +234,6 @@ port_groups_update(const struct sbrec_port_group_table *port_group_table,
     }
 }
 
-static void
-update_ssl_config(const struct ovsrec_ssl_table *ssl_table)
-{
-    const struct ovsrec_ssl *ssl = ovsrec_ssl_table_first(ssl_table);
-
-    if (ssl) {
-        stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
-        stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
-    }
-}
-
 static int
 get_ofctrl_probe_interval(struct ovsdb_idl *ovs_idl)
 {
@@ -389,28 +243,6 @@ get_ofctrl_probe_interval(struct ovsdb_idl *ovs_idl)
                         OFCTRL_DEFAULT_PROBE_INTERVAL_SEC);
 }
 
-/* Retrieves the pointer to the OVN Southbound database from 'ovs_idl' and
- * updates 'sbdb_idl' with that pointer. */
-static void
-update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl)
-{
-    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
-
-    /* Set remote based on user configuration. */
-    const char *remote = NULL;
-    if (cfg) {
-        remote = smap_get(&cfg->external_ids, "ovn-remote");
-    }
-    ovsdb_idl_set_remote(ovnsb_idl, remote, true);
-
-    /* Set probe interval, based on user configuration and the remote. */
-    int default_interval = (remote && !stream_or_pstream_needs_probes(remote)
-                            ? 0 : DEFAULT_PROBE_INTERVAL_MSEC);
-    int interval = smap_get_int(&cfg->external_ids,
-                                "ovn-remote-probe-interval", default_interval);
-    ovsdb_idl_set_probe_interval(ovnsb_idl, interval);
-}
-
 static void
 update_ct_zones(const struct sset *lports, const struct hmap *local_datapaths,
                 struct simap *ct_zones, unsigned long *ct_zone_bitmap,
@@ -1964,6 +1796,9 @@ main(int argc, char *argv[])
                 chassis = chassis_run(ovnsb_idl_txn, sbrec_chassis_by_name,
                                       ovs_table, chassis_table, chassis_id,
                                       br_int, &transport_zones);
+            } else {
+                static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+                VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing.");
             }
 
             if (br_int) {
diff --git a/controller/ovn-controller.h b/controller/ovn-controller.h
index 86b300e44..d4640a01f 100644
--- a/controller/ovn-controller.h
+++ b/controller/ovn-controller.h
@@ -20,7 +20,11 @@
 #include "simap.h"
 #include "lib/ovn-sb-idl.h"
 
+struct ovsrec_open_vswitch;
 struct ovsrec_bridge_table;
+struct ovsrec_ssl_table;
+struct ovsrec_open_vswitch_table;
+struct sset;
 
 /* Linux supports a maximum of 64K zones, which seems like a fine default. */
 #define MAX_CT_ZONES 65535
@@ -79,8 +83,19 @@ struct local_datapath *get_local_datapath(const struct hmap *,
 const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *,
                                        const char *br_name);
 
+const char *br_int_name(const struct ovsrec_open_vswitch *);
+
+const struct ovsrec_bridge *get_br_int(const struct ovsrec_bridge_table *,
+        const struct ovsrec_open_vswitch_table *);
+
 struct sbrec_encap *preferred_encap(const struct sbrec_chassis *);
 
+void update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl);
+
+void update_ssl_config(const struct ovsrec_ssl_table *ssl_table);
+
+const char *get_ovs_chassis_id(const struct ovsrec_open_vswitch_table *);
+
 /* Must be a bit-field ordered from most-preferred (higher number) to
  * least-preferred (lower number). */
 enum chassis_tunnel_type {
@@ -91,4 +106,9 @@ enum chassis_tunnel_type {
 
 uint32_t get_tunnel_type(const char *name);
 
+void update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
+                   const struct sbrec_chassis *chassis,
+                   const struct sset *local_ifaces,
+                   struct hmap *local_datapaths);
+
 #endif /* controller/ovn-controller.h */
diff --git a/controller/ovn-pinctrl.c b/controller/ovn-pinctrl.c
index e2010661f..cb4be2ca5 100644
--- a/controller/ovn-pinctrl.c
+++ b/controller/ovn-pinctrl.c
@@ -71,45 +71,6 @@
 
 VLOG_DEFINE_THIS_MODULE(main);
 
-#define DEFAULT_BRIDGE_NAME "br-int"
-#define DEFAULT_PROBE_INTERVAL_MSEC 5000
-
-// XXX Copied directly from ovn-controller
-/* Retrieves the pointer to the OVN Southbound database from 'ovs_idl' and
- * updates 'sbdb_idl' with that pointer. */
-static void
-update_sb_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnsb_idl)
-{
-    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
-
-    /* Set remote based on user configuration. */
-    const char *remote = NULL;
-    if (cfg) {
-        remote = smap_get(&cfg->external_ids, "ovn-remote");
-    }
-    ovsdb_idl_set_remote(ovnsb_idl, remote, true);
-
-    /* Set probe interval, based on user configuration and the remote. */
-    int default_interval = (remote && !stream_or_pstream_needs_probes(remote)
-                            ? 0 : DEFAULT_PROBE_INTERVAL_MSEC);
-    int interval = smap_get_int(&cfg->external_ids,
-                                "ovn-remote-probe-interval", default_interval);
-    ovsdb_idl_set_probe_interval(ovnsb_idl, interval);
-}
-
-// XXX copied directly from ovn-controller
-static void
-update_ssl_config(const struct ovsrec_ssl_table *ssl_table)
-{
-    const struct ovsrec_ssl *ssl = ovsrec_ssl_table_first(ssl_table);
-
-    if (ssl) {
-        stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
-        stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
-    }
-}
-
-// XXX Copied directly from ovn-controller
 static void
 ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
 {
@@ -119,16 +80,18 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
     ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids);
     ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges);
     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_bfd);
-    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status);
-    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_type);
-    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options);
-    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd_status);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_type);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_options);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_ofport);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_status);
     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_column(ovs_idl, &ovsrec_port_col_name);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_external_ids);
     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name);
@@ -140,127 +103,6 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
     ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_ca_cert);
     ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_certificate);
     ovsdb_idl_add_column(ovs_idl, &ovsrec_ssl_col_private_key);
-    chassis_register_ovs_idl(ovs_idl);
-    encaps_register_ovs_idl(ovs_idl);
-    binding_register_ovs_idl(ovs_idl);
-    bfd_register_ovs_idl(ovs_idl);
-    physical_register_ovs_idl(ovs_idl);
-}
-
-// XXX copied directly from ovn-controller
-static void
-update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
-                   const struct sbrec_chassis *chassis,
-                   const struct sset *local_ifaces,
-                   struct hmap *local_datapaths)
-{
-    /* Monitor Port_Bindings rows for local interfaces and local datapaths.
-     *
-     * Monitor Logical_Flow, MAC_Binding, Multicast_Group, and DNS tables for
-     * local datapaths.
-     *
-     * Monitor Controller_Event rows for local chassis.
-     *
-     * Monitor IP_Multicast for local datapaths.
-     *
-     * Monitor IGMP_Groups for local chassis.
-     *
-     * We always monitor patch ports because they allow us to see the linkages
-     * between related logical datapaths.  That way, when we know that we have
-     * a VIF on a particular logical switch, we immediately know to monitor all
-     * the connected logical routers and logical switches. */
-    struct ovsdb_idl_condition pb = OVSDB_IDL_CONDITION_INIT(&pb);
-    struct ovsdb_idl_condition lf = OVSDB_IDL_CONDITION_INIT(&lf);
-    struct ovsdb_idl_condition mb = OVSDB_IDL_CONDITION_INIT(&mb);
-    struct ovsdb_idl_condition mg = OVSDB_IDL_CONDITION_INIT(&mg);
-    struct ovsdb_idl_condition dns = OVSDB_IDL_CONDITION_INIT(&dns);
-    struct ovsdb_idl_condition ce =  OVSDB_IDL_CONDITION_INIT(&ce);
-    struct ovsdb_idl_condition ip_mcast = OVSDB_IDL_CONDITION_INIT(&ip_mcast);
-    struct ovsdb_idl_condition igmp = OVSDB_IDL_CONDITION_INIT(&igmp);
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "patch");
-    /* XXX: We can optimize this, if we find a way to only monitor
-     * ports that have a Gateway_Chassis that point's to our own
-     * chassis */
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "chassisredirect");
-    sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "external");
-    if (chassis) {
-        /* This should be mostly redundant with the other clauses for port
-         * bindings, but it allows us to catch any ports that are assigned to
-         * us but should not be.  That way, we can clear their chassis
-         * assignments. */
-        sbrec_port_binding_add_clause_chassis(&pb, OVSDB_F_EQ,
-                                              &chassis->header_.uuid);
-
-        /* Ensure that we find out about l2gateway and l3gateway ports that
-         * should be present on this chassis.  Otherwise, we might never find
-         * out about those ports, if their datapaths don't otherwise have a VIF
-         * in this chassis. */
-        const char *id = chassis->name;
-        const struct smap l2 = SMAP_CONST1(&l2, "l2gateway-chassis", id);
-        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l2);
-        const struct smap l3 = SMAP_CONST1(&l3, "l3gateway-chassis", id);
-        sbrec_port_binding_add_clause_options(&pb, OVSDB_F_INCLUDES, &l3);
-
-        sbrec_controller_event_add_clause_chassis(&ce, OVSDB_F_EQ,
-                                                  &chassis->header_.uuid);
-        sbrec_igmp_group_add_clause_chassis(&igmp, OVSDB_F_EQ,
-                                            &chassis->header_.uuid);
-    }
-    if (local_ifaces) {
-        const char *name;
-        SSET_FOR_EACH (name, local_ifaces) {
-            sbrec_port_binding_add_clause_logical_port(&pb, OVSDB_F_EQ, name);
-            sbrec_port_binding_add_clause_parent_port(&pb, OVSDB_F_EQ, name);
-        }
-    }
-    if (local_datapaths) {
-        const struct local_datapath *ld;
-        HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
-            struct uuid *uuid = CONST_CAST(struct uuid *,
-                                           &ld->datapath->header_.uuid);
-            sbrec_port_binding_add_clause_datapath(&pb, OVSDB_F_EQ, uuid);
-            sbrec_logical_flow_add_clause_logical_datapath(&lf, OVSDB_F_EQ,
-                                                           uuid);
-            sbrec_mac_binding_add_clause_datapath(&mb, OVSDB_F_EQ, uuid);
-            sbrec_multicast_group_add_clause_datapath(&mg, OVSDB_F_EQ, uuid);
-            sbrec_dns_add_clause_datapaths(&dns, OVSDB_F_INCLUDES, &uuid, 1);
-            sbrec_ip_multicast_add_clause_datapath(&ip_mcast, OVSDB_F_EQ,
-                                                   uuid);
-        }
-    }
-    sbrec_port_binding_set_condition(ovnsb_idl, &pb);
-    sbrec_logical_flow_set_condition(ovnsb_idl, &lf);
-    sbrec_mac_binding_set_condition(ovnsb_idl, &mb);
-    sbrec_multicast_group_set_condition(ovnsb_idl, &mg);
-    sbrec_dns_set_condition(ovnsb_idl, &dns);
-    sbrec_controller_event_set_condition(ovnsb_idl, &ce);
-    sbrec_ip_multicast_set_condition(ovnsb_idl, &ip_mcast);
-    sbrec_igmp_group_set_condition(ovnsb_idl, &igmp);
-    ovsdb_idl_condition_destroy(&pb);
-    ovsdb_idl_condition_destroy(&lf);
-    ovsdb_idl_condition_destroy(&mb);
-    ovsdb_idl_condition_destroy(&mg);
-    ovsdb_idl_condition_destroy(&dns);
-    ovsdb_idl_condition_destroy(&ce);
-    ovsdb_idl_condition_destroy(&ip_mcast);
-    ovsdb_idl_condition_destroy(&igmp);
-}
-
-// XXX Copied directly from ovn-controller
-static const char *
-get_ovs_chassis_id(const struct ovsrec_open_vswitch_table *ovs_table)
-{
-    const struct ovsrec_open_vswitch *cfg
-        = ovsrec_open_vswitch_table_first(ovs_table);
-    const char *chassis_id = cfg ? smap_get(&cfg->external_ids, "system-id")
-                                 : NULL;
-
-    if (!chassis_id) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
-        VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing.");
-    }
-
-    return chassis_id;
 }
 
 static unixctl_cb_func ovn_pinctrl_exit;
@@ -281,7 +123,6 @@ usage(void)
     exit(EXIT_SUCCESS);
 }
 
-// XXX Copied directly from ovn-controller
 static char *
 parse_options(int argc, char *argv[])
 {
@@ -357,27 +198,6 @@ parse_options(int argc, char *argv[])
     return ovs_remote;
 }
 
-// XXX Copied directly from ovn-controller
-static const char *
-br_int_name(const struct ovsrec_open_vswitch *cfg)
-{
-    return smap_get_def(&cfg->external_ids, "ovn-bridge", DEFAULT_BRIDGE_NAME);
-}
-
-// XXX Copied directly from ovn-controller
-static const struct ovsrec_bridge *
-get_br_int(const struct ovsrec_bridge_table *bridge_table,
-           const struct ovsrec_open_vswitch_table *ovs_table)
-{
-    const struct ovsrec_open_vswitch *cfg;
-    cfg = ovsrec_open_vswitch_table_first(ovs_table);
-    if (!cfg) {
-        return NULL;
-    }
-
-    return get_bridge(bridge_table, br_int_name(cfg));
-}
-
 int
 main(int argc, char *argv[])
 {
@@ -499,6 +319,9 @@ main(int argc, char *argv[])
             const struct sbrec_chassis *chassis = NULL;
             if (chassis_id) {
                 chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+            } else {
+                static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+                VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing.");
             }
 
             if (br_int && chassis) {
