We're working to make ovn-controller compute more incrementally, to reduce
CPU usage.  To make it easier to keep track of dependencies, it makes sense
to pass around pointers to fine-grained resources instead of an entire
database at a time.  This commit introduces a way to pass individual tables
around and starts using that feature in ovn-controller.

CC: Han Zhou <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
---
 ovn/controller/bfd.c            |   9 ++-
 ovn/controller/bfd.h            |   5 +-
 ovn/controller/binding.c        |  29 ++++---
 ovn/controller/binding.h        |  13 +++-
 ovn/controller/chassis.c        |   9 ++-
 ovn/controller/chassis.h        |   9 ++-
 ovn/controller/encaps.c         |   9 ++-
 ovn/controller/encaps.h         |   7 +-
 ovn/controller/lflow.c          |  49 +++++++-----
 ovn/controller/lflow.h          |   8 ++
 ovn/controller/ovn-controller.c | 163 +++++++++++++++++++++++++++-------------
 ovn/controller/ovn-controller.h |   6 +-
 ovn/controller/patch.c          |  27 ++++---
 ovn/controller/patch.h          |  11 ++-
 ovn/controller/physical.c       |  11 ++-
 ovn/controller/physical.h       |   9 ++-
 ovn/controller/pinctrl.c        |  35 +++++----
 ovn/controller/pinctrl.h        |   4 +
 ovn/lib/chassis-index.c         |   6 +-
 ovn/lib/chassis-index.h         |   6 +-
 ovn/northd/ovn-northd.c         |   3 +-
 ovsdb/ovsdb-idlc.in             |  27 +++++++
 22 files changed, 318 insertions(+), 137 deletions(-)

diff --git a/ovn/controller/bfd.c b/ovn/controller/bfd.c
index 6fc83554c9b0..c6c6cbaaacb9 100644
--- a/ovn/controller/bfd.c
+++ b/ovn/controller/bfd.c
@@ -246,8 +246,11 @@ bfd_calculate_chassis(struct controller_ctx *ctx,
 }
 
 void
-bfd_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
-        const struct sbrec_chassis *chassis_rec, const struct hmap 
*local_datapaths,
+bfd_run(struct controller_ctx *ctx,
+        const struct ovsrec_interface_table *interface_table,
+        const struct ovsrec_bridge *br_int,
+        const struct sbrec_chassis *chassis_rec,
+        const struct hmap *local_datapaths,
         const struct chassis_index *chassis_index)
 {
 
@@ -274,7 +277,7 @@ bfd_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
 
     /* Enable or disable bfd */
     const struct ovsrec_interface *iface;
-    OVSREC_INTERFACE_FOR_EACH (iface, ctx->ovs_idl) {
+    OVSREC_INTERFACE_TABLE_FOR_EACH (iface, interface_table) {
         if (sset_contains(&tunnels, iface->name)) {
                 interface_set_bfd(
                         iface, sset_contains(&bfd_ifaces, iface->name));
diff --git a/ovn/controller/bfd.h b/ovn/controller/bfd.h
index 7fa4775654dd..240cf2d6bde5 100644
--- a/ovn/controller/bfd.h
+++ b/ovn/controller/bfd.h
@@ -21,11 +21,14 @@ struct controller_ctx;
 struct hmap;
 struct ovsdb_idl;
 struct ovsrec_bridge;
+struct ovsrec_interface_table;
 struct sbrec_chassis;
 struct sset;
 
 void bfd_register_ovs_idl(struct ovsdb_idl *);
-void bfd_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
+void bfd_run(struct controller_ctx *ctx,
+             const struct ovsrec_interface_table *interface_table,
+             const struct ovsrec_bridge *br_int,
              const struct sbrec_chassis *chassis_rec,
              const struct hmap *local_datapaths, const struct chassis_index *);
 void  bfd_calculate_active_tunnels(const struct ovsrec_bridge *br_int,
diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index 3ee1f6739247..a9a50dc68132 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -200,10 +200,11 @@ get_qos_params(const struct sbrec_port_binding *pb, 
struct hmap *queue_map)
 }
 
 static const struct ovsrec_qos *
-get_noop_qos(struct controller_ctx *ctx)
+get_noop_qos(struct controller_ctx *ctx,
+             const struct ovsrec_qos_table *qos_table)
 {
     const struct ovsrec_qos *qos;
-    OVSREC_QOS_FOR_EACH (qos, ctx->ovs_idl) {
+    OVSREC_QOS_TABLE_FOR_EACH (qos, qos_table) {
         if (!strcmp(qos->type, "linux-noop")) {
             return qos;
         }
@@ -218,13 +219,16 @@ get_noop_qos(struct controller_ctx *ctx)
 }
 
 static bool
-set_noop_qos(struct controller_ctx *ctx, struct sset *egress_ifaces)
+set_noop_qos(struct controller_ctx *ctx,
+             const struct ovsrec_port_table *port_table,
+             const struct ovsrec_qos_table *qos_table,
+             struct sset *egress_ifaces)
 {
     if (!ctx->ovs_idl_txn) {
         return false;
     }
 
-    const struct ovsrec_qos *noop_qos = get_noop_qos(ctx);
+    const struct ovsrec_qos *noop_qos = get_noop_qos(ctx, qos_table);
     if (!noop_qos) {
         return false;
     }
@@ -232,7 +236,7 @@ set_noop_qos(struct controller_ctx *ctx, struct sset 
*egress_ifaces)
     const struct ovsrec_port *port;
     size_t count = 0;
 
-    OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
+    OVSREC_PORT_TABLE_FOR_EACH (port, port_table) {
         if (sset_contains(egress_ifaces, port->name)) {
             ovsrec_port_set_qos(port, noop_qos);
             count++;
@@ -524,7 +528,11 @@ consider_localnet_port(const struct sbrec_port_binding 
*binding_rec,
 }
 
 void
-binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
+binding_run(struct controller_ctx *ctx,
+            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 chassis_index *chassis_index,
             const struct sset *active_tunnels,
@@ -549,7 +557,7 @@ binding_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
     /* 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_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
+    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
         consider_local_datapath(ctx, chassis_index,
                                 active_tunnels, chassis_rec, binding_rec,
                                 sset_is_empty(&egress_ifaces) ? NULL :
@@ -561,14 +569,14 @@ binding_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
     /* 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_FOR_EACH (binding_rec, ctx->ovnsb_idl) {
+    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(ctx, &egress_ifaces)) {
+        && set_noop_qos(ctx, port_table, qos_table, &egress_ifaces)) {
         const char *entry;
         SSET_FOR_EACH (entry, &egress_ifaces) {
             setup_qos(entry, &qos_map);
@@ -584,6 +592,7 @@ binding_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
  * required. */
 bool
 binding_cleanup(struct controller_ctx *ctx,
+                const struct sbrec_port_binding_table *port_binding_table,
                 const struct sbrec_chassis *chassis_rec)
 {
     if (!ctx->ovnsb_idl_txn) {
@@ -600,7 +609,7 @@ binding_cleanup(struct controller_ctx *ctx,
 
     const struct sbrec_port_binding *binding_rec;
     bool any_changes = false;
-    SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
+    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding_rec, port_binding_table) {
         if (binding_rec->chassis == chassis_rec) {
             sbrec_port_binding_set_chassis(binding_rec, NULL);
             any_changes = true;
diff --git a/ovn/controller/binding.h b/ovn/controller/binding.h
index eb4c024c0e37..0f8a3a19bcf9 100644
--- a/ovn/controller/binding.h
+++ b/ovn/controller/binding.h
@@ -24,16 +24,25 @@ struct chassis_index;
 struct hmap;
 struct ovsdb_idl;
 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 controller_ctx *, const struct ovsrec_bridge *br_int,
+void binding_run(struct controller_ctx *,
+                 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 chassis_index *,
                  const struct sset *active_tunnels,
                  struct hmap *local_datapaths,
                  struct sset *local_lports, struct sset *local_lport_ids);
-bool binding_cleanup(struct controller_ctx *, const struct sbrec_chassis *);
+bool binding_cleanup(struct controller_ctx *,
+                     const struct sbrec_port_binding_table *,
+                     const struct sbrec_chassis *);
 
 #endif /* ovn/binding.h */
diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c
index 6b5286ae7578..c509e2fcab50 100644
--- a/ovn/controller/chassis.c
+++ b/ovn/controller/chassis.c
@@ -75,7 +75,10 @@ get_cms_options(const struct smap *ext_ids)
 /* Returns this chassis's Chassis record, if it is available and is currently
  * amenable to a transaction. */
 const struct sbrec_chassis *
-chassis_run(struct controller_ctx *ctx, const char *chassis_id,
+chassis_run(struct controller_ctx *ctx,
+            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)
 {
     if (!ctx->ovnsb_idl_txn) {
@@ -86,7 +89,7 @@ chassis_run(struct controller_ctx *ctx, const char 
*chassis_id,
     const char *encap_type, *encap_ip;
     static bool inited = false;
 
-    cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
     if (!cfg) {
         VLOG_INFO("No Open_vSwitch row defined.");
         return NULL;
@@ -136,7 +139,7 @@ chassis_run(struct controller_ctx *ctx, const char 
*chassis_id,
     const char *iface_types_str = ds_cstr(&iface_types);
 
     const struct sbrec_chassis *chassis_rec
-        = get_chassis(ctx->ovnsb_idl, chassis_id);
+        = get_chassis(chassis_table, chassis_id);
     const char *encap_csum = smap_get_def(&cfg->external_ids,
                                           "ovn-encap-csum", "true");
     if (chassis_rec) {
diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h
index 2cc47fc2f5e9..6d4787854c1c 100644
--- a/ovn/controller/chassis.h
+++ b/ovn/controller/chassis.h
@@ -21,12 +21,15 @@
 struct controller_ctx;
 struct ovsdb_idl;
 struct ovsrec_bridge;
+struct ovsrec_open_vswitch_table;
 struct sbrec_chassis;
+struct sbrec_chassis_table;
 
 void chassis_register_ovs_idl(struct ovsdb_idl *);
-const struct sbrec_chassis *chassis_run(struct controller_ctx *,
-                                        const char *chassis_id,
-                                        const struct ovsrec_bridge *br_int);
+const struct sbrec_chassis *chassis_run(
+    struct controller_ctx *, const struct ovsrec_open_vswitch_table *,
+    const struct sbrec_chassis_table *,
+    const char *chassis_id, const struct ovsrec_bridge *br_int);
 bool chassis_cleanup(struct controller_ctx *, const struct sbrec_chassis *);
 
 #endif /* ovn/chassis.h */
diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c
index f187a8f7bfb8..edcc86977ab8 100644
--- a/ovn/controller/encaps.c
+++ b/ovn/controller/encaps.c
@@ -153,7 +153,10 @@ preferred_encap(const struct sbrec_chassis *chassis_rec)
 }
 
 void
-encaps_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
+encaps_run(struct controller_ctx *ctx,
+           const struct ovsrec_bridge_table *bridge_table,
+           const struct ovsrec_bridge *br_int,
+           const struct sbrec_chassis_table *chassis_table,
            const char *chassis_id)
 {
     if (!ctx->ovs_idl_txn || !br_int) {
@@ -177,7 +180,7 @@ encaps_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
     /* Collect all port names into tc.port_names.
      *
      * Collect all the OVN-created tunnels into tc.tunnel_hmap. */
-    OVSREC_BRIDGE_FOR_EACH(br, ctx->ovs_idl) {
+    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);
@@ -198,7 +201,7 @@ encaps_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
         }
     }
 
-    SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->ovnsb_idl) {
+    SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) {
         if (strcmp(chassis_rec->name, chassis_id)) {
             /* Create tunnels to the other chassis. */
             const struct sbrec_encap *encap = preferred_encap(chassis_rec);
diff --git a/ovn/controller/encaps.h b/ovn/controller/encaps.h
index 20f0eb0f5339..429643f3f0cf 100644
--- a/ovn/controller/encaps.h
+++ b/ovn/controller/encaps.h
@@ -21,10 +21,15 @@
 struct controller_ctx;
 struct ovsdb_idl;
 struct ovsrec_bridge;
+struct ovsrec_bridge_table;
+struct sbrec_chassis_table;
 
 void encaps_register_ovs_idl(struct ovsdb_idl *);
 void encaps_run(struct controller_ctx *,
-                const struct ovsrec_bridge *br_int, const char *chassis_id);
+                const struct ovsrec_bridge_table *,
+                const struct ovsrec_bridge *br_int,
+                const struct sbrec_chassis_table *,
+                const char *chassis_id);
 bool encaps_cleanup(struct controller_ctx *,
                     const struct ovsrec_bridge *br_int);
 
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index db96197828aa..86aac2a4731a 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -137,17 +137,21 @@ is_switch(const struct sbrec_datapath_binding *ldp)
 
 /* Adds the logical flows from the Logical_Flow table to flow tables. */
 static void
-add_logical_flows(struct controller_ctx *ctx,
-                  const struct chassis_index *chassis_index,
-                  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 hmap *flow_table,
-                  struct ovn_extend_table *group_table,
-                  struct ovn_extend_table *meter_table)
+add_logical_flows(
+    struct controller_ctx *ctx,
+    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 chassis_index *chassis_index,
+    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 hmap *flow_table,
+    struct ovn_extend_table *group_table,
+    struct ovn_extend_table *meter_table)
 {
     uint32_t conj_id_ofs = 1;
     const struct sbrec_logical_flow *lflow;
@@ -155,14 +159,15 @@ add_logical_flows(struct controller_ctx *ctx,
     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_FOR_EACH(dhcp_opt_row, ctx->ovnsb_idl) {
+    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_FOR_EACH(dhcpv6_opt_row, ctx->ovnsb_idl) {
+    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);
     }
@@ -170,7 +175,7 @@ add_logical_flows(struct controller_ctx *ctx,
     struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
     nd_ra_opts_init(&nd_ra_opts);
 
-    SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow, logical_flow_table) {
         consider_logical_flow(ctx, chassis_index, lflow, local_datapaths,
                               chassis, &dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
                               &conj_id_ofs, addr_sets, port_groups,
@@ -428,10 +433,11 @@ consider_neighbor_flow(struct controller_ctx *ctx,
  * southbound database. */
 static void
 add_neighbor_flows(struct controller_ctx *ctx,
+                   const struct sbrec_mac_binding_table *mac_binding_table,
                    struct hmap *flow_table)
 {
     const struct sbrec_mac_binding *b;
-    SBREC_MAC_BINDING_FOR_EACH (b, ctx->ovnsb_idl) {
+    SBREC_MAC_BINDING_TABLE_FOR_EACH (b, mac_binding_table) {
         consider_neighbor_flow(ctx, b, flow_table);
     }
 }
@@ -440,6 +446,10 @@ add_neighbor_flows(struct controller_ctx *ctx,
  * into OpenFlow flows.  See ovn-architecture(7) for more information. */
 void
 lflow_run(struct controller_ctx *ctx,
+          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 chassis_index *chassis_index,
           const struct hmap *local_datapaths,
@@ -453,10 +463,11 @@ lflow_run(struct controller_ctx *ctx,
 {
     COVERAGE_INC(lflow_run);
 
-    add_logical_flows(ctx, chassis_index, local_datapaths, chassis, addr_sets,
-                      port_groups, active_tunnels, local_lport_ids,
-                      flow_table, group_table, meter_table);
-    add_neighbor_flows(ctx, flow_table);
+    add_logical_flows(ctx, dhcp_options_table, dhcpv6_options_table,
+                      logical_flow_table, chassis_index, local_datapaths,
+                      chassis, addr_sets, port_groups, active_tunnels,
+                      local_lport_ids, flow_table, group_table, meter_table);
+    add_neighbor_flows(ctx, mac_binding_table, flow_table);
 }
 
 void
diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
index 14d960179816..7e081d72126a 100644
--- a/ovn/controller/lflow.h
+++ b/ovn/controller/lflow.h
@@ -40,6 +40,10 @@ struct controller_ctx;
 struct ovn_extend_table;
 struct hmap;
 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;
@@ -63,6 +67,10 @@ struct uuid;
 
 void lflow_init(void);
 void lflow_run(struct controller_ctx *,
+               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 chassis_index *,
                const struct hmap *local_datapaths,
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index ec22688e4fef..30f6fbb892c2 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -72,8 +72,9 @@ static unixctl_cb_func inject_pkt;
 
 #define CONTROLLER_LOOP_STOPWATCH_NAME "ovn-controller-flow-generation"
 
-static void update_probe_interval(struct controller_ctx *,
-                                  const char *ovnsb_remote);
+static void update_probe_interval(const struct ovsrec_open_vswitch_table *,
+                                  const char *ovnsb_remote,
+                                  struct ovsdb_idl *ovnsb_idl);
 static char *parse_options(int argc, char *argv[]);
 OVS_NO_RETURN static void usage(void);
 
@@ -94,11 +95,12 @@ get_local_datapath(const struct hmap *local_datapaths, 
uint32_t tunnel_key)
 }
 
 const struct sbrec_chassis *
-get_chassis(struct ovsdb_idl *ovnsb_idl, const char *chassis_id)
+get_chassis(const struct sbrec_chassis_table *chassis_table,
+            const char *chassis_id)
 {
     const struct sbrec_chassis *chassis_rec;
 
-    SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
+    SBREC_CHASSIS_TABLE_FOR_EACH (chassis_rec, chassis_table) {
         if (!strcmp(chassis_rec->name, chassis_id)) {
             break;
         }
@@ -122,10 +124,10 @@ get_tunnel_type(const char *name)
 }
 
 const struct ovsrec_bridge *
-get_bridge(struct ovsdb_idl *ovs_idl, const char *br_name)
+get_bridge(const struct ovsrec_bridge_table *bridge_table, const char *br_name)
 {
     const struct ovsrec_bridge *br;
-    OVSREC_BRIDGE_FOR_EACH (br, ovs_idl) {
+    OVSREC_BRIDGE_TABLE_FOR_EACH (br, bridge_table) {
         if (!strcmp(br->name, br_name)) {
             return br;
         }
@@ -251,10 +253,12 @@ create_br_int(struct controller_ctx *ctx,
 }
 
 static const struct ovsrec_bridge *
-get_br_int(struct controller_ctx *ctx)
+get_br_int(struct controller_ctx *ctx,
+           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_first(ctx->ovs_idl);
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
     if (!cfg) {
         return NULL;
     }
@@ -262,8 +266,7 @@ get_br_int(struct controller_ctx *ctx)
     const char *br_int_name = smap_get_def(&cfg->external_ids, "ovn-bridge",
                                            DEFAULT_BRIDGE_NAME);
 
-    const struct ovsrec_bridge *br;
-    br = get_bridge(ctx->ovs_idl, br_int_name);
+    const struct ovsrec_bridge *br = get_bridge(bridge_table, br_int_name);
     if (!br) {
         return create_br_int(ctx, cfg, br_int_name);
     }
@@ -271,9 +274,10 @@ get_br_int(struct controller_ctx *ctx)
 }
 
 static const char *
-get_chassis_id(const struct ovsdb_idl *ovs_idl)
+get_chassis_id(const struct ovsrec_open_vswitch_table *ovs_table)
 {
-    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
+    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) {
@@ -287,10 +291,11 @@ get_chassis_id(const struct ovsdb_idl *ovs_idl)
 /* Iterate address sets in the southbound database.  Create and update the
  * corresponding symtab entries as necessary. */
 static void
-addr_sets_init(struct controller_ctx *ctx, struct shash *addr_sets)
+addr_sets_init(const struct sbrec_address_set_table *address_set_table,
+               struct shash *addr_sets)
 {
     const struct sbrec_address_set *as;
-    SBREC_ADDRESS_SET_FOR_EACH (as, ctx->ovnsb_idl) {
+    SBREC_ADDRESS_SET_TABLE_FOR_EACH (as, address_set_table) {
         expr_const_sets_add(addr_sets, as->name,
                             (const char *const *) as->addresses,
                             as->n_addresses, true);
@@ -300,10 +305,11 @@ addr_sets_init(struct controller_ctx *ctx, struct shash 
*addr_sets)
 /* Iterate port groups in the southbound database.  Create and update the
  * corresponding symtab entries as necessary. */
 static void
-port_groups_init(struct controller_ctx *ctx, struct shash *port_groups)
+port_groups_init(const struct sbrec_port_group_table *port_group_table,
+                 struct shash *port_groups)
 {
     const struct sbrec_port_group *pg;
-    SBREC_PORT_GROUP_FOR_EACH (pg, ctx->ovnsb_idl) {
+    SBREC_PORT_GROUP_TABLE_FOR_EACH (pg, port_group_table) {
         expr_const_sets_add(port_groups, pg->name,
                             (const char *const *) pg->ports,
                             pg->n_ports, false);
@@ -311,9 +317,9 @@ port_groups_init(struct controller_ctx *ctx, struct shash 
*port_groups)
 }
 
 static void
-update_ssl_config(const struct ovsdb_idl *ovs_idl)
+update_ssl_config(const struct ovsrec_ssl_table *ssl_table)
 {
-    const struct ovsrec_ssl *ssl = ovsrec_ssl_first(ovs_idl);
+    const struct ovsrec_ssl *ssl = ovsrec_ssl_table_first(ssl_table);
 
     if (ssl) {
         stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
@@ -334,7 +340,7 @@ get_ovnsb_remote(struct ovsdb_idl *ovs_idl)
         if (cfg) {
             const char *remote = smap_get(&cfg->external_ids, "ovn-remote");
             if (remote) {
-                update_ssl_config(ovs_idl);
+                update_ssl_config(ovsrec_ssl_table_get(ovs_idl));
                 return xstrdup(remote);
             }
         }
@@ -467,11 +473,12 @@ commit_ct_zones(const struct ovsrec_bridge *br_int,
 }
 
 static void
-restore_ct_zones(struct ovsdb_idl *ovs_idl,
+restore_ct_zones(const struct ovsrec_bridge_table *bridge_table,
+                 const struct ovsrec_open_vswitch_table *ovs_table,
                  struct simap *ct_zones, unsigned long *ct_zone_bitmap)
 {
     const struct ovsrec_open_vswitch *cfg;
-    cfg = ovsrec_open_vswitch_first(ovs_idl);
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
     if (!cfg) {
         return;
     }
@@ -480,7 +487,7 @@ restore_ct_zones(struct ovsdb_idl *ovs_idl,
                                            DEFAULT_BRIDGE_NAME);
 
     const struct ovsrec_bridge *br_int;
-    br_int = get_bridge(ovs_idl, br_int_name);
+    br_int = get_bridge(bridge_table, br_int_name);
     if (!br_int) {
         /* If the integration bridge hasn't been defined, assume that
          * any existing ct-zone definitions aren't valid. */
@@ -505,9 +512,10 @@ restore_ct_zones(struct ovsdb_idl *ovs_idl,
 }
 
 static int64_t
-get_nb_cfg(struct ovsdb_idl *idl)
+get_nb_cfg(const struct sbrec_sb_global_table *sb_global_table)
 {
-    const struct sbrec_sb_global *sb = sbrec_sb_global_first(idl);
+    const struct sbrec_sb_global *sb
+        = sbrec_sb_global_table_first(sb_global_table);
     return sb ? sb->nb_cfg : 0;
 }
 
@@ -648,7 +656,9 @@ main(int argc, char *argv[])
     unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)];
     memset(ct_zone_bitmap, 0, sizeof ct_zone_bitmap);
     bitmap_set1(ct_zone_bitmap, 0); /* Zone 0 is reserved. */
-    restore_ct_zones(ovs_idl_loop.idl, &ct_zones, ct_zone_bitmap);
+    restore_ct_zones(ovsrec_bridge_table_get(ovs_idl_loop.idl),
+                     ovsrec_open_vswitch_table_get(ovs_idl_loop.idl),
+                     &ct_zones, ct_zone_bitmap);
     unixctl_command_register("ct-zone-list", "", 0, 0,
                              ct_zone_list, &ct_zones);
 
@@ -677,9 +687,10 @@ main(int argc, char *argv[])
             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
         };
 
-        update_probe_interval(&ctx, ovnsb_remote);
+        update_probe_interval(ovsrec_open_vswitch_table_get(ctx.ovs_idl),
+                              ovnsb_remote, ctx.ovnsb_idl);
 
-        update_ssl_config(ctx.ovs_idl);
+        update_ssl_config(ovsrec_ssl_table_get(ctx.ovs_idl));
 
         /* Contains "struct local_datapath" nodes. */
         struct hmap local_datapaths = HMAP_INITIALIZER(&local_datapaths);
@@ -695,34 +706,55 @@ main(int argc, char *argv[])
         struct sset local_lport_ids = SSET_INITIALIZER(&local_lport_ids);
         struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels);
 
-        const struct ovsrec_bridge *br_int = get_br_int(&ctx);
-        const char *chassis_id = get_chassis_id(ctx.ovs_idl);
+        const struct ovsrec_bridge *br_int
+            = get_br_int(&ctx, ovsrec_bridge_table_get(ctx.ovs_idl),
+                         ovsrec_open_vswitch_table_get(ctx.ovs_idl));
+        const char *chassis_id
+            = get_chassis_id(ovsrec_open_vswitch_table_get(ctx.ovs_idl));
 
         struct chassis_index chassis_index;
-
-        chassis_index_init(&chassis_index, ctx.ovnsb_idl);
+        chassis_index_init(sbrec_chassis_table_get(ctx.ovnsb_idl),
+                           &chassis_index);
 
         const struct sbrec_chassis *chassis = NULL;
         if (chassis_id) {
-            chassis = chassis_run(&ctx, chassis_id, br_int);
-            encaps_run(&ctx, br_int, chassis_id);
+            chassis = chassis_run(&ctx,
+                                  ovsrec_open_vswitch_table_get(ctx.ovs_idl),
+                                  sbrec_chassis_table_get(ctx.ovnsb_idl),
+                                  chassis_id, br_int);
+            encaps_run(&ctx,
+                       ovsrec_bridge_table_get(ctx.ovs_idl), br_int,
+                       sbrec_chassis_table_get(ctx.ovnsb_idl), chassis_id);
             bfd_calculate_active_tunnels(br_int, &active_tunnels);
-            binding_run(&ctx, br_int, chassis,
+            binding_run(&ctx,
+                        ovsrec_port_table_get(ctx.ovs_idl),
+                        ovsrec_qos_table_get(ctx.ovs_idl),
+                        sbrec_port_binding_table_get(ctx.ovnsb_idl),
+                        br_int, chassis,
                         &chassis_index, &active_tunnels, &local_datapaths,
                         &local_lports, &local_lport_ids);
         }
         if (br_int && chassis) {
             struct shash addr_sets = SHASH_INITIALIZER(&addr_sets);
-            addr_sets_init(&ctx, &addr_sets);
+            addr_sets_init(sbrec_address_set_table_get(ctx.ovnsb_idl),
+                           &addr_sets);
             struct shash port_groups = SHASH_INITIALIZER(&port_groups);
-            port_groups_init(&ctx, &port_groups);
+            port_groups_init(sbrec_port_group_table_get(ctx.ovnsb_idl),
+                             &port_groups);
 
-            patch_run(&ctx, br_int, chassis);
+            patch_run(&ctx,
+                      ovsrec_bridge_table_get(ctx.ovs_idl),
+                      ovsrec_open_vswitch_table_get(ctx.ovs_idl),
+                      ovsrec_port_table_get(ctx.ovs_idl),
+                      sbrec_port_binding_table_get(ctx.ovnsb_idl),
+                      br_int, chassis);
 
             enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int,
                                                          &pending_ct_zones);
 
-            pinctrl_run(&ctx, br_int, chassis, &chassis_index,
+            pinctrl_run(&ctx, sbrec_dns_table_get(ctx.ovnsb_idl),
+                        sbrec_mac_binding_table_get(ctx.ovnsb_idl),
+                        br_int, chassis, &chassis_index,
                         &local_datapaths, &active_tunnels);
             update_ct_zones(&local_lports, &local_datapaths, &ct_zones,
                             ct_zone_bitmap, &pending_ct_zones);
@@ -734,26 +766,38 @@ main(int argc, char *argv[])
                     commit_ct_zones(br_int, &pending_ct_zones);
 
                     struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
-                    lflow_run(&ctx, chassis,
+                    lflow_run(&ctx,
+                              sbrec_dhcp_options_table_get(ctx.ovnsb_idl),
+                              sbrec_dhcpv6_options_table_get(ctx.ovnsb_idl),
+                              sbrec_logical_flow_table_get(ctx.ovnsb_idl),
+                              sbrec_mac_binding_table_get(ctx.ovnsb_idl),
+                              chassis,
                               &chassis_index, &local_datapaths, &addr_sets,
                               &port_groups, &active_tunnels, &local_lport_ids,
                               &flow_table, &group_table, &meter_table);
 
                     if (chassis_id) {
-                        bfd_run(&ctx, br_int, chassis, &local_datapaths,
+                        bfd_run(&ctx,
+                                ovsrec_interface_table_get(ctx.ovs_idl),
+                                br_int, chassis, &local_datapaths,
                                 &chassis_index);
                     }
-                    physical_run(&ctx, mff_ovn_geneve,
-                                 br_int, chassis, &ct_zones,
-                                 &local_datapaths, &local_lports,
-                                 &chassis_index, &active_tunnels,
-                                 &flow_table);
+                    physical_run(
+                        &ctx,
+                        sbrec_multicast_group_table_get(ctx.ovnsb_idl),
+                        sbrec_port_binding_table_get(ctx.ovnsb_idl),
+                        mff_ovn_geneve,
+                        br_int, chassis, &ct_zones,
+                        &local_datapaths, &local_lports,
+                        &chassis_index, &active_tunnels,
+                        &flow_table);
 
                     stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME,
                                    time_msec());
 
                     ofctrl_put(&flow_table, &pending_ct_zones,
-                               get_nb_cfg(ctx.ovnsb_idl));
+                               get_nb_cfg(sbrec_sb_global_table_get(
+                                              ctx.ovnsb_idl)));
 
                     hmap_destroy(&flow_table);
                 }
@@ -850,14 +894,25 @@ main(int argc, char *argv[])
             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
         };
 
-        const struct ovsrec_bridge *br_int = get_br_int(&ctx);
-        const char *chassis_id = get_chassis_id(ctx.ovs_idl);
+        const struct ovsrec_bridge_table *bridge_table
+            = ovsrec_bridge_table_get(ctx.ovs_idl);
+        const struct ovsrec_open_vswitch_table *ovs_table
+            = ovsrec_open_vswitch_table_get(ctx.ovs_idl);
+
+        const struct sbrec_chassis_table *chassis_table
+            = sbrec_chassis_table_get(ctx.ovnsb_idl);
+        const struct sbrec_port_binding_table *port_binding_table
+            = sbrec_port_binding_table_get(ctx.ovnsb_idl);
+
+        const struct ovsrec_bridge *br_int = get_br_int(&ctx, bridge_table,
+                                                        ovs_table);
+        const char *chassis_id = get_chassis_id(ovs_table);
         const struct sbrec_chassis *chassis
-            = chassis_id ? get_chassis(ctx.ovnsb_idl, chassis_id) : NULL;
+            = chassis_id ? get_chassis(chassis_table, chassis_id) : NULL;
 
         /* 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, chassis);
+        done = binding_cleanup(&ctx, port_binding_table, chassis);
         done = chassis_cleanup(&ctx, chassis) && done;
         done = encaps_cleanup(&ctx, br_int) && done;
         if (done) {
@@ -1024,10 +1079,12 @@ inject_pkt(struct unixctl_conn *conn, int argc 
OVS_UNUSED,
 /* Get the desired SB probe timer from the OVS database and configure it into
  * the SB database. */
 static void
-update_probe_interval(struct controller_ctx *ctx, const char *ovnsb_remote)
+update_probe_interval(const struct ovsrec_open_vswitch_table *ovs_table,
+                      const char *ovnsb_remote,
+                      struct ovsdb_idl *ovnsb_idl)
 {
     const struct ovsrec_open_vswitch *cfg
-        = ovsrec_open_vswitch_first(ctx->ovs_idl);
+        = ovsrec_open_vswitch_table_first(ovs_table);
     int interval = -1;
     if (cfg) {
         interval = smap_get_int(&cfg->external_ids,
@@ -1040,5 +1097,5 @@ update_probe_interval(struct controller_ctx *ctx, const 
char *ovnsb_remote)
                    : 0;
     }
 
-    ovsdb_idl_set_probe_interval(ctx->ovnsb_idl, interval);
+    ovsdb_idl_set_probe_interval(ovnsb_idl, interval);
 }
diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h
index 6617b0c1616f..7a172a7879bd 100644
--- a/ovn/controller/ovn-controller.h
+++ b/ovn/controller/ovn-controller.h
@@ -20,6 +20,8 @@
 #include "simap.h"
 #include "ovn/lib/ovn-sb-idl.h"
 
+struct ovsrec_bridge_table;
+
 /* Linux supports a maximum of 64K zones, which seems like a fine default. */
 #define MAX_CT_ZONES 65535
 
@@ -73,10 +75,10 @@ struct local_datapath {
 struct local_datapath *get_local_datapath(const struct hmap *,
                                           uint32_t tunnel_key);
 
-const struct ovsrec_bridge *get_bridge(struct ovsdb_idl *,
+const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table *,
                                        const char *br_name);
 
-const struct sbrec_chassis *get_chassis(struct ovsdb_idl *,
+const struct sbrec_chassis *get_chassis(const struct sbrec_chassis_table *,
                                         const char *chassis_id);
 
 /* Must be a bit-field ordered from most-preferred (higher number) to
diff --git a/ovn/controller/patch.c b/ovn/controller/patch.c
index d0cdd315cb52..2e747e95595e 100644
--- a/ovn/controller/patch.c
+++ b/ovn/controller/patch.c
@@ -99,7 +99,7 @@ create_patch_port(struct controller_ctx *ctx,
 }
 
 static void
-remove_port(struct controller_ctx *ctx,
+remove_port(const struct ovsrec_bridge_table *bridge_table,
             const struct ovsrec_port *port)
 {
     const struct ovsrec_bridge *bridge;
@@ -107,7 +107,7 @@ remove_port(struct controller_ctx *ctx,
     /* We know the port we want to delete, but we have to find the bridge its
      * on to do so.  Note this only runs on a config change that should be
      * pretty rare. */
-    OVSREC_BRIDGE_FOR_EACH (bridge, ctx->ovs_idl) {
+    OVSREC_BRIDGE_TABLE_FOR_EACH (bridge, bridge_table) {
         size_t i;
         for (i = 0; i < bridge->n_ports; i++) {
             if (bridge->ports[i] != port) {
@@ -134,6 +134,9 @@ remove_port(struct controller_ctx *ctx,
  * already existed from 'existing_ports'. */
 static void
 add_bridge_mappings(struct controller_ctx *ctx,
+                    const struct ovsrec_bridge_table *bridge_table,
+                    const struct ovsrec_open_vswitch_table *ovs_table,
+                    const struct sbrec_port_binding_table *port_binding_table,
                     const struct ovsrec_bridge *br_int,
                     struct shash *existing_ports,
                     const struct sbrec_chassis *chassis)
@@ -141,7 +144,7 @@ add_bridge_mappings(struct controller_ctx *ctx,
     /* Get ovn-bridge-mappings. */
     const char *mappings_cfg = "";
     const struct ovsrec_open_vswitch *cfg;
-    cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
+    cfg = ovsrec_open_vswitch_table_first(ovs_table);
     if (cfg) {
         mappings_cfg = smap_get(&cfg->external_ids, "ovn-bridge-mappings");
         if (!mappings_cfg || !mappings_cfg[0]) {
@@ -164,7 +167,7 @@ add_bridge_mappings(struct controller_ctx *ctx,
             break;
         }
 
-        ovs_bridge = get_bridge(ctx->ovs_idl, bridge);
+        ovs_bridge = get_bridge(bridge_table, bridge);
         if (!ovs_bridge) {
             VLOG_WARN("Bridge '%s' not found for network '%s'",
                     bridge, network);
@@ -176,7 +179,7 @@ add_bridge_mappings(struct controller_ctx *ctx,
     free(start);
 
     const struct sbrec_port_binding *binding;
-    SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
+    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding, port_binding_table) {
         const char *patch_port_id;
         if (!strcmp(binding->type, "localnet")) {
             patch_port_id = "ovn-localnet-port";
@@ -223,7 +226,12 @@ add_bridge_mappings(struct controller_ctx *ctx,
 }
 
 void
-patch_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
+patch_run(struct controller_ctx *ctx,
+          const struct ovsrec_bridge_table *bridge_table,
+          const struct ovsrec_open_vswitch_table *ovs_table,
+          const struct ovsrec_port_table *port_table,
+          const struct sbrec_port_binding_table *port_binding_table,
+          const struct ovsrec_bridge *br_int,
           const struct sbrec_chassis *chassis)
 {
     if (!ctx->ovs_idl_txn) {
@@ -238,7 +246,7 @@ patch_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
      * leaving useless ports on upgrade. */
     struct shash existing_ports = SHASH_INITIALIZER(&existing_ports);
     const struct ovsrec_port *port;
-    OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
+    OVSREC_PORT_TABLE_FOR_EACH (port, port_table) {
         if (smap_get(&port->external_ids, "ovn-localnet-port")
             || smap_get(&port->external_ids, "ovn-l2gateway-port")
             || smap_get(&port->external_ids, "ovn-l3gateway-port")
@@ -250,7 +258,8 @@ patch_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
     /* Create in the database any patch ports that should exist.  Remove from
      * 'existing_ports' any patch ports that do exist in the database and
      * should be there. */
-    add_bridge_mappings(ctx, br_int, &existing_ports, chassis);
+    add_bridge_mappings(ctx, bridge_table, ovs_table, port_binding_table,
+                        br_int, &existing_ports, chassis);
 
     /* Now 'existing_ports' only still contains patch ports that exist in the
      * database but shouldn't.  Delete them from the database. */
@@ -258,7 +267,7 @@ patch_run(struct controller_ctx *ctx, const struct 
ovsrec_bridge *br_int,
     SHASH_FOR_EACH_SAFE (port_node, port_next_node, &existing_ports) {
         port = port_node->data;
         shash_delete(&existing_ports, port_node);
-        remove_port(ctx, port);
+        remove_port(bridge_table, port);
     }
     shash_destroy(&existing_ports);
 }
diff --git a/ovn/controller/patch.h b/ovn/controller/patch.h
index bcc89b60bb86..601f5bf06e8d 100644
--- a/ovn/controller/patch.h
+++ b/ovn/controller/patch.h
@@ -25,9 +25,18 @@
 struct controller_ctx;
 struct hmap;
 struct ovsrec_bridge;
+struct ovsrec_bridge_table;
+struct ovsrec_open_vswitch_table;
+struct ovsrec_port_table;
+struct sbrec_port_binding_table;
 struct sbrec_chassis;
 
-void patch_run(struct controller_ctx *, const struct ovsrec_bridge *br_int,
+void patch_run(struct controller_ctx *,
+               const struct ovsrec_bridge_table *,
+               const struct ovsrec_open_vswitch_table *,
+               const struct ovsrec_port_table *,
+               const struct sbrec_port_binding_table *,
+               const struct ovsrec_bridge *br_int,
                const struct sbrec_chassis *);
 
 #endif /* ovn/patch.h */
diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 6d62678d3337..2efe73219d89 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -867,7 +867,10 @@ update_ofports(struct simap *old, struct simap *new)
 }
 
 void
-physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
+physical_run(struct controller_ctx *ctx,
+             const struct sbrec_multicast_group_table *multicast_group_table,
+             const struct sbrec_port_binding_table *port_binding_table,
+             enum mf_field_id mff_ovn_geneve,
              const struct ovsrec_bridge *br_int,
              const struct sbrec_chassis *chassis,
              const struct simap *ct_zones,
@@ -995,7 +998,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id 
mff_ovn_geneve,
     /* Set up flows in table 0 for physical-to-logical translation and in table
      * 64 for logical-to-physical translation. */
     const struct sbrec_port_binding *binding;
-    SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
+    SBREC_PORT_BINDING_TABLE_FOR_EACH (binding, port_binding_table) {
         consider_port_binding(ctx, mff_ovn_geneve, ct_zones,
                               chassis_index, active_tunnels,
                               local_datapaths, binding, chassis,
@@ -1006,7 +1009,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id 
mff_ovn_geneve,
     const struct sbrec_multicast_group *mc;
     struct ofpbuf remote_ofpacts;
     ofpbuf_init(&remote_ofpacts, 0);
-    SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
+    SBREC_MULTICAST_GROUP_TABLE_FOR_EACH (mc, multicast_group_table) {
         consider_mc_group(mff_ovn_geneve, ct_zones, local_datapaths, chassis,
                           mc, &ofpacts, &remote_ofpacts, flow_table);
     }
@@ -1062,7 +1065,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id 
mff_ovn_geneve,
             continue;
         }
 
-        SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
+        SBREC_PORT_BINDING_TABLE_FOR_EACH (binding, port_binding_table) {
             struct match match = MATCH_CATCHALL_INITIALIZER;
 
             if (!binding->chassis ||
diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h
index 92a6e26616ea..288cefb2899b 100644
--- a/ovn/controller/physical.h
+++ b/ovn/controller/physical.h
@@ -27,13 +27,15 @@
 
 #include "openvswitch/meta-flow.h"
 
+struct chassis_index;
 struct controller_ctx;
 struct hmap;
 struct ovsdb_idl;
 struct ovsrec_bridge;
 struct simap;
+struct sbrec_multicast_group_table;
+struct sbrec_port_binding_table;
 struct sset;
-struct chassis_index;
 
 /* OVN Geneve option information.
  *
@@ -43,7 +45,10 @@ struct chassis_index;
 #define OVN_GENEVE_LEN 4
 
 void physical_register_ovs_idl(struct ovsdb_idl *);
-void physical_run(struct controller_ctx *, enum mf_field_id mff_ovn_geneve,
+void physical_run(struct controller_ctx *,
+                  const struct sbrec_multicast_group_table *,
+                  const struct sbrec_port_binding_table *,
+                  enum mf_field_id mff_ovn_geneve,
                   const struct ovsrec_bridge *br_int,
                   const struct sbrec_chassis *chassis,
                   const struct simap *ct_zones,
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index 435b436c2743..a6be76889a5b 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -66,7 +66,8 @@ static void pinctrl_handle_put_mac_binding(const struct flow 
*md,
                                            bool is_arp);
 static void init_put_mac_bindings(void);
 static void destroy_put_mac_bindings(void);
-static void run_put_mac_bindings(struct controller_ctx *);
+static void run_put_mac_bindings(struct controller_ctx *,
+                                 const struct sbrec_mac_binding_table *);
 static void wait_put_mac_bindings(struct controller_ctx *);
 static void flush_put_mac_bindings(void);
 
@@ -856,9 +857,9 @@ put_be32(struct ofpbuf *buf, ovs_be32 x)
 
 static void
 pinctrl_handle_dns_lookup(
+    const struct sbrec_dns_table *dns_table,
     struct dp_packet *pkt_in, struct ofputil_packet_in *pin,
-    struct ofpbuf *userdata, struct ofpbuf *continuation,
-    struct controller_ctx *ctx)
+    struct ofpbuf *userdata, struct ofpbuf *continuation)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     enum ofp_version version = rconn_get_version(swconn);
@@ -951,7 +952,7 @@ pinctrl_handle_dns_lookup(
     uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata);
     const struct sbrec_dns *sbrec_dns;
     const char *answer_ips = NULL;
-    SBREC_DNS_FOR_EACH(sbrec_dns, ctx->ovnsb_idl) {
+    SBREC_DNS_TABLE_FOR_EACH (sbrec_dns, dns_table) {
         for (size_t i = 0; i < sbrec_dns->n_datapaths; i++) {
             if (sbrec_dns->datapaths[i]->tunnel_key == dp_key) {
                 answer_ips = smap_get(&sbrec_dns->records,
@@ -1109,7 +1110,8 @@ exit:
 }
 
 static void
-process_packet_in(const struct ofp_header *msg, struct controller_ctx *ctx)
+process_packet_in(const struct ofp_header *msg,
+                  const struct sbrec_dns_table *dns_table)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
@@ -1173,7 +1175,8 @@ process_packet_in(const struct ofp_header *msg, struct 
controller_ctx *ctx)
         break;
 
     case ACTION_OPCODE_DNS_LOOKUP:
-        pinctrl_handle_dns_lookup(&packet, &pin, &userdata, &continuation, 
ctx);
+        pinctrl_handle_dns_lookup(dns_table,
+                                  &packet, &pin, &userdata, &continuation);
         break;
 
     case ACTION_OPCODE_LOG:
@@ -1207,8 +1210,8 @@ process_packet_in(const struct ofp_header *msg, struct 
controller_ctx *ctx)
 }
 
 static void
-pinctrl_recv(const struct ofp_header *oh, enum ofptype type,
-             struct controller_ctx *ctx)
+pinctrl_recv(const struct sbrec_dns_table *dns_table,
+             const struct ofp_header *oh, enum ofptype type)
 {
     if (type == OFPTYPE_ECHO_REQUEST) {
         queue_msg(ofputil_encode_echo_reply(oh));
@@ -1220,7 +1223,7 @@ pinctrl_recv(const struct ofp_header *oh, enum ofptype 
type,
         config.miss_send_len = UINT16_MAX;
         set_switch_config(swconn, &config);
     } else if (type == OFPTYPE_PACKET_IN) {
-        process_packet_in(oh, ctx);
+        process_packet_in(oh, dns_table);
     } else {
         if (VLOG_IS_DBG_ENABLED()) {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
@@ -1235,6 +1238,8 @@ pinctrl_recv(const struct ofp_header *oh, enum ofptype 
type,
 
 void
 pinctrl_run(struct controller_ctx *ctx,
+            const struct sbrec_dns_table *dns_table,
+            const struct sbrec_mac_binding_table *mac_binding_table,
             const struct ovsrec_bridge *br_int,
             const struct sbrec_chassis *chassis,
             const struct chassis_index *chassis_index,
@@ -1271,11 +1276,11 @@ pinctrl_run(struct controller_ctx *ctx,
         enum ofptype type;
 
         ofptype_decode(&type, oh);
-        pinctrl_recv(oh, type, ctx);
+        pinctrl_recv(dns_table, oh, type);
         ofpbuf_delete(msg);
     }
 
-    run_put_mac_bindings(ctx);
+    run_put_mac_bindings(ctx, mac_binding_table);
     send_garp_run(ctx, br_int, chassis, chassis_index, local_datapaths,
                   active_tunnels);
     send_ipv6_ras(ctx, local_datapaths);
@@ -1686,6 +1691,7 @@ pinctrl_handle_put_mac_binding(const struct flow *md,
 
 static void
 run_put_mac_binding(struct controller_ctx *ctx,
+                    const struct sbrec_mac_binding_table *mac_binding_table,
                     const struct put_mac_binding *pmb)
 {
     if (time_msec() > pmb->timestamp + 1000) {
@@ -1713,7 +1719,7 @@ run_put_mac_binding(struct controller_ctx *ctx,
      *
      * XXX This is not very efficient. */
     const struct sbrec_mac_binding *b;
-    SBREC_MAC_BINDING_FOR_EACH (b, ctx->ovnsb_idl) {
+    SBREC_MAC_BINDING_TABLE_FOR_EACH (b, mac_binding_table) {
         if (!strcmp(b->logical_port, pb->logical_port)
             && !strcmp(b->ip, pmb->ip_s)) {
             if (strcmp(b->mac, mac_string)) {
@@ -1732,7 +1738,8 @@ run_put_mac_binding(struct controller_ctx *ctx,
 }
 
 static void
-run_put_mac_bindings(struct controller_ctx *ctx)
+run_put_mac_bindings(struct controller_ctx *ctx,
+                     const struct sbrec_mac_binding_table *mac_binding_table)
 {
     if (!ctx->ovnsb_idl_txn) {
         return;
@@ -1740,7 +1747,7 @@ run_put_mac_bindings(struct controller_ctx *ctx)
 
     const struct put_mac_binding *pmb;
     HMAP_FOR_EACH (pmb, hmap_node, &put_mac_bindings) {
-        run_put_mac_binding(ctx, pmb);
+        run_put_mac_binding(ctx, mac_binding_table, pmb);
     }
     flush_put_mac_bindings();
 }
diff --git a/ovn/controller/pinctrl.h b/ovn/controller/pinctrl.h
index 56920e8c8587..a2518ebcdaec 100644
--- a/ovn/controller/pinctrl.h
+++ b/ovn/controller/pinctrl.h
@@ -28,9 +28,13 @@ struct hmap;
 struct lport_index;
 struct ovsrec_bridge;
 struct sbrec_chassis;
+struct sbrec_dns_table;
+struct sbrec_mac_binding_table;
 
 void pinctrl_init(void);
 void pinctrl_run(struct controller_ctx *,
+                 const struct sbrec_dns_table *,
+                 const struct sbrec_mac_binding_table *,
                  const struct ovsrec_bridge *, const struct sbrec_chassis *,
                  const struct chassis_index *,
                  const struct hmap *local_datapaths,
diff --git a/ovn/lib/chassis-index.c b/ovn/lib/chassis-index.c
index ae65375f0a6e..5ead32a4b118 100644
--- a/ovn/lib/chassis-index.c
+++ b/ovn/lib/chassis-index.c
@@ -42,13 +42,13 @@ chassis_lookup_by_name(const struct chassis_index 
*chassis_index,
 }
 
 void
-chassis_index_init(struct chassis_index *chassis_index,
-                   struct ovsdb_idl *sb_idl)
+chassis_index_init(const struct sbrec_chassis_table *chassis_table,
+                   struct chassis_index *chassis_index)
 {
     hmap_init(&chassis_index->by_name);
 
     const struct sbrec_chassis *chassis;
-    SBREC_CHASSIS_FOR_EACH (chassis, sb_idl) {
+    SBREC_CHASSIS_TABLE_FOR_EACH (chassis, chassis_table) {
         if (!chassis->name) {
             continue;
         }
diff --git a/ovn/lib/chassis-index.h b/ovn/lib/chassis-index.h
index a490cbb780f4..59b3de7d4532 100644
--- a/ovn/lib/chassis-index.h
+++ b/ovn/lib/chassis-index.h
@@ -22,7 +22,7 @@ struct chassis_index {
     struct hmap by_name;
 };
 
-struct ovsdb_idl;
+struct sbrec_chassis_table;
 
 /* Finds and returns the chassis with the given 'name', or NULL if no such
  * chassis exists. */
@@ -31,8 +31,8 @@ chassis_lookup_by_name(const struct chassis_index 
*chassis_index,
                        const char *name);
 
 /* Initializes the chassis index out of the ovsdb_idl to SBDB */
-void chassis_index_init(struct chassis_index *chassis_index,
-                        struct ovsdb_idl *sb_idl);
+void chassis_index_init(const struct sbrec_chassis_table *,
+                        struct chassis_index *chassis_index);
 
 /* Free a chassis index from memory */
 void chassis_index_destroy(struct chassis_index *chassis_index);
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 0e06776add91..151e64873aab 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -7217,7 +7217,8 @@ main(int argc, char *argv[])
         struct chassis_index chassis_index;
         bool destroy_chassis_index = false;
         if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {
-            chassis_index_init(&chassis_index, ctx.ovnsb_idl);
+            chassis_index_init(sbrec_chassis_table_get(ovnsb_idl_loop.idl),
+                               &chassis_index);
             destroy_chassis_index = true;
 
             ovnnb_db_run(&ctx, &chassis_index, &ovnsb_idl_loop);
diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 80715dfea1a7..5a675ebba24b 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -238,6 +238,18 @@ extern "C" {
         print("\nextern struct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % 
(structName, structName.upper()))
 
         print('''
+const struct %(s)s_table *%(s)s_table_get(const struct ovsdb_idl *);
+const struct %(s)s *%(s)s_table_first(const struct %(s)s_table *);
+
+#define %(S)s_TABLE_FOR_EACH(ROW, TABLE) \\
+        for ((ROW) = %(s)s_table_first(TABLE); \\
+             (ROW); \\
+             (ROW) = %(s)s_next(ROW))
+#define %(S)s_TABLE_FOR_EACH_SAFE(ROW, NEXT, TABLE) \\
+        for ((ROW) = %(s)s_table_first(TABLE); \\
+             (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\
+             (ROW) = (NEXT))
+
 const struct %(s)s *%(s)s_get_for_uuid(const struct ovsdb_idl *, const struct 
uuid *);
 const struct %(s)s *%(s)s_first(const struct ovsdb_idl *);
 const struct %(s)s *%(s)s_next(const struct %(s)s *);
@@ -435,6 +447,21 @@ static struct %(s)s *
         print("")
         print("/* %s table. */" % (tableName))
 
+        print('''
+const struct %(s)s_table *
+%(s)s_table_get(const struct ovsdb_idl *idl)
+{
+    return (const struct %(s)s_table *) idl;
+}
+
+const struct %(s)s *
+%(s)s_table_first(const struct %(s)s_table *table)
+{
+    const struct ovsdb_idl *idl = (const struct ovsdb_idl *) table;
+    return %(s)s_first(idl);
+}
+''' % {'s': structName})
+
         # Parse functions.
         for columnName, column in sorted_columns(table):
             if 'parse' in column.extensions:
-- 
2.16.1

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

Reply via email to