diff mbox series

[ovs-dev,ovn,3/4] Refactor lflow functions to take two context argument - lflow_ctx_in and lflow_ctx_out.

Message ID 20200124110339.1555623-1-numans@ovn.org
State Accepted
Headers show
Series [ovs-dev,ovn,1/4] Make is_switch() in lflow.c a util function | expand

Commit Message

Numan Siddique Jan. 24, 2020, 11:03 a.m. UTC
From: Numan Siddique <numans@ovn.org>

Presently most of the lflow_*() functions called from ovn-controller.c
takes lots of arguments. This patch adds 'struct lflow_ctx_in' and
'struct lflow_ctx_out'  to simplify the code a bit. This also reduces some
code in ovn-controller.c and improves readability to some degree.

No functional changes are introduced in this patch.

Signed-off-by: Numan Siddique <numans@ovn.org>
---
 controller/lflow.c          | 294 +++++++++++-------------------------
 controller/lflow.h          |  91 ++++-------
 controller/ovn-controller.c | 251 ++++++++++++------------------
 3 files changed, 220 insertions(+), 416 deletions(-)

Comments

Han Zhou Jan. 28, 2020, 7:39 a.m. UTC | #1
On Fri, Jan 24, 2020 at 3:04 AM <numans@ovn.org> wrote:
>
> From: Numan Siddique <numans@ovn.org>
>
> Presently most of the lflow_*() functions called from ovn-controller.c
> takes lots of arguments. This patch adds 'struct lflow_ctx_in' and
> 'struct lflow_ctx_out'  to simplify the code a bit. This also reduces some
> code in ovn-controller.c and improves readability to some degree.
>
> No functional changes are introduced in this patch.
>
> Signed-off-by: Numan Siddique <numans@ovn.org>
> ---
>  controller/lflow.c          | 294 +++++++++++-------------------------
>  controller/lflow.h          |  91 ++++-------
>  controller/ovn-controller.c | 251 ++++++++++++------------------
>  3 files changed, 220 insertions(+), 416 deletions(-)
>
> diff --git a/controller/lflow.c b/controller/lflow.c
> index 3ddb0571e..95bc65735 100644
> --- a/controller/lflow.c
> +++ b/controller/lflow.c
> @@ -61,27 +61,14 @@ struct condition_aux {
>      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,
> -    bool delete_expr_from_cache,
> -    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,
> -    struct hmap *lflow_expr_cache);
> +static bool
> +consider_logical_flow(const struct sbrec_logical_flow *lflow,
> +                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> +                      struct hmap *nd_ra_opts,
> +                      bool delete_expr_from_cache,
> +                      struct lflow_ctx_in *l_ctx_in,
> +                      struct lflow_ctx_out *l_ctx_out,
> +                      struct controller_event_options
*controller_event_opts);

I suggest to move the controller_event_opts parameter above, because it is
an input parameter. Probably better before the "delete_expr_from_cache".
Otherwise:

Acked-by: Han Zhou <hzhou@ovn.org>

>
>  static bool
>  lookup_port_cb(const void *aux_, const char *port_name, unsigned int
*portp)
> @@ -331,31 +318,16 @@ lflow_expr_destroy(struct hmap *lflow_expr_cache)
>
>  /* 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,
> -    struct hmap *lflow_expr_cache)
> +add_logical_flows(struct lflow_ctx_in *l_ctx_in,
> +                  struct lflow_ctx_out *l_ctx_out)
>  {
>      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)
{
> +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> +                                       l_ctx_in->dhcp_options_table) {
>          dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
>                       dhcp_opt_row->type);
>      }
> @@ -363,7 +335,7 @@ add_logical_flows(
>
>      const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
>      SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> -                                         dhcpv6_options_table) {
> +                                         l_ctx_in->dhcpv6_options_table)
{
>         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
dhcpv6_opt_row->code,
>                      dhcpv6_opt_row->type);
>      }
> @@ -374,16 +346,11 @@ add_logical_flows(
>      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,
false,
> -                                   flow_table, group_table, meter_table,
> -                                   lfrr, conj_id_ofs, lflow_expr_cache))
{
> +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow,
l_ctx_in->logical_flow_table) {
> +        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> +                                   &nd_ra_opts, false,
> +                                   l_ctx_in, l_ctx_out,
> +                                   &controller_event_opts)) {
>              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));
> @@ -397,24 +364,8 @@ add_logical_flows(
>  }
>
>  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,
> -    struct hmap *lflow_expr_cache)
> +lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in,
> +                           struct lflow_ctx_out *l_ctx_out)
>  {
>      bool ret = true;
>      const struct sbrec_logical_flow *lflow;
> @@ -422,7 +373,8 @@ lflow_handle_changed_flows(
>      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)
{
> +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> +                                       l_ctx_in->dhcp_options_table) {
>          dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
>                       dhcp_opt_row->type);
>      }
> @@ -430,7 +382,7 @@ lflow_handle_changed_flows(
>
>      const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
>      SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> -                                         dhcpv6_options_table) {
> +                                         l_ctx_in->dhcpv6_options_table)
{
>         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
dhcpv6_opt_row->code,
>                      dhcpv6_opt_row->type);
>      }
> @@ -441,27 +393,24 @@ lflow_handle_changed_flows(
>      /* 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) {
> +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
> +
l_ctx_in->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);
> +            ofctrl_remove_flows(l_ctx_out->flow_table,
&lflow->header_.uuid);
>              /* Delete entries from lflow resource reference. */
> -            lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> -
> -            /* Delete the expr cache for this lflow. */
> -            struct lflow_expr *le = lflow_expr_get(lflow_expr_cache,
lflow);
> -            if (le) {
> -                lflow_expr_delete(lflow_expr_cache, le);
> -            }
> +            lflow_resource_destroy_lflow(l_ctx_out->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) {
> +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
> +
l_ctx_in->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
> @@ -469,21 +418,17 @@ lflow_handle_changed_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);
> +                ofctrl_remove_flows(l_ctx_out->flow_table,
> +                                    &lflow->header_.uuid);
>                  /* Delete entries from lflow resource reference. */
> -                lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> +                lflow_resource_destroy_lflow(l_ctx_out->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,
true,
> -                                       flow_table, group_table,
meter_table,
> -                                       lfrr, conj_id_ofs,
lflow_expr_cache)) {
> +            if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> +                                       &nd_ra_opts, true, l_ctx_in,
l_ctx_out,
> +                                       &controller_event_opts)) {
>                  ret = false;
>                  break;
>              }
> @@ -497,30 +442,14 @@ lflow_handle_changed_flows(
>  }
>
>  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,
> -    struct hmap *lflow_expr_cache,
> -    bool *changed)
> +lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name,
> +                         struct lflow_ctx_in *l_ctx_in,
> +                         struct lflow_ctx_out *l_ctx_out,
> +                         bool *changed)
>  {
> -    struct ref_lflow_node *rlfn =
ref_lflow_lookup(&lfrr->ref_lflow_table,
> -                                                   ref_type, ref_name);
> +    struct ref_lflow_node *rlfn =
> +        ref_lflow_lookup(&l_ctx_out->lfrr->ref_lflow_table, ref_type,
> +                         ref_name);
>      if (!rlfn) {
>          *changed = false;
>          return true;
> @@ -530,7 +459,7 @@ lflow_handle_changed_ref(
>      *changed = false;
>      bool ret = true;
>
> -    hmap_remove(&lfrr->ref_lflow_table, &rlfn->node);
> +    hmap_remove(&l_ctx_out->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
> @@ -539,19 +468,21 @@ lflow_handle_changed_ref(
>       * 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);
> +        lflow_resource_destroy_lflow(l_ctx_out->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)
{
> +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> +                                       l_ctx_in->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) {
> +    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH(dhcpv6_opt_row,
> +                                        l_ctx_in->dhcpv6_options_table) {
>         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
dhcpv6_opt_row->code,
>                      dhcpv6_opt_row->type);
>      }
> @@ -565,7 +496,7 @@ lflow_handle_changed_ref(
>      /* 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,
> +
 sbrec_logical_flow_table_get_for_uuid(l_ctx_in->logical_flow_table,
>                                                    &lrln->lflow_uuid);
>          if (!lflow) {
>              VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d,"
> @@ -578,17 +509,11 @@ lflow_handle_changed_ref(
>                   " 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, true,
> -                                   flow_table, group_table, meter_table,
> -                                   lfrr, conj_id_ofs, lflow_expr_cache))
{
> +        ofctrl_remove_flows(l_ctx_out->flow_table, &lrln->lflow_uuid);
> +
> +        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> +                                   &nd_ra_opts, true, l_ctx_in,
l_ctx_out,
> +                                   &controller_event_opts)) {
>              ret = false;
>              break;
>          }
> @@ -620,27 +545,13 @@ update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t
n_conjs)
>  }
>
>  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,
> -    bool delete_expr_from_cache,
> -    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,
> -    struct hmap *lflow_expr_cache)
> +consider_logical_flow(const struct sbrec_logical_flow *lflow,
> +                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> +                      struct hmap *nd_ra_opts,
> +                      bool delete_expr_from_cache,
> +                      struct lflow_ctx_in *l_ctx_in,
> +                      struct lflow_ctx_out *l_ctx_out,
> +                      struct controller_event_options
*controller_event_opts)
>  {
>      /* Determine translation of logical table IDs to physical table IDs.
*/
>      bool ingress = !strcmp(lflow->pipeline, "ingress");
> @@ -651,7 +562,7 @@ consider_logical_flow(
>                   UUID_ARGS(&lflow->header_.uuid));
>          return true;
>      }
> -    if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) {
> +    if (!get_local_datapath(l_ctx_in->local_datapaths, ldp->tunnel_key))
{
>          VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip",
>                   UUID_ARGS(&lflow->header_.uuid));
>          return true;
> @@ -702,27 +613,28 @@ consider_logical_flow(
>
>      struct sset addr_sets_ref = SSET_INITIALIZER(&addr_sets_ref);
>      struct sset port_groups_ref = SSET_INITIALIZER(&port_groups_ref);
> -    struct lflow_expr *le = lflow_expr_get(lflow_expr_cache, lflow);
> +    struct lflow_expr *le = lflow_expr_get(l_ctx_out->lflow_expr_cache,
lflow);
>      if (le) {
>          if (delete_expr_from_cache) {
> -            lflow_expr_delete(lflow_expr_cache, le);
> +            lflow_expr_delete(l_ctx_out->lflow_expr_cache, le);
>          } else {
>              expr = le->expr;
>          }
>      }
>
>      if (!expr) {
> -        expr = expr_parse_string(lflow->match, &symtab, addr_sets,
port_groups,
> -                                &addr_sets_ref, &port_groups_ref,
&error);
> +        expr = expr_parse_string(lflow->match, &symtab,
l_ctx_in->addr_sets,
> +                                 l_ctx_in->port_groups, &addr_sets_ref,
> +                                 &port_groups_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);
> +            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_ADDRSET,
> +                               addr_set_name, &lflow->header_.uuid);
>          }
>          const char *port_group_name;
>          SSET_FOR_EACH (port_group_name, &port_groups_ref) {
> -            lflow_resource_add(lfrr, REF_TYPE_PORTGROUP, port_group_name,
> -                            &lflow->header_.uuid);
> +            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_PORTGROUP,
> +                               port_group_name, &lflow->header_.uuid);
>          }
>          sset_destroy(&addr_sets_ref);
>          sset_destroy(&port_groups_ref);
> @@ -748,13 +660,13 @@ consider_logical_flow(
>          expr = expr_simplify(expr);
>          expr = expr_normalize(expr);
>
> -        lflow_expr_add(lflow_expr_cache, lflow, expr);
> +        lflow_expr_add(l_ctx_out->lflow_expr_cache, lflow, expr);
>      }
>
>      struct condition_aux cond_aux = {
> -        .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
> -        .chassis = chassis,
> -        .active_tunnels = active_tunnels,
> +        .sbrec_port_binding_by_name =
l_ctx_in->sbrec_port_binding_by_name,
> +        .chassis = l_ctx_in->chassis,
> +        .active_tunnels = l_ctx_in->active_tunnels,
>      };
>
>      expr = expr_clone(expr);
> @@ -762,8 +674,8 @@ consider_logical_flow(
>
>      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,
> +            = l_ctx_in->sbrec_multicast_group_by_name_datapath,
> +        .sbrec_port_binding_by_name =
l_ctx_in->sbrec_port_binding_by_name,
>          .dp = lflow->logical_datapath
>      };
>      uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
> @@ -788,8 +700,8 @@ consider_logical_flow(
>          .tunnel_ofport = tunnel_ofport_cb,
>          .aux = &aux,
>          .is_switch = datapath_is_switch(ldp),
> -        .group_table = group_table,
> -        .meter_table = meter_table,
> +        .group_table = l_ctx_out->group_table,
> +        .meter_table = l_ctx_out->meter_table,
>          .lflow_uuid = lflow->header_.uuid,
>
>          .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
> @@ -809,7 +721,7 @@ consider_logical_flow(
>          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;
> +            m->match.flow.conj_id += *l_ctx_out->conj_id_ofs;
>          }
>          if (datapath_is_switch(ldp)) {
>              unsigned int reg_index
> @@ -819,7 +731,7 @@ consider_logical_flow(
>                  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)) {
> +                if (!sset_contains(l_ctx_in->local_lport_ids, buf)) {
>                      VLOG_DBG("lflow "UUID_FMT
>                               " port %s in match is not local, skip",
>                               UUID_ARGS(&lflow->header_.uuid),
> @@ -829,7 +741,7 @@ consider_logical_flow(
>              }
>          }
>          if (!m->n) {
> -            ofctrl_add_flow(flow_table, ptable, lflow->priority,
> +            ofctrl_add_flow(l_ctx_out->flow_table, ptable,
lflow->priority,
>                              lflow->header_.uuid.parts[0], &m->match,
&ofpacts,
>                              &lflow->header_.uuid);
>          } else {
> @@ -842,12 +754,13 @@ consider_logical_flow(
>                  struct ofpact_conjunction *dst;
>
>                  dst = ofpact_put_CONJUNCTION(&conj);
> -                dst->id = src->id + *conj_id_ofs;
> +                dst->id = src->id + *l_ctx_out->conj_id_ofs;
>                  dst->clause = src->clause;
>                  dst->n_clauses = src->n_clauses;
>              }
>
> -            ofctrl_add_or_append_flow(flow_table, ptable,
lflow->priority, 0,
> +            ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable,
> +                                      lflow->priority, 0,
>                                        &m->match, &conj,
&lflow->header_.uuid);
>              ofpbuf_uninit(&conj);
>          }
> @@ -856,7 +769,7 @@ consider_logical_flow(
>      /* Clean up. */
>      expr_matches_destroy(&matches);
>      ofpbuf_uninit(&ofpacts);
> -    return update_conj_id_ofs(conj_id_ofs, n_conjs);
> +    return update_conj_id_ofs(l_ctx_out->conj_id_ofs, n_conjs);
>  }
>
>  static void
> @@ -965,7 +878,6 @@ lflow_handle_changed_neighbors(
>      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. */
> @@ -995,35 +907,13 @@ lflow_handle_changed_neighbors(
>  /* 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,
> -          struct hmap *lflow_expr_cache)
> +lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out)
>  {
>      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, lflow_expr_cache);
> -    add_neighbor_flows(sbrec_port_binding_by_name, mac_binding_table,
> -                       flow_table);
> +    add_logical_flows(l_ctx_in, l_ctx_out);
> +    add_neighbor_flows(l_ctx_in->sbrec_port_binding_by_name,
> +                       l_ctx_in->mac_binding_table,
l_ctx_out->flow_table);
>  }
>
>  void
> diff --git a/controller/lflow.h b/controller/lflow.h
> index a2fa087f8..8433cc0c6 100644
> --- a/controller/lflow.h
> +++ b/controller/lflow.h
> @@ -115,67 +115,38 @@ 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,
> -               struct hmap *lflow_expr_cache);
> -
> -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,
> -    struct hmap *lflow_expr_cache);
> -
> -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,
> -    struct hmap *lflow_expr_cache,
> -    bool *changed);
> +struct lflow_ctx_in {
> +    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_datapath_binding_table *dp_binding_table;
> +    const struct sbrec_mac_binding_table *mac_binding_table;
> +    const struct sbrec_logical_flow_table *logical_flow_table;
> +    const struct sbrec_multicast_group_table *mc_group_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 lflow_ctx_out {
> +    struct ovn_desired_flow_table *flow_table;
> +    struct ovn_extend_table *group_table;
> +    struct ovn_extend_table *meter_table;
> +    struct lflow_resource_ref *lfrr;
> +    struct hmap *lflow_expr_cache;
> +    uint32_t *conj_id_ofs;
> +};
> +
> +void lflow_init(void);
> +void lflow_run(struct lflow_ctx_in *, struct lflow_ctx_out *);
> +bool lflow_handle_changed_flows(struct lflow_ctx_in *, struct
lflow_ctx_out *);
> +bool lflow_handle_changed_ref(enum ref_type, const char *ref_name,
> +                              struct lflow_ctx_in *, struct
lflow_ctx_out *,
> +                              bool *changed);
>  void lflow_handle_changed_neighbors(
>      struct ovsdb_idl_index *sbrec_port_binding_by_name,
>      const struct sbrec_mac_binding_table *,
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 9b88f88fe..efd5d258d 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -1214,6 +1214,85 @@ struct ed_type_flow_output {
>      struct hmap lflow_expr_cache;
>  };
>
> +static void init_lflow_ctx(struct engine_node *node,
> +                           struct ed_type_runtime_data *rt_data,
> +                           struct ed_type_flow_output *fo,
> +                           struct lflow_ctx_in *l_ctx_in,
> +                           struct lflow_ctx_out *l_ctx_out)
> +{
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> +        engine_ovsdb_node_get_index(
> +                engine_get_input("SB_port_binding", node),
> +                "name");
> +
> +    struct ovsdb_idl_index *sbrec_mc_group_by_name_dp =
> +        engine_ovsdb_node_get_index(
> +                engine_get_input("SB_multicast_group", node),
> +                "name_datapath");
> +
> +    struct sbrec_dhcp_options_table *dhcp_table =
> +        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> +            engine_get_input("SB_dhcp_options", node));
> +
> +    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> +        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> +            engine_get_input("SB_dhcpv6_options", node));
> +
> +    struct sbrec_mac_binding_table *mac_binding_table =
> +        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
> +            engine_get_input("SB_mac_binding", node));
> +
> +    struct sbrec_logical_flow_table *logical_flow_table =
> +        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> +            engine_get_input("SB_logical_flow", node));
> +
> +    struct sbrec_multicast_group_table *multicast_group_table =
> +        (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
> +            engine_get_input("SB_multicast_group", node));
> +
> +    const char *chassis_id = chassis_get_id();
> +    const struct sbrec_chassis *chassis = NULL;
> +    struct ovsdb_idl_index *sbrec_chassis_by_name =
> +        engine_ovsdb_node_get_index(
> +                engine_get_input("SB_chassis", node),
> +                "name");
> +    if (chassis_id) {
> +        chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
chassis_id);
> +    }
> +
> +    ovs_assert(chassis);
> +
> +    struct ed_type_addr_sets *as_data =
> +        engine_get_input_data("addr_sets", node);
> +    struct shash *addr_sets = &as_data->addr_sets;
> +
> +    struct ed_type_port_groups *pg_data =
> +        engine_get_input_data("port_groups", node);
> +    struct shash *port_groups = &pg_data->port_groups;
> +
> +    l_ctx_in->sbrec_multicast_group_by_name_datapath =
> +        sbrec_mc_group_by_name_dp;
> +    l_ctx_in->sbrec_port_binding_by_name = sbrec_port_binding_by_name;
> +    l_ctx_in->dhcp_options_table  = dhcp_table;
> +    l_ctx_in->dhcpv6_options_table = dhcpv6_table;
> +    l_ctx_in->mac_binding_table = mac_binding_table;
> +    l_ctx_in->logical_flow_table = logical_flow_table;
> +    l_ctx_in->mc_group_table = multicast_group_table;
> +    l_ctx_in->chassis = chassis;
> +    l_ctx_in->local_datapaths = &rt_data->local_datapaths;
> +    l_ctx_in->addr_sets = addr_sets;
> +    l_ctx_in->port_groups = port_groups;
> +    l_ctx_in->active_tunnels = &rt_data->active_tunnels;
> +    l_ctx_in->local_lport_ids = &rt_data->local_lport_ids;
> +
> +    l_ctx_out->flow_table = &fo->flow_table;
> +    l_ctx_out->group_table = &fo->group_table;
> +    l_ctx_out->meter_table = &fo->meter_table;
> +    l_ctx_out->lfrr = &fo->lflow_resource_ref;
> +    l_ctx_out->lflow_expr_cache = &fo->lflow_expr_cache;
> +    l_ctx_out->conj_id_ofs = &fo->conj_id_ofs;
> +}
> +
>  static void *
>  en_flow_output_init(struct engine_node *node OVS_UNUSED,
>                      struct engine_arg *arg OVS_UNUSED)
> @@ -1247,7 +1326,6 @@ en_flow_output_run(struct engine_node *node, void
*data)
>          engine_get_input_data("runtime_data", node);
>      struct hmap *local_datapaths = &rt_data->local_datapaths;
>      struct sset *local_lports = &rt_data->local_lports;
> -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
>      struct sset *active_tunnels = &rt_data->active_tunnels;
>
>      struct ed_type_ct_zones *ct_zones_data =
> @@ -1271,13 +1349,6 @@ en_flow_output_run(struct engine_node *node, void
*data)
>          engine_ovsdb_node_get_index(
>                  engine_get_input("SB_chassis", node),
>                  "name");
> -    struct ed_type_addr_sets *as_data =
> -        engine_get_input_data("addr_sets", node);
> -    struct shash *addr_sets = &as_data->addr_sets;
> -
> -    struct ed_type_port_groups *pg_data =
> -        engine_get_input_data("port_groups", node);
> -    struct shash *port_groups = &pg_data->port_groups;
>
>      const struct sbrec_chassis *chassis = NULL;
>      if (chassis_id) {
> @@ -1303,43 +1374,16 @@ en_flow_output_run(struct engine_node *node, void
*data)
>          lflow_resource_clear(lfrr);
>      }
>
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_multicast_group", node),
> -                "name_datapath");
> -
>      struct ovsdb_idl_index *sbrec_port_binding_by_name =
>          engine_ovsdb_node_get_index(
>                  engine_get_input("SB_port_binding", node),
>                  "name");
>
> -    struct sbrec_dhcp_options_table *dhcp_table =
> -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcp_options", node));
> -
> -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcpv6_options", node));
> -
> -    struct sbrec_logical_flow_table *logical_flow_table =
> -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_logical_flow", node));
> -
> -    struct sbrec_mac_binding_table *mac_binding_table =
> -        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_mac_binding", node));
> -
>      *conj_id_ofs = 1;
> -    lflow_run(sbrec_multicast_group_by_name_datapath,
> -              sbrec_port_binding_by_name,
> -              dhcp_table, dhcpv6_table,
> -              logical_flow_table,
> -              mac_binding_table,
> -              chassis, local_datapaths, addr_sets,
> -              port_groups, active_tunnels, local_lport_ids,
> -              flow_table, group_table, meter_table, lfrr,
> -              conj_id_ofs,
> -              &fo->lflow_expr_cache);
> +    struct lflow_ctx_in l_ctx_in;
> +    struct lflow_ctx_out l_ctx_out;
> +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
> +    lflow_run(&l_ctx_in, &l_ctx_out);
>
>      struct sbrec_multicast_group_table *multicast_group_table =
>          (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
> @@ -1371,17 +1415,6 @@ flow_output_sb_logical_flow_handler(struct
engine_node *node, void *data)
>  {
>      struct ed_type_runtime_data *rt_data =
>          engine_get_input_data("runtime_data", node);
> -    struct hmap *local_datapaths = &rt_data->local_datapaths;
> -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
> -    struct sset *active_tunnels = &rt_data->active_tunnels;
> -    struct ed_type_addr_sets *as_data =
> -        engine_get_input_data("addr_sets", node);
> -    struct shash *addr_sets = &as_data->addr_sets;
> -
> -    struct ed_type_port_groups *pg_data =
> -        engine_get_input_data("port_groups", node);
> -    struct shash *port_groups = &pg_data->port_groups;
> -
>      struct ovsrec_open_vswitch_table *ovs_table =
>          (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
>              engine_get_input("OVS_open_vswitch", node));
> @@ -1389,58 +1422,14 @@ flow_output_sb_logical_flow_handler(struct
engine_node *node, void *data)
>          (struct ovsrec_bridge_table *)EN_OVSDB_GET(
>              engine_get_input("OVS_bridge", node));
>      const struct ovsrec_bridge *br_int = get_br_int(bridge_table,
ovs_table);
> -    const char *chassis_id = chassis_get_id();
> -
> -    struct ovsdb_idl_index *sbrec_chassis_by_name =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_chassis", node),
> -                "name");
> -
> -    const struct sbrec_chassis *chassis = NULL;
> -    if (chassis_id) {
> -        chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
chassis_id);
> -    }
> -
> -    ovs_assert(br_int && chassis);
> +    ovs_assert(br_int);
>
>      struct ed_type_flow_output *fo = data;
> -    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
> -    struct ovn_extend_table *group_table = &fo->group_table;
> -    struct ovn_extend_table *meter_table = &fo->meter_table;
> -    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
> -    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
> -
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_multicast_group", node),
> -                "name_datapath");
> -
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_port_binding", node),
> -                "name");
> -
> -    struct sbrec_dhcp_options_table *dhcp_table =
> -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcp_options", node));
> -
> -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcpv6_options", node));
> -
> -    struct sbrec_logical_flow_table *logical_flow_table =
> -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_logical_flow", node));
> +    struct lflow_ctx_in l_ctx_in;
> +    struct lflow_ctx_out l_ctx_out;
> +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
>
> -    bool handled = lflow_handle_changed_flows(
> -              sbrec_multicast_group_by_name_datapath,
> -              sbrec_port_binding_by_name,
> -              dhcp_table, dhcpv6_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, &fo->lflow_expr_cache);
> +    bool handled = lflow_handle_changed_flows(&l_ctx_in, &l_ctx_out);
>
>      engine_set_node_state(node, EN_UPDATED);
>      return handled;
> @@ -1628,17 +1617,12 @@ _flow_output_resource_ref_handler(struct
engine_node *node, void *data,
>  {
>      struct ed_type_runtime_data *rt_data =
>          engine_get_input_data("runtime_data", node);
> -    struct hmap *local_datapaths = &rt_data->local_datapaths;
> -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
> -    struct sset *active_tunnels = &rt_data->active_tunnels;
>
>      struct ed_type_addr_sets *as_data =
>          engine_get_input_data("addr_sets", node);
> -    struct shash *addr_sets = &as_data->addr_sets;
>
>      struct ed_type_port_groups *pg_data =
>          engine_get_input_data("port_groups", node);
> -    struct shash *port_groups = &pg_data->port_groups;
>
>      struct ovsrec_open_vswitch_table *ovs_table =
>          (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
> @@ -1661,33 +1645,10 @@ _flow_output_resource_ref_handler(struct
engine_node *node, void *data,
>      ovs_assert(br_int && chassis);
>
>      struct ed_type_flow_output *fo = data;
> -    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
> -    struct ovn_extend_table *group_table = &fo->group_table;
> -    struct ovn_extend_table *meter_table = &fo->meter_table;
> -    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
> -    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
>
> -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_multicast_group", node),
> -                "name_datapath");
> -
> -    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> -        engine_ovsdb_node_get_index(
> -                engine_get_input("SB_port_binding", node),
> -                "name");
> -
> -    struct sbrec_dhcp_options_table *dhcp_table =
> -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcp_options", node));
> -
> -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_dhcpv6_options", node));
> -
> -    struct sbrec_logical_flow_table *logical_flow_table =
> -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> -            engine_get_input("SB_logical_flow", node));
> +    struct lflow_ctx_in l_ctx_in;
> +    struct lflow_ctx_out l_ctx_out;
> +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
>
>      bool changed;
>      const char *ref_name;
> @@ -1718,14 +1679,8 @@ _flow_output_resource_ref_handler(struct
engine_node *node, void *data,
>
>
>      SSET_FOR_EACH (ref_name, deleted) {
> -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> -                    sbrec_multicast_group_by_name_datapath,
> -                    sbrec_port_binding_by_name,dhcp_table,
> -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> +                                      &l_ctx_out, &changed)) {
>              return false;
>          }
>          if (changed) {
> @@ -1733,14 +1688,8 @@ _flow_output_resource_ref_handler(struct
engine_node *node, void *data,
>          }
>      }
>      SSET_FOR_EACH (ref_name, updated) {
> -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> -                    sbrec_multicast_group_by_name_datapath,
> -                    sbrec_port_binding_by_name,dhcp_table,
> -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> +                                      &l_ctx_out, &changed)) {
>              return false;
>          }
>          if (changed) {
> @@ -1748,14 +1697,8 @@ _flow_output_resource_ref_handler(struct
engine_node *node, void *data,
>          }
>      }
>      SSET_FOR_EACH (ref_name, new) {
> -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> -                    sbrec_multicast_group_by_name_datapath,
> -                    sbrec_port_binding_by_name,dhcp_table,
> -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> +                                      &l_ctx_out, &changed)) {
>              return false;
>          }
>          if (changed) {
> --
> 2.24.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Numan Siddique Jan. 28, 2020, 2:22 p.m. UTC | #2
On Tue, Jan 28, 2020 at 1:11 PM Han Zhou <hzhou@ovn.org> wrote:
>
> On Fri, Jan 24, 2020 at 3:04 AM <numans@ovn.org> wrote:
> >
> > From: Numan Siddique <numans@ovn.org>
> >
> > Presently most of the lflow_*() functions called from ovn-controller.c
> > takes lots of arguments. This patch adds 'struct lflow_ctx_in' and
> > 'struct lflow_ctx_out'  to simplify the code a bit. This also reduces some
> > code in ovn-controller.c and improves readability to some degree.
> >
> > No functional changes are introduced in this patch.
> >
> > Signed-off-by: Numan Siddique <numans@ovn.org>
> > ---
> >  controller/lflow.c          | 294 +++++++++++-------------------------
> >  controller/lflow.h          |  91 ++++-------
> >  controller/ovn-controller.c | 251 ++++++++++++------------------
> >  3 files changed, 220 insertions(+), 416 deletions(-)
> >
> > diff --git a/controller/lflow.c b/controller/lflow.c
> > index 3ddb0571e..95bc65735 100644
> > --- a/controller/lflow.c
> > +++ b/controller/lflow.c
> > @@ -61,27 +61,14 @@ struct condition_aux {
> >      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,
> > -    bool delete_expr_from_cache,
> > -    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,
> > -    struct hmap *lflow_expr_cache);
> > +static bool
> > +consider_logical_flow(const struct sbrec_logical_flow *lflow,
> > +                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> > +                      struct hmap *nd_ra_opts,
> > +                      bool delete_expr_from_cache,
> > +                      struct lflow_ctx_in *l_ctx_in,
> > +                      struct lflow_ctx_out *l_ctx_out,
> > +                      struct controller_event_options
> *controller_event_opts);
>
> I suggest to move the controller_event_opts parameter above, because it is
> an input parameter. Probably better before the "delete_expr_from_cache".
> Otherwise:
>
> Acked-by: Han Zhou <hzhou@ovn.org>

Thanks for the review. With the below changes I applied the patches 1,
3 and 4 of this series to master.

diff --git a/controller/lflow.c b/controller/lflow.c
index 95bc65735..780aa9331 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -65,10 +65,10 @@ static bool
 consider_logical_flow(const struct sbrec_logical_flow *lflow,
                       struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
                       struct hmap *nd_ra_opts,
+                      struct controller_event_options *controller_event_opts,
                       bool delete_expr_from_cache,
                       struct lflow_ctx_in *l_ctx_in,
-                      struct lflow_ctx_out *l_ctx_out,
-                      struct controller_event_options *controller_event_opts);
+                      struct lflow_ctx_out *l_ctx_out);

 static bool
 lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
@@ -348,9 +348,8 @@ add_logical_flows(struct lflow_ctx_in *l_ctx_in,

     SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow, l_ctx_in->logical_flow_table) {
         if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
-                                   &nd_ra_opts, false,
-                                   l_ctx_in, l_ctx_out,
-                                   &controller_event_opts)) {
+                                   &nd_ra_opts, &controller_event_opts, false,
+                                   l_ctx_in, l_ctx_out)) {
             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));
@@ -427,8 +426,8 @@ lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in,
             VLOG_DBG("handle new lflow "UUID_FMT,
                      UUID_ARGS(&lflow->header_.uuid));
             if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
-                                       &nd_ra_opts, true, l_ctx_in, l_ctx_out,
-                                       &controller_event_opts)) {
+                                       &nd_ra_opts, &controller_event_opts,
+                                       true, l_ctx_in, l_ctx_out)) {
                 ret = false;
                 break;
             }
@@ -512,8 +511,8 @@ lflow_handle_changed_ref(enum ref_type ref_type,
const char *ref_name,
         ofctrl_remove_flows(l_ctx_out->flow_table, &lrln->lflow_uuid);

         if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
-                                   &nd_ra_opts, true, l_ctx_in, l_ctx_out,
-                                   &controller_event_opts)) {
+                                   &nd_ra_opts, &controller_event_opts,
+                                   true, l_ctx_in, l_ctx_out)) {
             ret = false;
             break;
         }
@@ -548,10 +547,10 @@ static bool
 consider_logical_flow(const struct sbrec_logical_flow *lflow,
                       struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
                       struct hmap *nd_ra_opts,
+                      struct controller_event_options *controller_event_opts,
                       bool delete_expr_from_cache,
                       struct lflow_ctx_in *l_ctx_in,
-                      struct lflow_ctx_out *l_ctx_out,
-                      struct controller_event_options *controller_event_opts)
+                      struct lflow_ctx_out *l_ctx_out)
 {
     /* Determine translation of logical table IDs to physical table IDs. */
     bool ingress = !strcmp(lflow->pipeline, "ingress");

>
> >
> >  static bool
> >  lookup_port_cb(const void *aux_, const char *port_name, unsigned int
> *portp)
> > @@ -331,31 +318,16 @@ lflow_expr_destroy(struct hmap *lflow_expr_cache)
> >
> >  /* 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,
> > -    struct hmap *lflow_expr_cache)
> > +add_logical_flows(struct lflow_ctx_in *l_ctx_in,
> > +                  struct lflow_ctx_out *l_ctx_out)
> >  {
> >      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)
> {
> > +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> > +                                       l_ctx_in->dhcp_options_table) {
> >          dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
> >                       dhcp_opt_row->type);
> >      }
> > @@ -363,7 +335,7 @@ add_logical_flows(
> >
> >      const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
> >      SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> > -                                         dhcpv6_options_table) {
> > +                                         l_ctx_in->dhcpv6_options_table)
> {
> >         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> >                      dhcpv6_opt_row->type);
> >      }
> > @@ -374,16 +346,11 @@ add_logical_flows(
> >      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,
> false,
> > -                                   flow_table, group_table, meter_table,
> > -                                   lfrr, conj_id_ofs, lflow_expr_cache))
> {
> > +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow,
> l_ctx_in->logical_flow_table) {
> > +        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> > +                                   &nd_ra_opts, false,
> > +                                   l_ctx_in, l_ctx_out,
> > +                                   &controller_event_opts)) {
> >              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));
> > @@ -397,24 +364,8 @@ add_logical_flows(
> >  }
> >
> >  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,
> > -    struct hmap *lflow_expr_cache)
> > +lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in,
> > +                           struct lflow_ctx_out *l_ctx_out)
> >  {
> >      bool ret = true;
> >      const struct sbrec_logical_flow *lflow;
> > @@ -422,7 +373,8 @@ lflow_handle_changed_flows(
> >      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)
> {
> > +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> > +                                       l_ctx_in->dhcp_options_table) {
> >          dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
> >                       dhcp_opt_row->type);
> >      }
> > @@ -430,7 +382,7 @@ lflow_handle_changed_flows(
> >
> >      const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
> >      SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
> > -                                         dhcpv6_options_table) {
> > +                                         l_ctx_in->dhcpv6_options_table)
> {
> >         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> >                      dhcpv6_opt_row->type);
> >      }
> > @@ -441,27 +393,24 @@ lflow_handle_changed_flows(
> >      /* 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) {
> > +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
> > +
> l_ctx_in->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);
> > +            ofctrl_remove_flows(l_ctx_out->flow_table,
> &lflow->header_.uuid);
> >              /* Delete entries from lflow resource reference. */
> > -            lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> > -
> > -            /* Delete the expr cache for this lflow. */
> > -            struct lflow_expr *le = lflow_expr_get(lflow_expr_cache,
> lflow);
> > -            if (le) {
> > -                lflow_expr_delete(lflow_expr_cache, le);
> > -            }
> > +            lflow_resource_destroy_lflow(l_ctx_out->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) {
> > +    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
> > +
> l_ctx_in->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
> > @@ -469,21 +418,17 @@ lflow_handle_changed_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);
> > +                ofctrl_remove_flows(l_ctx_out->flow_table,
> > +                                    &lflow->header_.uuid);
> >                  /* Delete entries from lflow resource reference. */
> > -                lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
> > +                lflow_resource_destroy_lflow(l_ctx_out->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,
> true,
> > -                                       flow_table, group_table,
> meter_table,
> > -                                       lfrr, conj_id_ofs,
> lflow_expr_cache)) {
> > +            if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> > +                                       &nd_ra_opts, true, l_ctx_in,
> l_ctx_out,
> > +                                       &controller_event_opts)) {
> >                  ret = false;
> >                  break;
> >              }
> > @@ -497,30 +442,14 @@ lflow_handle_changed_flows(
> >  }
> >
> >  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,
> > -    struct hmap *lflow_expr_cache,
> > -    bool *changed)
> > +lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name,
> > +                         struct lflow_ctx_in *l_ctx_in,
> > +                         struct lflow_ctx_out *l_ctx_out,
> > +                         bool *changed)
> >  {
> > -    struct ref_lflow_node *rlfn =
> ref_lflow_lookup(&lfrr->ref_lflow_table,
> > -                                                   ref_type, ref_name);
> > +    struct ref_lflow_node *rlfn =
> > +        ref_lflow_lookup(&l_ctx_out->lfrr->ref_lflow_table, ref_type,
> > +                         ref_name);
> >      if (!rlfn) {
> >          *changed = false;
> >          return true;
> > @@ -530,7 +459,7 @@ lflow_handle_changed_ref(
> >      *changed = false;
> >      bool ret = true;
> >
> > -    hmap_remove(&lfrr->ref_lflow_table, &rlfn->node);
> > +    hmap_remove(&l_ctx_out->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
> > @@ -539,19 +468,21 @@ lflow_handle_changed_ref(
> >       * 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);
> > +        lflow_resource_destroy_lflow(l_ctx_out->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)
> {
> > +    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
> > +                                       l_ctx_in->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) {
> > +    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH(dhcpv6_opt_row,
> > +                                        l_ctx_in->dhcpv6_options_table) {
> >         dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name,
> dhcpv6_opt_row->code,
> >                      dhcpv6_opt_row->type);
> >      }
> > @@ -565,7 +496,7 @@ lflow_handle_changed_ref(
> >      /* 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,
> > +
>  sbrec_logical_flow_table_get_for_uuid(l_ctx_in->logical_flow_table,
> >                                                    &lrln->lflow_uuid);
> >          if (!lflow) {
> >              VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d,"
> > @@ -578,17 +509,11 @@ lflow_handle_changed_ref(
> >                   " 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, true,
> > -                                   flow_table, group_table, meter_table,
> > -                                   lfrr, conj_id_ofs, lflow_expr_cache))
> {
> > +        ofctrl_remove_flows(l_ctx_out->flow_table, &lrln->lflow_uuid);
> > +
> > +        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
> > +                                   &nd_ra_opts, true, l_ctx_in,
> l_ctx_out,
> > +                                   &controller_event_opts)) {
> >              ret = false;
> >              break;
> >          }
> > @@ -620,27 +545,13 @@ update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t
> n_conjs)
> >  }
> >
> >  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,
> > -    bool delete_expr_from_cache,
> > -    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,
> > -    struct hmap *lflow_expr_cache)
> > +consider_logical_flow(const struct sbrec_logical_flow *lflow,
> > +                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> > +                      struct hmap *nd_ra_opts,
> > +                      bool delete_expr_from_cache,
> > +                      struct lflow_ctx_in *l_ctx_in,
> > +                      struct lflow_ctx_out *l_ctx_out,
> > +                      struct controller_event_options
> *controller_event_opts)
> >  {
> >      /* Determine translation of logical table IDs to physical table IDs.
> */
> >      bool ingress = !strcmp(lflow->pipeline, "ingress");
> > @@ -651,7 +562,7 @@ consider_logical_flow(
> >                   UUID_ARGS(&lflow->header_.uuid));
> >          return true;
> >      }
> > -    if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) {
> > +    if (!get_local_datapath(l_ctx_in->local_datapaths, ldp->tunnel_key))
> {
> >          VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip",
> >                   UUID_ARGS(&lflow->header_.uuid));
> >          return true;
> > @@ -702,27 +613,28 @@ consider_logical_flow(
> >
> >      struct sset addr_sets_ref = SSET_INITIALIZER(&addr_sets_ref);
> >      struct sset port_groups_ref = SSET_INITIALIZER(&port_groups_ref);
> > -    struct lflow_expr *le = lflow_expr_get(lflow_expr_cache, lflow);
> > +    struct lflow_expr *le = lflow_expr_get(l_ctx_out->lflow_expr_cache,
> lflow);
> >      if (le) {
> >          if (delete_expr_from_cache) {
> > -            lflow_expr_delete(lflow_expr_cache, le);
> > +            lflow_expr_delete(l_ctx_out->lflow_expr_cache, le);
> >          } else {
> >              expr = le->expr;
> >          }
> >      }
> >
> >      if (!expr) {
> > -        expr = expr_parse_string(lflow->match, &symtab, addr_sets,
> port_groups,
> > -                                &addr_sets_ref, &port_groups_ref,
> &error);
> > +        expr = expr_parse_string(lflow->match, &symtab,
> l_ctx_in->addr_sets,
> > +                                 l_ctx_in->port_groups, &addr_sets_ref,
> > +                                 &port_groups_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);
> > +            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_ADDRSET,
> > +                               addr_set_name, &lflow->header_.uuid);
> >          }
> >          const char *port_group_name;
> >          SSET_FOR_EACH (port_group_name, &port_groups_ref) {
> > -            lflow_resource_add(lfrr, REF_TYPE_PORTGROUP, port_group_name,
> > -                            &lflow->header_.uuid);
> > +            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_PORTGROUP,
> > +                               port_group_name, &lflow->header_.uuid);
> >          }
> >          sset_destroy(&addr_sets_ref);
> >          sset_destroy(&port_groups_ref);
> > @@ -748,13 +660,13 @@ consider_logical_flow(
> >          expr = expr_simplify(expr);
> >          expr = expr_normalize(expr);
> >
> > -        lflow_expr_add(lflow_expr_cache, lflow, expr);
> > +        lflow_expr_add(l_ctx_out->lflow_expr_cache, lflow, expr);
> >      }
> >
> >      struct condition_aux cond_aux = {
> > -        .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
> > -        .chassis = chassis,
> > -        .active_tunnels = active_tunnels,
> > +        .sbrec_port_binding_by_name =
> l_ctx_in->sbrec_port_binding_by_name,
> > +        .chassis = l_ctx_in->chassis,
> > +        .active_tunnels = l_ctx_in->active_tunnels,
> >      };
> >
> >      expr = expr_clone(expr);
> > @@ -762,8 +674,8 @@ consider_logical_flow(
> >
> >      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,
> > +            = l_ctx_in->sbrec_multicast_group_by_name_datapath,
> > +        .sbrec_port_binding_by_name =
> l_ctx_in->sbrec_port_binding_by_name,
> >          .dp = lflow->logical_datapath
> >      };
> >      uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
> > @@ -788,8 +700,8 @@ consider_logical_flow(
> >          .tunnel_ofport = tunnel_ofport_cb,
> >          .aux = &aux,
> >          .is_switch = datapath_is_switch(ldp),
> > -        .group_table = group_table,
> > -        .meter_table = meter_table,
> > +        .group_table = l_ctx_out->group_table,
> > +        .meter_table = l_ctx_out->meter_table,
> >          .lflow_uuid = lflow->header_.uuid,
> >
> >          .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
> > @@ -809,7 +721,7 @@ consider_logical_flow(
> >          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;
> > +            m->match.flow.conj_id += *l_ctx_out->conj_id_ofs;
> >          }
> >          if (datapath_is_switch(ldp)) {
> >              unsigned int reg_index
> > @@ -819,7 +731,7 @@ consider_logical_flow(
> >                  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)) {
> > +                if (!sset_contains(l_ctx_in->local_lport_ids, buf)) {
> >                      VLOG_DBG("lflow "UUID_FMT
> >                               " port %s in match is not local, skip",
> >                               UUID_ARGS(&lflow->header_.uuid),
> > @@ -829,7 +741,7 @@ consider_logical_flow(
> >              }
> >          }
> >          if (!m->n) {
> > -            ofctrl_add_flow(flow_table, ptable, lflow->priority,
> > +            ofctrl_add_flow(l_ctx_out->flow_table, ptable,
> lflow->priority,
> >                              lflow->header_.uuid.parts[0], &m->match,
> &ofpacts,
> >                              &lflow->header_.uuid);
> >          } else {
> > @@ -842,12 +754,13 @@ consider_logical_flow(
> >                  struct ofpact_conjunction *dst;
> >
> >                  dst = ofpact_put_CONJUNCTION(&conj);
> > -                dst->id = src->id + *conj_id_ofs;
> > +                dst->id = src->id + *l_ctx_out->conj_id_ofs;
> >                  dst->clause = src->clause;
> >                  dst->n_clauses = src->n_clauses;
> >              }
> >
> > -            ofctrl_add_or_append_flow(flow_table, ptable,
> lflow->priority, 0,
> > +            ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable,
> > +                                      lflow->priority, 0,
> >                                        &m->match, &conj,
> &lflow->header_.uuid);
> >              ofpbuf_uninit(&conj);
> >          }
> > @@ -856,7 +769,7 @@ consider_logical_flow(
> >      /* Clean up. */
> >      expr_matches_destroy(&matches);
> >      ofpbuf_uninit(&ofpacts);
> > -    return update_conj_id_ofs(conj_id_ofs, n_conjs);
> > +    return update_conj_id_ofs(l_ctx_out->conj_id_ofs, n_conjs);
> >  }
> >
> >  static void
> > @@ -965,7 +878,6 @@ lflow_handle_changed_neighbors(
> >      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. */
> > @@ -995,35 +907,13 @@ lflow_handle_changed_neighbors(
> >  /* 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,
> > -          struct hmap *lflow_expr_cache)
> > +lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out)
> >  {
> >      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, lflow_expr_cache);
> > -    add_neighbor_flows(sbrec_port_binding_by_name, mac_binding_table,
> > -                       flow_table);
> > +    add_logical_flows(l_ctx_in, l_ctx_out);
> > +    add_neighbor_flows(l_ctx_in->sbrec_port_binding_by_name,
> > +                       l_ctx_in->mac_binding_table,
> l_ctx_out->flow_table);
> >  }
> >
> >  void
> > diff --git a/controller/lflow.h b/controller/lflow.h
> > index a2fa087f8..8433cc0c6 100644
> > --- a/controller/lflow.h
> > +++ b/controller/lflow.h
> > @@ -115,67 +115,38 @@ 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,
> > -               struct hmap *lflow_expr_cache);
> > -
> > -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,
> > -    struct hmap *lflow_expr_cache);
> > -
> > -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,
> > -    struct hmap *lflow_expr_cache,
> > -    bool *changed);
> > +struct lflow_ctx_in {
> > +    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_datapath_binding_table *dp_binding_table;
> > +    const struct sbrec_mac_binding_table *mac_binding_table;
> > +    const struct sbrec_logical_flow_table *logical_flow_table;
> > +    const struct sbrec_multicast_group_table *mc_group_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 lflow_ctx_out {
> > +    struct ovn_desired_flow_table *flow_table;
> > +    struct ovn_extend_table *group_table;
> > +    struct ovn_extend_table *meter_table;
> > +    struct lflow_resource_ref *lfrr;
> > +    struct hmap *lflow_expr_cache;
> > +    uint32_t *conj_id_ofs;
> > +};
> > +
> > +void lflow_init(void);
> > +void lflow_run(struct lflow_ctx_in *, struct lflow_ctx_out *);
> > +bool lflow_handle_changed_flows(struct lflow_ctx_in *, struct
> lflow_ctx_out *);
> > +bool lflow_handle_changed_ref(enum ref_type, const char *ref_name,
> > +                              struct lflow_ctx_in *, struct
> lflow_ctx_out *,
> > +                              bool *changed);
> >  void lflow_handle_changed_neighbors(
> >      struct ovsdb_idl_index *sbrec_port_binding_by_name,
> >      const struct sbrec_mac_binding_table *,
> > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> > index 9b88f88fe..efd5d258d 100644
> > --- a/controller/ovn-controller.c
> > +++ b/controller/ovn-controller.c
> > @@ -1214,6 +1214,85 @@ struct ed_type_flow_output {
> >      struct hmap lflow_expr_cache;
> >  };
> >
> > +static void init_lflow_ctx(struct engine_node *node,
> > +                           struct ed_type_runtime_data *rt_data,
> > +                           struct ed_type_flow_output *fo,
> > +                           struct lflow_ctx_in *l_ctx_in,
> > +                           struct lflow_ctx_out *l_ctx_out)
> > +{
> > +    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> > +        engine_ovsdb_node_get_index(
> > +                engine_get_input("SB_port_binding", node),
> > +                "name");
> > +
> > +    struct ovsdb_idl_index *sbrec_mc_group_by_name_dp =
> > +        engine_ovsdb_node_get_index(
> > +                engine_get_input("SB_multicast_group", node),
> > +                "name_datapath");
> > +
> > +    struct sbrec_dhcp_options_table *dhcp_table =
> > +        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> > +            engine_get_input("SB_dhcp_options", node));
> > +
> > +    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> > +        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> > +            engine_get_input("SB_dhcpv6_options", node));
> > +
> > +    struct sbrec_mac_binding_table *mac_binding_table =
> > +        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
> > +            engine_get_input("SB_mac_binding", node));
> > +
> > +    struct sbrec_logical_flow_table *logical_flow_table =
> > +        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> > +            engine_get_input("SB_logical_flow", node));
> > +
> > +    struct sbrec_multicast_group_table *multicast_group_table =
> > +        (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
> > +            engine_get_input("SB_multicast_group", node));
> > +
> > +    const char *chassis_id = chassis_get_id();
> > +    const struct sbrec_chassis *chassis = NULL;
> > +    struct ovsdb_idl_index *sbrec_chassis_by_name =
> > +        engine_ovsdb_node_get_index(
> > +                engine_get_input("SB_chassis", node),
> > +                "name");
> > +    if (chassis_id) {
> > +        chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
> chassis_id);
> > +    }
> > +
> > +    ovs_assert(chassis);
> > +
> > +    struct ed_type_addr_sets *as_data =
> > +        engine_get_input_data("addr_sets", node);
> > +    struct shash *addr_sets = &as_data->addr_sets;
> > +
> > +    struct ed_type_port_groups *pg_data =
> > +        engine_get_input_data("port_groups", node);
> > +    struct shash *port_groups = &pg_data->port_groups;
> > +
> > +    l_ctx_in->sbrec_multicast_group_by_name_datapath =
> > +        sbrec_mc_group_by_name_dp;
> > +    l_ctx_in->sbrec_port_binding_by_name = sbrec_port_binding_by_name;
> > +    l_ctx_in->dhcp_options_table  = dhcp_table;
> > +    l_ctx_in->dhcpv6_options_table = dhcpv6_table;
> > +    l_ctx_in->mac_binding_table = mac_binding_table;
> > +    l_ctx_in->logical_flow_table = logical_flow_table;
> > +    l_ctx_in->mc_group_table = multicast_group_table;
> > +    l_ctx_in->chassis = chassis;
> > +    l_ctx_in->local_datapaths = &rt_data->local_datapaths;
> > +    l_ctx_in->addr_sets = addr_sets;
> > +    l_ctx_in->port_groups = port_groups;
> > +    l_ctx_in->active_tunnels = &rt_data->active_tunnels;
> > +    l_ctx_in->local_lport_ids = &rt_data->local_lport_ids;
> > +
> > +    l_ctx_out->flow_table = &fo->flow_table;
> > +    l_ctx_out->group_table = &fo->group_table;
> > +    l_ctx_out->meter_table = &fo->meter_table;
> > +    l_ctx_out->lfrr = &fo->lflow_resource_ref;
> > +    l_ctx_out->lflow_expr_cache = &fo->lflow_expr_cache;
> > +    l_ctx_out->conj_id_ofs = &fo->conj_id_ofs;
> > +}
> > +
> >  static void *
> >  en_flow_output_init(struct engine_node *node OVS_UNUSED,
> >                      struct engine_arg *arg OVS_UNUSED)
> > @@ -1247,7 +1326,6 @@ en_flow_output_run(struct engine_node *node, void
> *data)
> >          engine_get_input_data("runtime_data", node);
> >      struct hmap *local_datapaths = &rt_data->local_datapaths;
> >      struct sset *local_lports = &rt_data->local_lports;
> > -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
> >      struct sset *active_tunnels = &rt_data->active_tunnels;
> >
> >      struct ed_type_ct_zones *ct_zones_data =
> > @@ -1271,13 +1349,6 @@ en_flow_output_run(struct engine_node *node, void
> *data)
> >          engine_ovsdb_node_get_index(
> >                  engine_get_input("SB_chassis", node),
> >                  "name");
> > -    struct ed_type_addr_sets *as_data =
> > -        engine_get_input_data("addr_sets", node);
> > -    struct shash *addr_sets = &as_data->addr_sets;
> > -
> > -    struct ed_type_port_groups *pg_data =
> > -        engine_get_input_data("port_groups", node);
> > -    struct shash *port_groups = &pg_data->port_groups;
> >
> >      const struct sbrec_chassis *chassis = NULL;
> >      if (chassis_id) {
> > @@ -1303,43 +1374,16 @@ en_flow_output_run(struct engine_node *node, void
> *data)
> >          lflow_resource_clear(lfrr);
> >      }
> >
> > -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_multicast_group", node),
> > -                "name_datapath");
> > -
> >      struct ovsdb_idl_index *sbrec_port_binding_by_name =
> >          engine_ovsdb_node_get_index(
> >                  engine_get_input("SB_port_binding", node),
> >                  "name");
> >
> > -    struct sbrec_dhcp_options_table *dhcp_table =
> > -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcp_options", node));
> > -
> > -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> > -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcpv6_options", node));
> > -
> > -    struct sbrec_logical_flow_table *logical_flow_table =
> > -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_logical_flow", node));
> > -
> > -    struct sbrec_mac_binding_table *mac_binding_table =
> > -        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_mac_binding", node));
> > -
> >      *conj_id_ofs = 1;
> > -    lflow_run(sbrec_multicast_group_by_name_datapath,
> > -              sbrec_port_binding_by_name,
> > -              dhcp_table, dhcpv6_table,
> > -              logical_flow_table,
> > -              mac_binding_table,
> > -              chassis, local_datapaths, addr_sets,
> > -              port_groups, active_tunnels, local_lport_ids,
> > -              flow_table, group_table, meter_table, lfrr,
> > -              conj_id_ofs,
> > -              &fo->lflow_expr_cache);
> > +    struct lflow_ctx_in l_ctx_in;
> > +    struct lflow_ctx_out l_ctx_out;
> > +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
> > +    lflow_run(&l_ctx_in, &l_ctx_out);
> >
> >      struct sbrec_multicast_group_table *multicast_group_table =
> >          (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
> > @@ -1371,17 +1415,6 @@ flow_output_sb_logical_flow_handler(struct
> engine_node *node, void *data)
> >  {
> >      struct ed_type_runtime_data *rt_data =
> >          engine_get_input_data("runtime_data", node);
> > -    struct hmap *local_datapaths = &rt_data->local_datapaths;
> > -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
> > -    struct sset *active_tunnels = &rt_data->active_tunnels;
> > -    struct ed_type_addr_sets *as_data =
> > -        engine_get_input_data("addr_sets", node);
> > -    struct shash *addr_sets = &as_data->addr_sets;
> > -
> > -    struct ed_type_port_groups *pg_data =
> > -        engine_get_input_data("port_groups", node);
> > -    struct shash *port_groups = &pg_data->port_groups;
> > -
> >      struct ovsrec_open_vswitch_table *ovs_table =
> >          (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
> >              engine_get_input("OVS_open_vswitch", node));
> > @@ -1389,58 +1422,14 @@ flow_output_sb_logical_flow_handler(struct
> engine_node *node, void *data)
> >          (struct ovsrec_bridge_table *)EN_OVSDB_GET(
> >              engine_get_input("OVS_bridge", node));
> >      const struct ovsrec_bridge *br_int = get_br_int(bridge_table,
> ovs_table);
> > -    const char *chassis_id = chassis_get_id();
> > -
> > -    struct ovsdb_idl_index *sbrec_chassis_by_name =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_chassis", node),
> > -                "name");
> > -
> > -    const struct sbrec_chassis *chassis = NULL;
> > -    if (chassis_id) {
> > -        chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
> chassis_id);
> > -    }
> > -
> > -    ovs_assert(br_int && chassis);
> > +    ovs_assert(br_int);
> >
> >      struct ed_type_flow_output *fo = data;
> > -    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
> > -    struct ovn_extend_table *group_table = &fo->group_table;
> > -    struct ovn_extend_table *meter_table = &fo->meter_table;
> > -    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
> > -    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
> > -
> > -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_multicast_group", node),
> > -                "name_datapath");
> > -
> > -    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_port_binding", node),
> > -                "name");
> > -
> > -    struct sbrec_dhcp_options_table *dhcp_table =
> > -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcp_options", node));
> > -
> > -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> > -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcpv6_options", node));
> > -
> > -    struct sbrec_logical_flow_table *logical_flow_table =
> > -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_logical_flow", node));
> > +    struct lflow_ctx_in l_ctx_in;
> > +    struct lflow_ctx_out l_ctx_out;
> > +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
> >
> > -    bool handled = lflow_handle_changed_flows(
> > -              sbrec_multicast_group_by_name_datapath,
> > -              sbrec_port_binding_by_name,
> > -              dhcp_table, dhcpv6_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, &fo->lflow_expr_cache);
> > +    bool handled = lflow_handle_changed_flows(&l_ctx_in, &l_ctx_out);
> >
> >      engine_set_node_state(node, EN_UPDATED);
> >      return handled;
> > @@ -1628,17 +1617,12 @@ _flow_output_resource_ref_handler(struct
> engine_node *node, void *data,
> >  {
> >      struct ed_type_runtime_data *rt_data =
> >          engine_get_input_data("runtime_data", node);
> > -    struct hmap *local_datapaths = &rt_data->local_datapaths;
> > -    struct sset *local_lport_ids = &rt_data->local_lport_ids;
> > -    struct sset *active_tunnels = &rt_data->active_tunnels;
> >
> >      struct ed_type_addr_sets *as_data =
> >          engine_get_input_data("addr_sets", node);
> > -    struct shash *addr_sets = &as_data->addr_sets;
> >
> >      struct ed_type_port_groups *pg_data =
> >          engine_get_input_data("port_groups", node);
> > -    struct shash *port_groups = &pg_data->port_groups;
> >
> >      struct ovsrec_open_vswitch_table *ovs_table =
> >          (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
> > @@ -1661,33 +1645,10 @@ _flow_output_resource_ref_handler(struct
> engine_node *node, void *data,
> >      ovs_assert(br_int && chassis);
> >
> >      struct ed_type_flow_output *fo = data;
> > -    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
> > -    struct ovn_extend_table *group_table = &fo->group_table;
> > -    struct ovn_extend_table *meter_table = &fo->meter_table;
> > -    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
> > -    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
> >
> > -    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_multicast_group", node),
> > -                "name_datapath");
> > -
> > -    struct ovsdb_idl_index *sbrec_port_binding_by_name =
> > -        engine_ovsdb_node_get_index(
> > -                engine_get_input("SB_port_binding", node),
> > -                "name");
> > -
> > -    struct sbrec_dhcp_options_table *dhcp_table =
> > -        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcp_options", node));
> > -
> > -    struct sbrec_dhcpv6_options_table *dhcpv6_table =
> > -        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_dhcpv6_options", node));
> > -
> > -    struct sbrec_logical_flow_table *logical_flow_table =
> > -        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
> > -            engine_get_input("SB_logical_flow", node));
> > +    struct lflow_ctx_in l_ctx_in;
> > +    struct lflow_ctx_out l_ctx_out;
> > +    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
> >
> >      bool changed;
> >      const char *ref_name;
> > @@ -1718,14 +1679,8 @@ _flow_output_resource_ref_handler(struct
> engine_node *node, void *data,
> >
> >
> >      SSET_FOR_EACH (ref_name, deleted) {
> > -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> > -                    sbrec_multicast_group_by_name_datapath,
> > -                    sbrec_port_binding_by_name,dhcp_table,
> > -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> > +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> > +                                      &l_ctx_out, &changed)) {
> >              return false;
> >          }
> >          if (changed) {
> > @@ -1733,14 +1688,8 @@ _flow_output_resource_ref_handler(struct
> engine_node *node, void *data,
> >          }
> >      }
> >      SSET_FOR_EACH (ref_name, updated) {
> > -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> > -                    sbrec_multicast_group_by_name_datapath,
> > -                    sbrec_port_binding_by_name,dhcp_table,
> > -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> > +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> > +                                      &l_ctx_out, &changed)) {
> >              return false;
> >          }
> >          if (changed) {
> > @@ -1748,14 +1697,8 @@ _flow_output_resource_ref_handler(struct
> engine_node *node, void *data,
> >          }
> >      }
> >      SSET_FOR_EACH (ref_name, new) {
> > -        if (!lflow_handle_changed_ref(ref_type, ref_name,
> > -                    sbrec_multicast_group_by_name_datapath,
> > -                    sbrec_port_binding_by_name,dhcp_table,
> > -                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
> > +        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
> > +                                      &l_ctx_out, &changed)) {
> >              return false;
> >          }
> >          if (changed) {
> > --
> > 2.24.1
> >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
diff mbox series

Patch

diff --git a/controller/lflow.c b/controller/lflow.c
index 3ddb0571e..95bc65735 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -61,27 +61,14 @@  struct condition_aux {
     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,
-    bool delete_expr_from_cache,
-    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,
-    struct hmap *lflow_expr_cache);
+static bool
+consider_logical_flow(const struct sbrec_logical_flow *lflow,
+                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
+                      struct hmap *nd_ra_opts,
+                      bool delete_expr_from_cache,
+                      struct lflow_ctx_in *l_ctx_in,
+                      struct lflow_ctx_out *l_ctx_out,
+                      struct controller_event_options *controller_event_opts);
 
 static bool
 lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
@@ -331,31 +318,16 @@  lflow_expr_destroy(struct hmap *lflow_expr_cache)
 
 /* 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,
-    struct hmap *lflow_expr_cache)
+add_logical_flows(struct lflow_ctx_in *l_ctx_in,
+                  struct lflow_ctx_out *l_ctx_out)
 {
     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) {
+    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
+                                       l_ctx_in->dhcp_options_table) {
         dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
                      dhcp_opt_row->type);
     }
@@ -363,7 +335,7 @@  add_logical_flows(
 
     const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
     SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
-                                         dhcpv6_options_table) {
+                                         l_ctx_in->dhcpv6_options_table) {
        dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code,
                     dhcpv6_opt_row->type);
     }
@@ -374,16 +346,11 @@  add_logical_flows(
     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, false,
-                                   flow_table, group_table, meter_table,
-                                   lfrr, conj_id_ofs, lflow_expr_cache)) {
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow, l_ctx_in->logical_flow_table) {
+        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
+                                   &nd_ra_opts, false,
+                                   l_ctx_in, l_ctx_out,
+                                   &controller_event_opts)) {
             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));
@@ -397,24 +364,8 @@  add_logical_flows(
 }
 
 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,
-    struct hmap *lflow_expr_cache)
+lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in,
+                           struct lflow_ctx_out *l_ctx_out)
 {
     bool ret = true;
     const struct sbrec_logical_flow *lflow;
@@ -422,7 +373,8 @@  lflow_handle_changed_flows(
     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) {
+    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
+                                       l_ctx_in->dhcp_options_table) {
         dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
                      dhcp_opt_row->type);
     }
@@ -430,7 +382,7 @@  lflow_handle_changed_flows(
 
     const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
     SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
-                                         dhcpv6_options_table) {
+                                         l_ctx_in->dhcpv6_options_table) {
        dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code,
                     dhcpv6_opt_row->type);
     }
@@ -441,27 +393,24 @@  lflow_handle_changed_flows(
     /* 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) {
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
+                                               l_ctx_in->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);
+            ofctrl_remove_flows(l_ctx_out->flow_table, &lflow->header_.uuid);
             /* Delete entries from lflow resource reference. */
-            lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
-
-            /* Delete the expr cache for this lflow. */
-            struct lflow_expr *le = lflow_expr_get(lflow_expr_cache, lflow);
-            if (le) {
-                lflow_expr_delete(lflow_expr_cache, le);
-            }
+            lflow_resource_destroy_lflow(l_ctx_out->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) {
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow,
+                                               l_ctx_in->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
@@ -469,21 +418,17 @@  lflow_handle_changed_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);
+                ofctrl_remove_flows(l_ctx_out->flow_table,
+                                    &lflow->header_.uuid);
                 /* Delete entries from lflow resource reference. */
-                lflow_resource_destroy_lflow(lfrr, &lflow->header_.uuid);
+                lflow_resource_destroy_lflow(l_ctx_out->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, true,
-                                       flow_table, group_table, meter_table,
-                                       lfrr, conj_id_ofs, lflow_expr_cache)) {
+            if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
+                                       &nd_ra_opts, true, l_ctx_in, l_ctx_out,
+                                       &controller_event_opts)) {
                 ret = false;
                 break;
             }
@@ -497,30 +442,14 @@  lflow_handle_changed_flows(
 }
 
 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,
-    struct hmap *lflow_expr_cache,
-    bool *changed)
+lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name,
+                         struct lflow_ctx_in *l_ctx_in,
+                         struct lflow_ctx_out *l_ctx_out,
+                         bool *changed)
 {
-    struct ref_lflow_node *rlfn = ref_lflow_lookup(&lfrr->ref_lflow_table,
-                                                   ref_type, ref_name);
+    struct ref_lflow_node *rlfn =
+        ref_lflow_lookup(&l_ctx_out->lfrr->ref_lflow_table, ref_type,
+                         ref_name);
     if (!rlfn) {
         *changed = false;
         return true;
@@ -530,7 +459,7 @@  lflow_handle_changed_ref(
     *changed = false;
     bool ret = true;
 
-    hmap_remove(&lfrr->ref_lflow_table, &rlfn->node);
+    hmap_remove(&l_ctx_out->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
@@ -539,19 +468,21 @@  lflow_handle_changed_ref(
      * 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);
+        lflow_resource_destroy_lflow(l_ctx_out->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) {
+    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row,
+                                       l_ctx_in->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) {
+    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH(dhcpv6_opt_row,
+                                        l_ctx_in->dhcpv6_options_table) {
        dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code,
                     dhcpv6_opt_row->type);
     }
@@ -565,7 +496,7 @@  lflow_handle_changed_ref(
     /* 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,
+            sbrec_logical_flow_table_get_for_uuid(l_ctx_in->logical_flow_table,
                                                   &lrln->lflow_uuid);
         if (!lflow) {
             VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d,"
@@ -578,17 +509,11 @@  lflow_handle_changed_ref(
                  " 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, true,
-                                   flow_table, group_table, meter_table,
-                                   lfrr, conj_id_ofs, lflow_expr_cache)) {
+        ofctrl_remove_flows(l_ctx_out->flow_table, &lrln->lflow_uuid);
+
+        if (!consider_logical_flow(lflow, &dhcp_opts, &dhcpv6_opts,
+                                   &nd_ra_opts, true, l_ctx_in, l_ctx_out,
+                                   &controller_event_opts)) {
             ret = false;
             break;
         }
@@ -620,27 +545,13 @@  update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs)
 }
 
 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,
-    bool delete_expr_from_cache,
-    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,
-    struct hmap *lflow_expr_cache)
+consider_logical_flow(const struct sbrec_logical_flow *lflow,
+                      struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
+                      struct hmap *nd_ra_opts,
+                      bool delete_expr_from_cache,
+                      struct lflow_ctx_in *l_ctx_in,
+                      struct lflow_ctx_out *l_ctx_out,
+                      struct controller_event_options *controller_event_opts)
 {
     /* Determine translation of logical table IDs to physical table IDs. */
     bool ingress = !strcmp(lflow->pipeline, "ingress");
@@ -651,7 +562,7 @@  consider_logical_flow(
                  UUID_ARGS(&lflow->header_.uuid));
         return true;
     }
-    if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) {
+    if (!get_local_datapath(l_ctx_in->local_datapaths, ldp->tunnel_key)) {
         VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip",
                  UUID_ARGS(&lflow->header_.uuid));
         return true;
@@ -702,27 +613,28 @@  consider_logical_flow(
 
     struct sset addr_sets_ref = SSET_INITIALIZER(&addr_sets_ref);
     struct sset port_groups_ref = SSET_INITIALIZER(&port_groups_ref);
-    struct lflow_expr *le = lflow_expr_get(lflow_expr_cache, lflow);
+    struct lflow_expr *le = lflow_expr_get(l_ctx_out->lflow_expr_cache, lflow);
     if (le) {
         if (delete_expr_from_cache) {
-            lflow_expr_delete(lflow_expr_cache, le);
+            lflow_expr_delete(l_ctx_out->lflow_expr_cache, le);
         } else {
             expr = le->expr;
         }
     }
 
     if (!expr) {
-        expr = expr_parse_string(lflow->match, &symtab, addr_sets, port_groups,
-                                &addr_sets_ref, &port_groups_ref, &error);
+        expr = expr_parse_string(lflow->match, &symtab, l_ctx_in->addr_sets,
+                                 l_ctx_in->port_groups, &addr_sets_ref,
+                                 &port_groups_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);
+            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_ADDRSET,
+                               addr_set_name, &lflow->header_.uuid);
         }
         const char *port_group_name;
         SSET_FOR_EACH (port_group_name, &port_groups_ref) {
-            lflow_resource_add(lfrr, REF_TYPE_PORTGROUP, port_group_name,
-                            &lflow->header_.uuid);
+            lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_PORTGROUP,
+                               port_group_name, &lflow->header_.uuid);
         }
         sset_destroy(&addr_sets_ref);
         sset_destroy(&port_groups_ref);
@@ -748,13 +660,13 @@  consider_logical_flow(
         expr = expr_simplify(expr);
         expr = expr_normalize(expr);
 
-        lflow_expr_add(lflow_expr_cache, lflow, expr);
+        lflow_expr_add(l_ctx_out->lflow_expr_cache, lflow, expr);
     }
 
     struct condition_aux cond_aux = {
-        .sbrec_port_binding_by_name = sbrec_port_binding_by_name,
-        .chassis = chassis,
-        .active_tunnels = active_tunnels,
+        .sbrec_port_binding_by_name = l_ctx_in->sbrec_port_binding_by_name,
+        .chassis = l_ctx_in->chassis,
+        .active_tunnels = l_ctx_in->active_tunnels,
     };
 
     expr = expr_clone(expr);
@@ -762,8 +674,8 @@  consider_logical_flow(
 
     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,
+            = l_ctx_in->sbrec_multicast_group_by_name_datapath,
+        .sbrec_port_binding_by_name = l_ctx_in->sbrec_port_binding_by_name,
         .dp = lflow->logical_datapath
     };
     uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
@@ -788,8 +700,8 @@  consider_logical_flow(
         .tunnel_ofport = tunnel_ofport_cb,
         .aux = &aux,
         .is_switch = datapath_is_switch(ldp),
-        .group_table = group_table,
-        .meter_table = meter_table,
+        .group_table = l_ctx_out->group_table,
+        .meter_table = l_ctx_out->meter_table,
         .lflow_uuid = lflow->header_.uuid,
 
         .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
@@ -809,7 +721,7 @@  consider_logical_flow(
         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;
+            m->match.flow.conj_id += *l_ctx_out->conj_id_ofs;
         }
         if (datapath_is_switch(ldp)) {
             unsigned int reg_index
@@ -819,7 +731,7 @@  consider_logical_flow(
                 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)) {
+                if (!sset_contains(l_ctx_in->local_lport_ids, buf)) {
                     VLOG_DBG("lflow "UUID_FMT
                              " port %s in match is not local, skip",
                              UUID_ARGS(&lflow->header_.uuid),
@@ -829,7 +741,7 @@  consider_logical_flow(
             }
         }
         if (!m->n) {
-            ofctrl_add_flow(flow_table, ptable, lflow->priority,
+            ofctrl_add_flow(l_ctx_out->flow_table, ptable, lflow->priority,
                             lflow->header_.uuid.parts[0], &m->match, &ofpacts,
                             &lflow->header_.uuid);
         } else {
@@ -842,12 +754,13 @@  consider_logical_flow(
                 struct ofpact_conjunction *dst;
 
                 dst = ofpact_put_CONJUNCTION(&conj);
-                dst->id = src->id + *conj_id_ofs;
+                dst->id = src->id + *l_ctx_out->conj_id_ofs;
                 dst->clause = src->clause;
                 dst->n_clauses = src->n_clauses;
             }
 
-            ofctrl_add_or_append_flow(flow_table, ptable, lflow->priority, 0,
+            ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable,
+                                      lflow->priority, 0,
                                       &m->match, &conj, &lflow->header_.uuid);
             ofpbuf_uninit(&conj);
         }
@@ -856,7 +769,7 @@  consider_logical_flow(
     /* Clean up. */
     expr_matches_destroy(&matches);
     ofpbuf_uninit(&ofpacts);
-    return update_conj_id_ofs(conj_id_ofs, n_conjs);
+    return update_conj_id_ofs(l_ctx_out->conj_id_ofs, n_conjs);
 }
 
 static void
@@ -965,7 +878,6 @@  lflow_handle_changed_neighbors(
     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. */
@@ -995,35 +907,13 @@  lflow_handle_changed_neighbors(
 /* 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,
-          struct hmap *lflow_expr_cache)
+lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out)
 {
     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, lflow_expr_cache);
-    add_neighbor_flows(sbrec_port_binding_by_name, mac_binding_table,
-                       flow_table);
+    add_logical_flows(l_ctx_in, l_ctx_out);
+    add_neighbor_flows(l_ctx_in->sbrec_port_binding_by_name,
+                       l_ctx_in->mac_binding_table, l_ctx_out->flow_table);
 }
 
 void
diff --git a/controller/lflow.h b/controller/lflow.h
index a2fa087f8..8433cc0c6 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -115,67 +115,38 @@  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,
-               struct hmap *lflow_expr_cache);
-
-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,
-    struct hmap *lflow_expr_cache);
-
-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,
-    struct hmap *lflow_expr_cache,
-    bool *changed);
+struct lflow_ctx_in {
+    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_datapath_binding_table *dp_binding_table;
+    const struct sbrec_mac_binding_table *mac_binding_table;
+    const struct sbrec_logical_flow_table *logical_flow_table;
+    const struct sbrec_multicast_group_table *mc_group_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 lflow_ctx_out {
+    struct ovn_desired_flow_table *flow_table;
+    struct ovn_extend_table *group_table;
+    struct ovn_extend_table *meter_table;
+    struct lflow_resource_ref *lfrr;
+    struct hmap *lflow_expr_cache;
+    uint32_t *conj_id_ofs;
+};
+
+void lflow_init(void);
+void lflow_run(struct lflow_ctx_in *, struct lflow_ctx_out *);
+bool lflow_handle_changed_flows(struct lflow_ctx_in *, struct lflow_ctx_out *);
+bool lflow_handle_changed_ref(enum ref_type, const char *ref_name,
+                              struct lflow_ctx_in *, struct lflow_ctx_out *,
+                              bool *changed);
 void lflow_handle_changed_neighbors(
     struct ovsdb_idl_index *sbrec_port_binding_by_name,
     const struct sbrec_mac_binding_table *,
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 9b88f88fe..efd5d258d 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -1214,6 +1214,85 @@  struct ed_type_flow_output {
     struct hmap lflow_expr_cache;
 };
 
+static void init_lflow_ctx(struct engine_node *node,
+                           struct ed_type_runtime_data *rt_data,
+                           struct ed_type_flow_output *fo,
+                           struct lflow_ctx_in *l_ctx_in,
+                           struct lflow_ctx_out *l_ctx_out)
+{
+    struct ovsdb_idl_index *sbrec_port_binding_by_name =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_port_binding", node),
+                "name");
+
+    struct ovsdb_idl_index *sbrec_mc_group_by_name_dp =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_multicast_group", node),
+                "name_datapath");
+
+    struct sbrec_dhcp_options_table *dhcp_table =
+        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
+            engine_get_input("SB_dhcp_options", node));
+
+    struct sbrec_dhcpv6_options_table *dhcpv6_table =
+        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
+            engine_get_input("SB_dhcpv6_options", node));
+
+    struct sbrec_mac_binding_table *mac_binding_table =
+        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
+            engine_get_input("SB_mac_binding", node));
+
+    struct sbrec_logical_flow_table *logical_flow_table =
+        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
+            engine_get_input("SB_logical_flow", node));
+
+    struct sbrec_multicast_group_table *multicast_group_table =
+        (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
+            engine_get_input("SB_multicast_group", node));
+
+    const char *chassis_id = chassis_get_id();
+    const struct sbrec_chassis *chassis = NULL;
+    struct ovsdb_idl_index *sbrec_chassis_by_name =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_chassis", node),
+                "name");
+    if (chassis_id) {
+        chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+    }
+
+    ovs_assert(chassis);
+
+    struct ed_type_addr_sets *as_data =
+        engine_get_input_data("addr_sets", node);
+    struct shash *addr_sets = &as_data->addr_sets;
+
+    struct ed_type_port_groups *pg_data =
+        engine_get_input_data("port_groups", node);
+    struct shash *port_groups = &pg_data->port_groups;
+
+    l_ctx_in->sbrec_multicast_group_by_name_datapath =
+        sbrec_mc_group_by_name_dp;
+    l_ctx_in->sbrec_port_binding_by_name = sbrec_port_binding_by_name;
+    l_ctx_in->dhcp_options_table  = dhcp_table;
+    l_ctx_in->dhcpv6_options_table = dhcpv6_table;
+    l_ctx_in->mac_binding_table = mac_binding_table;
+    l_ctx_in->logical_flow_table = logical_flow_table;
+    l_ctx_in->mc_group_table = multicast_group_table;
+    l_ctx_in->chassis = chassis;
+    l_ctx_in->local_datapaths = &rt_data->local_datapaths;
+    l_ctx_in->addr_sets = addr_sets;
+    l_ctx_in->port_groups = port_groups;
+    l_ctx_in->active_tunnels = &rt_data->active_tunnels;
+    l_ctx_in->local_lport_ids = &rt_data->local_lport_ids;
+
+    l_ctx_out->flow_table = &fo->flow_table;
+    l_ctx_out->group_table = &fo->group_table;
+    l_ctx_out->meter_table = &fo->meter_table;
+    l_ctx_out->lfrr = &fo->lflow_resource_ref;
+    l_ctx_out->lflow_expr_cache = &fo->lflow_expr_cache;
+    l_ctx_out->conj_id_ofs = &fo->conj_id_ofs;
+}
+
 static void *
 en_flow_output_init(struct engine_node *node OVS_UNUSED,
                     struct engine_arg *arg OVS_UNUSED)
@@ -1247,7 +1326,6 @@  en_flow_output_run(struct engine_node *node, void *data)
         engine_get_input_data("runtime_data", node);
     struct hmap *local_datapaths = &rt_data->local_datapaths;
     struct sset *local_lports = &rt_data->local_lports;
-    struct sset *local_lport_ids = &rt_data->local_lport_ids;
     struct sset *active_tunnels = &rt_data->active_tunnels;
 
     struct ed_type_ct_zones *ct_zones_data =
@@ -1271,13 +1349,6 @@  en_flow_output_run(struct engine_node *node, void *data)
         engine_ovsdb_node_get_index(
                 engine_get_input("SB_chassis", node),
                 "name");
-    struct ed_type_addr_sets *as_data =
-        engine_get_input_data("addr_sets", node);
-    struct shash *addr_sets = &as_data->addr_sets;
-
-    struct ed_type_port_groups *pg_data =
-        engine_get_input_data("port_groups", node);
-    struct shash *port_groups = &pg_data->port_groups;
 
     const struct sbrec_chassis *chassis = NULL;
     if (chassis_id) {
@@ -1303,43 +1374,16 @@  en_flow_output_run(struct engine_node *node, void *data)
         lflow_resource_clear(lfrr);
     }
 
-    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_multicast_group", node),
-                "name_datapath");
-
     struct ovsdb_idl_index *sbrec_port_binding_by_name =
         engine_ovsdb_node_get_index(
                 engine_get_input("SB_port_binding", node),
                 "name");
 
-    struct sbrec_dhcp_options_table *dhcp_table =
-        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcp_options", node));
-
-    struct sbrec_dhcpv6_options_table *dhcpv6_table =
-        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcpv6_options", node));
-
-    struct sbrec_logical_flow_table *logical_flow_table =
-        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
-            engine_get_input("SB_logical_flow", node));
-
-    struct sbrec_mac_binding_table *mac_binding_table =
-        (struct sbrec_mac_binding_table *)EN_OVSDB_GET(
-            engine_get_input("SB_mac_binding", node));
-
     *conj_id_ofs = 1;
-    lflow_run(sbrec_multicast_group_by_name_datapath,
-              sbrec_port_binding_by_name,
-              dhcp_table, dhcpv6_table,
-              logical_flow_table,
-              mac_binding_table,
-              chassis, local_datapaths, addr_sets,
-              port_groups, active_tunnels, local_lport_ids,
-              flow_table, group_table, meter_table, lfrr,
-              conj_id_ofs,
-              &fo->lflow_expr_cache);
+    struct lflow_ctx_in l_ctx_in;
+    struct lflow_ctx_out l_ctx_out;
+    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+    lflow_run(&l_ctx_in, &l_ctx_out);
 
     struct sbrec_multicast_group_table *multicast_group_table =
         (struct sbrec_multicast_group_table *)EN_OVSDB_GET(
@@ -1371,17 +1415,6 @@  flow_output_sb_logical_flow_handler(struct engine_node *node, void *data)
 {
     struct ed_type_runtime_data *rt_data =
         engine_get_input_data("runtime_data", node);
-    struct hmap *local_datapaths = &rt_data->local_datapaths;
-    struct sset *local_lport_ids = &rt_data->local_lport_ids;
-    struct sset *active_tunnels = &rt_data->active_tunnels;
-    struct ed_type_addr_sets *as_data =
-        engine_get_input_data("addr_sets", node);
-    struct shash *addr_sets = &as_data->addr_sets;
-
-    struct ed_type_port_groups *pg_data =
-        engine_get_input_data("port_groups", node);
-    struct shash *port_groups = &pg_data->port_groups;
-
     struct ovsrec_open_vswitch_table *ovs_table =
         (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
             engine_get_input("OVS_open_vswitch", node));
@@ -1389,58 +1422,14 @@  flow_output_sb_logical_flow_handler(struct engine_node *node, void *data)
         (struct ovsrec_bridge_table *)EN_OVSDB_GET(
             engine_get_input("OVS_bridge", node));
     const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
-    const char *chassis_id = chassis_get_id();
-
-    struct ovsdb_idl_index *sbrec_chassis_by_name =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_chassis", node),
-                "name");
-
-    const struct sbrec_chassis *chassis = NULL;
-    if (chassis_id) {
-        chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
-    }
-
-    ovs_assert(br_int && chassis);
+    ovs_assert(br_int);
 
     struct ed_type_flow_output *fo = data;
-    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
-    struct ovn_extend_table *group_table = &fo->group_table;
-    struct ovn_extend_table *meter_table = &fo->meter_table;
-    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
-    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
-
-    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_multicast_group", node),
-                "name_datapath");
-
-    struct ovsdb_idl_index *sbrec_port_binding_by_name =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_port_binding", node),
-                "name");
-
-    struct sbrec_dhcp_options_table *dhcp_table =
-        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcp_options", node));
-
-    struct sbrec_dhcpv6_options_table *dhcpv6_table =
-        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcpv6_options", node));
-
-    struct sbrec_logical_flow_table *logical_flow_table =
-        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
-            engine_get_input("SB_logical_flow", node));
+    struct lflow_ctx_in l_ctx_in;
+    struct lflow_ctx_out l_ctx_out;
+    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
 
-    bool handled = lflow_handle_changed_flows(
-              sbrec_multicast_group_by_name_datapath,
-              sbrec_port_binding_by_name,
-              dhcp_table, dhcpv6_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, &fo->lflow_expr_cache);
+    bool handled = lflow_handle_changed_flows(&l_ctx_in, &l_ctx_out);
 
     engine_set_node_state(node, EN_UPDATED);
     return handled;
@@ -1628,17 +1617,12 @@  _flow_output_resource_ref_handler(struct engine_node *node, void *data,
 {
     struct ed_type_runtime_data *rt_data =
         engine_get_input_data("runtime_data", node);
-    struct hmap *local_datapaths = &rt_data->local_datapaths;
-    struct sset *local_lport_ids = &rt_data->local_lport_ids;
-    struct sset *active_tunnels = &rt_data->active_tunnels;
 
     struct ed_type_addr_sets *as_data =
         engine_get_input_data("addr_sets", node);
-    struct shash *addr_sets = &as_data->addr_sets;
 
     struct ed_type_port_groups *pg_data =
         engine_get_input_data("port_groups", node);
-    struct shash *port_groups = &pg_data->port_groups;
 
     struct ovsrec_open_vswitch_table *ovs_table =
         (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
@@ -1661,33 +1645,10 @@  _flow_output_resource_ref_handler(struct engine_node *node, void *data,
     ovs_assert(br_int && chassis);
 
     struct ed_type_flow_output *fo = data;
-    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
-    struct ovn_extend_table *group_table = &fo->group_table;
-    struct ovn_extend_table *meter_table = &fo->meter_table;
-    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
-    struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref;
 
-    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_multicast_group", node),
-                "name_datapath");
-
-    struct ovsdb_idl_index *sbrec_port_binding_by_name =
-        engine_ovsdb_node_get_index(
-                engine_get_input("SB_port_binding", node),
-                "name");
-
-    struct sbrec_dhcp_options_table *dhcp_table =
-        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcp_options", node));
-
-    struct sbrec_dhcpv6_options_table *dhcpv6_table =
-        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
-            engine_get_input("SB_dhcpv6_options", node));
-
-    struct sbrec_logical_flow_table *logical_flow_table =
-        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
-            engine_get_input("SB_logical_flow", node));
+    struct lflow_ctx_in l_ctx_in;
+    struct lflow_ctx_out l_ctx_out;
+    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
 
     bool changed;
     const char *ref_name;
@@ -1718,14 +1679,8 @@  _flow_output_resource_ref_handler(struct engine_node *node, void *data,
 
 
     SSET_FOR_EACH (ref_name, deleted) {
-        if (!lflow_handle_changed_ref(ref_type, ref_name,
-                    sbrec_multicast_group_by_name_datapath,
-                    sbrec_port_binding_by_name,dhcp_table,
-                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
+        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
+                                      &l_ctx_out, &changed)) {
             return false;
         }
         if (changed) {
@@ -1733,14 +1688,8 @@  _flow_output_resource_ref_handler(struct engine_node *node, void *data,
         }
     }
     SSET_FOR_EACH (ref_name, updated) {
-        if (!lflow_handle_changed_ref(ref_type, ref_name,
-                    sbrec_multicast_group_by_name_datapath,
-                    sbrec_port_binding_by_name,dhcp_table,
-                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
+        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
+                                      &l_ctx_out, &changed)) {
             return false;
         }
         if (changed) {
@@ -1748,14 +1697,8 @@  _flow_output_resource_ref_handler(struct engine_node *node, void *data,
         }
     }
     SSET_FOR_EACH (ref_name, new) {
-        if (!lflow_handle_changed_ref(ref_type, ref_name,
-                    sbrec_multicast_group_by_name_datapath,
-                    sbrec_port_binding_by_name,dhcp_table,
-                    dhcpv6_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, &fo->lflow_expr_cache, &changed)) {
+        if (!lflow_handle_changed_ref(ref_type, ref_name, &l_ctx_in,
+                                      &l_ctx_out, &changed)) {
             return false;
         }
         if (changed) {