On Thu, Apr 10, 2025 at 4:14 AM Mark Michelson via dev <
ovs-dev@openvswitch.org> wrote:

> An engine node's run() callback is intended to do two things:
> 1. Recalculate node data based on inputs.
> 2. Change the state of the node to indicate how the data was affected
>    during the function call.
>
> (1) is well-documented and clear based on the stated intent of the run()
> callback from comments.
>
> (2) is less well-defined and very easy to overlook. I, personally, have
> lost hours trying to debug why input data was being read as NULL, only
> to figure out that the input node's run() callback had forgotten to
> update the node state to EN_UPDATED.
>
> This change seeks to solve this problem by forcing the run() callback
> to return the new engine node state to the incremental engine. The
> engine internals are then responsible for updating the node state based
> on the return value of the run() callback.
>
> This patch is intended not to alter any existing logic in the code. It
> should be exactly the same before and after this patch.
>
> Signed-off-by: Mark Michelson <mmich...@redhat.com>
> ---
>  controller/acl-ids.c              |   7 +-
>  controller/acl-ids.h              |   2 +-
>  controller/ovn-controller.c       | 127 +++++++++++++++---------------
>  lib/inc-proc-eng.c                |   8 +-
>  lib/inc-proc-eng.h                |   9 +--
>  northd/aging.c                    |  36 ++++-----
>  northd/aging.h                    |  11 ++-
>  northd/en-acl-ids.c               |   4 +-
>  northd/en-acl-ids.h               |   2 +-
>  northd/en-advertised-route-sync.c |   8 +-
>  northd/en-advertised-route-sync.h |   5 +-
>  northd/en-ecmp-nexthop.c          |   4 +-
>  northd/en-ecmp-nexthop.h          |   2 +-
>  northd/en-global-config.c         |   6 +-
>  northd/en-global-config.h         |   2 +-
>  northd/en-group-ecmp-route.c      |   4 +-
>  northd/en-group-ecmp-route.h      |   3 +-
>  northd/en-lb-data.c               |   4 +-
>  northd/en-lb-data.h               |   2 +-
>  northd/en-learned-route-sync.c    |   4 +-
>  northd/en-learned-route-sync.h    |   3 +-
>  northd/en-lflow.c                 |   5 +-
>  northd/en-lflow.h                 |   2 +-
>  northd/en-lr-nat.c                |   4 +-
>  northd/en-lr-nat.h                |   4 +-
>  northd/en-lr-stateful.c           |   4 +-
>  northd/en-lr-stateful.h           |   2 +-
>  northd/en-ls-stateful.c           |   4 +-
>  northd/en-ls-stateful.h           |   2 +-
>  northd/en-meters.c                |   4 +-
>  northd/en-meters.h                |   2 +-
>  northd/en-multicast.c             |   4 +-
>  northd/en-multicast.h             |   2 +-
>  northd/en-northd-output.c         |   7 +-
>  northd/en-northd-output.h         |   4 +-
>  northd/en-northd.c                |  20 ++---
>  northd/en-northd.h                |  12 +--
>  northd/en-port-group.c            |   4 +-
>  northd/en-port-group.h            |   2 +-
>  northd/en-sampling-app.c          |   4 +-
>  northd/en-sampling-app.h          |   2 +-
>  northd/en-sync-from-sb.c          |   4 +-
>  northd/en-sync-from-sb.h          |   2 +-
>  northd/en-sync-sb.c               |  18 ++---
>  northd/en-sync-sb.h               |   9 ++-
>  45 files changed, 195 insertions(+), 185 deletions(-)
>
> diff --git a/controller/acl-ids.c b/controller/acl-ids.c
> index 78f261f3c..824a57adb 100644
> --- a/controller/acl-ids.c
> +++ b/controller/acl-ids.c
> @@ -85,12 +85,11 @@ en_acl_id_init(struct engine_node *node OVS_UNUSED,
>      return ids;
>  }
>
> -void
> +enum engine_node_state
>  en_acl_id_run(struct engine_node *node, void *data)
>  {
>      if (!ovs_feature_is_supported(OVS_CT_LABEL_FLUSH_SUPPORT)) {
> -        engine_set_node_state(node, EN_UNCHANGED);
> -        return;
> +        return EN_UNCHANGED;
>      }
>
>      const struct sbrec_acl_id_table *sb_acl_id_table =
> @@ -121,7 +120,7 @@ en_acl_id_run(struct engine_node *node, void *data)
>          id->state = ACTIVE;
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/controller/acl-ids.h b/controller/acl-ids.h
> index f9708e5e4..6d0481f0a 100644
> --- a/controller/acl-ids.h
> +++ b/controller/acl-ids.h
> @@ -21,7 +21,7 @@
>  #include "openvswitch/types.h"
>
>  void *en_acl_id_init(struct engine_node *, struct engine_arg *);
> -void en_acl_id_run(struct engine_node *, void *);
> +enum engine_node_state en_acl_id_run(struct engine_node *, void *);
>  void en_acl_id_cleanup(void *);
>  bool en_acl_id_is_valid(struct engine_node *);
>
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index e70aaec7b..8e644fc58 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -1046,8 +1046,8 @@ en_ofctrl_is_connected_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -static void
> -en_ofctrl_is_connected_run(struct engine_node *node, void *data)
> +static enum engine_node_state
> +en_ofctrl_is_connected_run(struct engine_node *node OVS_UNUSED, void
> *data)
>  {
>      struct controller_engine_ctx *ctrl_ctx =
> engine_get_context()->client_ctx;
>      struct ed_type_ofctrl_is_connected *of_data = data;
> @@ -1059,10 +1059,9 @@ en_ofctrl_is_connected_run(struct engine_node
> *node, void *data)
>              ofctrl_seqno_flush();
>              if_status_mgr_clear(ctrl_ctx->if_mgr);
>          }
> -        engine_set_node_state(node, EN_UPDATED);
> -        return;
> +        return EN_UPDATED;
>      }
> -    engine_set_node_state(node, EN_UNCHANGED);
> +    return EN_UNCHANGED;
>  }
>
>  struct ed_type_if_status_mgr {
> @@ -1083,7 +1082,7 @@ en_if_status_mgr_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -static void
> +static enum engine_node_state
>  en_if_status_mgr_run(struct engine_node *node, void *data_)
>  {
>      enum engine_node_state state = EN_UNCHANGED;
> @@ -1098,7 +1097,7 @@ en_if_status_mgr_run(struct engine_node *node, void
> *data_)
>              state = EN_UPDATED;
>          }
>      }
> -    engine_set_node_state(node, state);
> +    return state;
>  }
>
>  static bool
> @@ -1181,21 +1180,21 @@ en_ovs_interface_shadow_clear_tracked_data(void
> *data_)
>      }
>  }
>
> -static void
> +static enum engine_node_state
>  en_ovs_interface_shadow_run(struct engine_node *node, void *data_)
>  {
>      struct ed_type_ovs_interface_shadow *data = data_;
>      const struct ovsrec_interface_table *iface_table =
>          EN_OVSDB_GET(engine_get_input("OVS_interface", node));
>      data->iface_table = iface_table;
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
>  ovs_interface_shadow_ovs_interface_handler(struct engine_node *node,
>                                             void *data_)
>  {
> -    en_ovs_interface_shadow_run(node, data_);
> +    engine_set_node_state(node, en_ovs_interface_shadow_run(node, data_));
>      return true;
>  }
>
> @@ -1234,8 +1233,8 @@ en_activated_ports_clear_tracked_data(void *data)
>      en_activated_ports_cleanup(data);
>  }
>
> -static void
> -en_activated_ports_run(struct engine_node *node, void *data_)
> +static enum engine_node_state
> +en_activated_ports_run(struct engine_node *node OVS_UNUSED, void *data_)
>  {
>      struct ed_type_activated_ports *data = data_;
>      enum engine_node_state state = EN_UNCHANGED;
> @@ -1243,7 +1242,7 @@ en_activated_ports_run(struct engine_node *node,
> void *data_)
>      if (data->activated_ports) {
>          state = EN_UPDATED;
>      }
> -    engine_set_node_state(node, state);
> +    return state;
>  }
>
>  struct ed_type_postponed_ports {
> @@ -1269,8 +1268,8 @@ en_postponed_ports_cleanup(void *data_)
>      data->postponed_ports = NULL;
>  }
>
> -static void
> -en_postponed_ports_run(struct engine_node *node, void *data_)
> +static enum engine_node_state
> +en_postponed_ports_run(struct engine_node *node OVS_UNUSED, void *data_)
>  {
>      struct ed_type_postponed_ports *data = data_;
>      enum engine_node_state state = EN_UNCHANGED;
> @@ -1278,7 +1277,7 @@ en_postponed_ports_run(struct engine_node *node,
> void *data_)
>      if (!sset_is_empty(data->postponed_ports)) {
>          state = EN_UPDATED;
>      }
> -    engine_set_node_state(node, state);
> +    return state;
>  }
>
>  struct ed_type_runtime_data {
> @@ -1523,7 +1522,7 @@ init_binding_ctx(struct engine_node *node,
>      b_ctx_out->localnet_learn_fdb_changed = false;
>  }
>
> -static void
> +static enum engine_node_state
>  en_runtime_data_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_runtime_data *rt_data = data;
> @@ -1580,7 +1579,7 @@ en_runtime_data_run(struct engine_node *node, void
> *data)
>      binding_run(&b_ctx_in, &b_ctx_out);
>      rt_data->localnet_learn_fdb = b_ctx_out.localnet_learn_fdb;
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  struct ed_type_sb_ro {
> @@ -1595,17 +1594,18 @@ en_sb_ro_init(struct engine_node *node OVS_UNUSED,
>      return data;
>  }
>
> -static void
> -en_sb_ro_run(struct engine_node *node, void *data)
> +static enum engine_node_state
> +en_sb_ro_run(struct engine_node *node OVS_UNUSED, void *data)
>  {
>      struct ed_type_sb_ro *sb_ro_data = data;
>      bool sb_readonly = !engine_get_context()->ovnsb_idl_txn;
>      if (sb_ro_data->sb_readonly != sb_readonly) {
>          sb_ro_data->sb_readonly = sb_readonly;
>          if (!sb_ro_data->sb_readonly) {
> -            engine_set_node_state(node, EN_UPDATED);
> +            return EN_UPDATED;
>          }
>      }
> +    return EN_UNCHANGED;
>  }
>
>  static void
> @@ -1843,7 +1843,7 @@ en_template_vars_init(struct engine_node *node
> OVS_UNUSED,
>      return tv_data;
>  }
>
> -static void
> +static enum engine_node_state
>  en_template_vars_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_template_vars *tv_data = data;
> @@ -1864,7 +1864,7 @@ en_template_vars_run(struct engine_node *node, void
> *data)
>      smap_clear(&tv_data->local_templates);
>      template_vars_init(sbrec_chassis_template_var_index_by_chassis,
>                         chassis, &tv_data->local_templates);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -2033,7 +2033,7 @@ addr_sets_update(const struct
> sbrec_address_set_table *address_set_table,
>      }
>  }
>
> -static void
> +static enum engine_node_state
>  en_addr_sets_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_addr_sets *as = data;
> @@ -2047,7 +2047,7 @@ en_addr_sets_run(struct engine_node *node, void
> *data)
>      addr_sets_init(as_table, &as->addr_sets);
>
>      as->change_tracked = false;
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -2220,7 +2220,7 @@ en_port_groups_clear_tracked_data(void *data_)
>      pg->change_tracked = false;
>  }
>
> -static void
> +static enum engine_node_state
>  en_port_groups_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_port_groups *pg = data;
> @@ -2237,7 +2237,7 @@ en_port_groups_run(struct engine_node *node, void
> *data)
>      port_groups_init(pg_table, &rt_data->related_lports.lport_names,
>                       &pg->port_group_ssets, &pg->port_groups_cs_local);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -2353,7 +2353,7 @@ en_ct_zones_cleanup(void *data)
>      ct_zone_ctx_destroy(&ct_zones_data->ctx);
>  }
>
> -static void
> +static enum engine_node_state
>  en_ct_zones_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_ct_zones *ct_zones_data = data;
> @@ -2376,7 +2376,7 @@ en_ct_zones_run(struct engine_node *node, void *data)
>                           &rt_data->lbinding_data.lports);
>
>      ct_zones_data->recomputed = true;
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  /* Handles datapath binding changes for the ct_zones engine.
> @@ -2505,17 +2505,16 @@ en_mff_ovn_geneve_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -static void
> -en_mff_ovn_geneve_run(struct engine_node *node, void *data)
> +static enum engine_node_state
> +en_mff_ovn_geneve_run(struct engine_node *node OVS_UNUSED, void *data)
>  {
>      struct ed_type_mff_ovn_geneve *ed_mff_ovn_geneve = data;
>      enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id();
>      if (ed_mff_ovn_geneve->mff_ovn_geneve != mff_ovn_geneve) {
>          ed_mff_ovn_geneve->mff_ovn_geneve = mff_ovn_geneve;
> -        engine_set_node_state(node, EN_UPDATED);
> -        return;
> +        return EN_UPDATED;
>      }
> -    engine_set_node_state(node, EN_UNCHANGED);
> +    return EN_UNCHANGED;
>  }
>
>  /* Stores the load balancers that are applied to the datapath 'dp'. */
> @@ -2823,7 +2822,7 @@ en_lb_data_init(struct engine_node *node OVS_UNUSED,
>      return lb_data;
>  }
>
> -static void
> +static enum engine_node_state
>  en_lb_data_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_lb_data *lb_data = data;
> @@ -2853,7 +2852,7 @@ en_lb_data_run(struct engine_node *node, void *data)
>                               &tv_data->local_templates, false);
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -3180,7 +3179,7 @@ en_mac_cache_init(struct engine_node *node
> OVS_UNUSED,
>      return cache_data;
>  }
>
> -static void
> +static enum engine_node_state
>  en_mac_cache_run(struct engine_node *node, void *data)
>  {
>      struct mac_cache_data *cache_data = data;
> @@ -3215,7 +3214,7 @@ en_mac_cache_run(struct engine_node *node, void
> *data)
>                                            sbrec_fdb_by_dp_key);
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -3417,7 +3416,7 @@ en_bfd_chassis_init(struct engine_node *node
> OVS_UNUSED,
>      return data;
>  }
>
> -static void
> +static enum engine_node_state
>  en_bfd_chassis_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      struct ed_type_bfd_chassis *bfd_chassis = data;
> @@ -3436,7 +3435,7 @@ en_bfd_chassis_run(struct engine_node *node, void
> *data OVS_UNUSED)
>      sset_clear(&bfd_chassis->bfd_chassis);
>      bfd_calculate_chassis(chassis, ha_chassis_grp_table,
>                            &bfd_chassis->bfd_chassis);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static void
> @@ -3453,7 +3452,7 @@ en_dns_cache_init(struct engine_node *node
> OVS_UNUSED,
>      return NULL;
>  }
>
> -static void
> +static enum engine_node_state
>  en_dns_cache_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct sbrec_dns_table *dns_table =
> @@ -3461,7 +3460,7 @@ en_dns_cache_run(struct engine_node *node, void
> *data OVS_UNUSED)
>
>      ovn_dns_sync_cache(dns_table);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -3511,7 +3510,7 @@ en_non_vif_data_cleanup(void *data OVS_UNUSED)
>      chassis_tunnels_destroy(&ed_non_vif_data->chassis_tunnels);
>  }
>
> -static void
> +static enum engine_node_state
>  en_non_vif_data_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_non_vif_data *ed_non_vif_data = data;
> @@ -3540,7 +3539,7 @@ en_non_vif_data_run(struct engine_node *node, void
> *data)
>
>      local_nonvif_data_run(br_int, chassis,
> &ed_non_vif_data->patch_ofports,
>                            &ed_non_vif_data->chassis_tunnels);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -3576,7 +3575,7 @@ en_northd_options_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -static void
> +static enum engine_node_state
>  en_northd_options_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_northd_options *n_opts = data;
> @@ -3603,7 +3602,7 @@ en_northd_options_run(struct engine_node *node, void
> *data)
>                          false)
>          : false;
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -3676,7 +3675,7 @@ en_dhcp_options_cleanup(void *data)
>      dhcp_opts_destroy(&dhcp_opts->v6_opts);
>  }
>
> -static void
> +static enum engine_node_state
>  en_dhcp_options_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_dhcp_options *dhcp_opts = data;
> @@ -3701,7 +3700,7 @@ en_dhcp_options_run(struct engine_node *node, void
> *data)
>         dhcp_opt_add(&dhcp_opts->v6_opts, dhcpv6_opt_row->name,
>                      dhcpv6_opt_row->code, dhcpv6_opt_row->type);
>      }
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  struct lflow_output_persistent_data {
> @@ -3935,7 +3934,7 @@ en_lflow_output_cleanup(void *data)
>      flow_collector_ids_destroy(&flow_output_data->collector_ids);
>  }
>
> -static void
> +static enum engine_node_state
>  en_lflow_output_run(struct engine_node *node, void *data)
>  {
>      const struct ovsrec_open_vswitch_table *ovs_table =
> @@ -3996,7 +3995,7 @@ en_lflow_output_run(struct engine_node *node, void
> *data)
>      init_lflow_ctx(node, fo, &l_ctx_in, &l_ctx_out);
>      lflow_run(&l_ctx_in, &l_ctx_out);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -4634,7 +4633,7 @@ en_pflow_output_cleanup(void *data OVS_UNUSED)
>      ovn_desired_flow_table_destroy(&pfo->flow_table);
>  }
>
> -static void
> +static enum engine_node_state
>  en_pflow_output_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_pflow_output *pfo = data;
> @@ -4656,7 +4655,7 @@ en_pflow_output_run(struct engine_node *node, void
> *data)
>      physical_run(&p_ctx, pflow_table);
>      destroy_physical_ctx(&p_ctx);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -4907,11 +4906,11 @@ en_controller_output_cleanup(void *data OVS_UNUSED)
>
>  }
>
> -static void
> +static enum engine_node_state
>  en_controller_output_run(struct engine_node *node OVS_UNUSED,
>                           void *data OVS_UNUSED)
>  {
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static bool
> @@ -5003,7 +5002,7 @@ struct ed_type_route {
>      struct ovsdb_idl *ovnsb_idl;
>  };
>
> -static void
> +static enum engine_node_state
>  en_route_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_route *re_data = data;
> @@ -5060,7 +5059,7 @@ en_route_run(struct engine_node *node, void *data)
>      sset_clear(r_ctx_out.tracked_ports_remote);
>
>      route_run(&r_ctx_in, &r_ctx_out);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>
> @@ -5223,7 +5222,7 @@ struct ed_type_route_exchange {
>      struct ovsdb_idl *sb_idl;
>  };
>
> -static void
> +static enum engine_node_state
>  en_route_exchange_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_route_exchange *re = data;
> @@ -5245,7 +5244,7 @@ en_route_exchange_run(struct engine_node *node, void
> *data)
>       * the Learned_Route table, since they where introduced in the same
>       * release. */
>      if (!sbrec_server_has_learned_route_table(re->sb_idl)) {
> -        return;
> +        return EN_STALE;
>      }
>
>      struct route_exchange_ctx_in r_ctx_in = {
> @@ -5264,7 +5263,7 @@ en_route_exchange_run(struct engine_node *node, void
> *data)
>      route_table_watch_request_cleanup(&r_ctx_out.route_table_watches);
>      hmap_destroy(&r_ctx_out.route_table_watches);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>
> @@ -5289,16 +5288,18 @@ struct ed_type_route_table_notify {
>      bool changed;
>  };
>
> -static void
> -en_route_table_notify_run(struct engine_node *node, void *data)
> +static enum engine_node_state
> +en_route_table_notify_run(struct engine_node *node OVS_UNUSED, void *data)
>  {
>      struct ed_type_route_table_notify *rtn = data;
> +    enum engine_node_state state;
>      if (rtn->changed) {
> -        engine_set_node_state(node, EN_UPDATED);
> +        state = EN_UPDATED;
>      } else {
> -        engine_set_node_state(node, EN_UNCHANGED);
> +        state = EN_UNCHANGED;
>      }
>      rtn->changed = false;
> +    return state;
>  }
>
>
> diff --git a/lib/inc-proc-eng.c b/lib/inc-proc-eng.c
> index 56dc62c4f..70913a00c 100644
> --- a/lib/inc-proc-eng.c
> +++ b/lib/inc-proc-eng.c
> @@ -427,7 +427,7 @@ engine_recompute(struct engine_node *node, bool
> allowed,
>
>      /* Run the node handler which might change state. */
>      long long int now = time_msec();
> -    node->run(node, node->data);
> +    engine_set_node_state(node, node->run(node, node->data));
>      node->stats.recompute++;
>      long long int delta_time = time_msec() - now;
>      if (delta_time > engine_compute_log_timeout_msec) {
> @@ -483,7 +483,7 @@ engine_run_node(struct engine_node *node, bool
> recompute_allowed)
>  {
>      if (!node->n_inputs) {
>          /* Run the node handler which might change state. */
> -        node->run(node, node->data);
> +        engine_set_node_state(node, node->run(node, node->data));
>          node->stats.recompute++;
>          return;
>      }
> @@ -559,7 +559,9 @@ engine_need_run(void)
>              continue;
>          }
>
> -        engine_nodes[i]->run(engine_nodes[i], engine_nodes[i]->data);
> +        engine_set_node_state(engine_nodes[i],
> +                              engine_nodes[i]->run(engine_nodes[i],
> +
>  engine_nodes[i]->data));
>          engine_nodes[i]->stats.recompute++;
>          VLOG_DBG("input node: %s, state: %s", engine_nodes[i]->name,
>                   engine_node_state_name[engine_nodes[i]->state]);
> diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
> index 49d6f7359..5ff320cf8 100644
> --- a/lib/inc-proc-eng.h
> +++ b/lib/inc-proc-eng.h
> @@ -241,7 +241,7 @@ struct engine_node {
>       * implementation guarantees that the txn pointers returned
>       * engine_get_context() are not NULL and valid.
>       */
> -    void (*run)(struct engine_node *node, void *data);
> +    enum engine_node_state (*run)(struct engine_node *node, void *data);
>
>      /* Method to validate if the 'internal_data' is valid. This allows
> users
>       * to customize when 'data' can be used (e.g., even if the node
> @@ -434,17 +434,16 @@ void engine_ovsdb_node_add_index(struct engine_node
> *, const char *name,
>  /* Macro to define member functions of an engine node which represents
>   * a table of OVSDB */
>  #define ENGINE_FUNC_OVSDB(DB_NAME, TBL_NAME) \
> -static void \
> +static enum engine_node_state \
>  en_##DB_NAME##_##TBL_NAME##_run(struct engine_node *node, \
>                                  void *data OVS_UNUSED) \
>  { \
>      const struct DB_NAME##rec_##TBL_NAME##_table *table = \
>          EN_OVSDB_GET(node); \
>      if (DB_NAME##rec_##TBL_NAME##_table_track_get_first(table)) { \
> -        engine_set_node_state(node, EN_UPDATED); \
> -        return; \
> +        return EN_UPDATED; \
>      } \
> -    engine_set_node_state(node, EN_UNCHANGED); \
> +    return EN_UNCHANGED; \
>  } \
>  static void *en_##DB_NAME##_##TBL_NAME##_init( \
>      struct engine_node *node OVS_UNUSED, \
> diff --git a/northd/aging.c b/northd/aging.c
> index e095f29b2..32b21ff61 100644
> --- a/northd/aging.c
> +++ b/northd/aging.c
> @@ -386,7 +386,7 @@ mac_binding_aging_run_for_datapath(const struct
> sbrec_datapath_binding *dp,
>      sbrec_mac_binding_index_destroy_row(mb_index_row);
>  }
>
> -void
> +enum engine_node_state
>  en_mac_binding_aging_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -400,7 +400,7 @@ en_mac_binding_aging_run(struct engine_node *node,
> void *data OVS_UNUSED)
>      if (!eng_ctx->ovnsb_idl_txn ||
>          !global_config->features.mac_binding_timestamp ||
>          time_msec() < waker->next_wake_msec) {
> -        return;
> +        return EN_STALE;
>      }
>
>      uint32_t limit = get_removal_limit(node, "mac_binding_removal_limit");
> @@ -441,7 +441,7 @@ en_mac_binding_aging_run(struct engine_node *node,
> void *data OVS_UNUSED)
>
>      aging_waker_schedule_next_wake(waker, ctx.next_wake_ms);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void *
> @@ -462,24 +462,22 @@ en_mac_binding_aging_cleanup(void *data OVS_UNUSED)
>   * if we there are updates, so it could process the other nodes, however
>   * the waker cannot be dependent on other node because it wouldn't be
>   * input node anymore. */
> -void
> -en_mac_binding_aging_waker_run(struct engine_node *node, void *data)
> +enum engine_node_state
> +en_mac_binding_aging_waker_run(struct engine_node *node OVS_UNUSED, void
> *data)
>  {
>      struct aging_waker *waker = data;
>
> -    engine_set_node_state(node, EN_UNCHANGED);
> -
>      if (!waker->should_schedule) {
> -        return;
> +        return EN_UNCHANGED;
>      }
>
>      if (time_msec() >= waker->next_wake_msec) {
>          waker->should_schedule = false;
> -        engine_set_node_state(node, EN_UPDATED);
> -        return;
> +        return EN_UPDATED;
>      }
>
>      poll_timer_wait_until(waker->next_wake_msec);
> +    return EN_UNCHANGED;
>  }
>
>  void *
> @@ -524,7 +522,7 @@ fdb_run_for_datapath(const struct
> sbrec_datapath_binding *dp,
>      sbrec_fdb_index_destroy_row(fdb_index_row);
>  }
>
> -void
> +enum engine_node_state
>  en_fdb_aging_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -536,7 +534,7 @@ en_fdb_aging_run(struct engine_node *node, void *data
> OVS_UNUSED)
>      if (!eng_ctx->ovnsb_idl_txn ||
>          !global_config->features.fdb_timestamp ||
>          time_msec() < waker->next_wake_msec) {
> -        return;
> +        return EN_STALE;
>      }
>
>      uint32_t limit = get_removal_limit(node, "fdb_removal_limit");
> @@ -570,7 +568,7 @@ en_fdb_aging_run(struct engine_node *node, void *data
> OVS_UNUSED)
>
>      aging_waker_schedule_next_wake(waker, ctx.next_wake_ms);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void *
> @@ -591,24 +589,22 @@ en_fdb_aging_cleanup(void *data OVS_UNUSED)
>   * if we there are updates, so it could process the other nodes, however
>   * the waker cannot be dependent on other node because it wouldn't be
>   * input node anymore. */
> -void
> -en_fdb_aging_waker_run(struct engine_node *node, void *data)
> +enum engine_node_state
> +en_fdb_aging_waker_run(struct engine_node *node OVS_UNUSED, void *data)
>  {
>      struct aging_waker *waker = data;
>
> -    engine_set_node_state(node, EN_UNCHANGED);
> -
>      if (!waker->should_schedule) {
> -        return;
> +        return EN_UNCHANGED;
>      }
>
>      if (time_msec() >= waker->next_wake_msec) {
>          waker->should_schedule = false;
> -        engine_set_node_state(node, EN_UPDATED);
> -        return;
> +        return EN_UPDATED;
>      }
>
>      poll_timer_wait_until(waker->next_wake_msec);
> +    return EN_UNCHANGED;
>  }
>
>  void *
> diff --git a/northd/aging.h b/northd/aging.h
> index 2cfe2fd44..76dadb951 100644
> --- a/northd/aging.h
> +++ b/northd/aging.h
> @@ -19,13 +19,15 @@
>  #include "lib/inc-proc-eng.h"
>
>  /* The MAC binding aging node functions. */
> -void en_mac_binding_aging_run(struct engine_node *node, void *data);
> +enum engine_node_state en_mac_binding_aging_run(struct engine_node *node,
> +                                                void *data);
>  void *en_mac_binding_aging_init(struct engine_node *node,
>                                  struct engine_arg *arg);
>  void en_mac_binding_aging_cleanup(void *data);
>
>  /* The MAC binding aging waker node functions. */
> -void en_mac_binding_aging_waker_run(struct engine_node *node, void *data);
> +enum engine_node_state en_mac_binding_aging_waker_run(struct engine_node
> *node,
> +                                                      void *data);
>  void *en_mac_binding_aging_waker_init(struct engine_node *node,
>                                        struct engine_arg *arg);
>  void en_mac_binding_aging_waker_cleanup(void *data);
> @@ -34,12 +36,13 @@ void en_mac_binding_aging_waker_cleanup(void *data);
>  unsigned int min_mac_binding_age_threshold(const char *opt);
>
>  /* The FDB aging node functions. */
> -void en_fdb_aging_run(struct engine_node *node, void *data);
> +enum engine_node_state en_fdb_aging_run(struct engine_node *node, void
> *data);
>  void *en_fdb_aging_init(struct engine_node *node, struct engine_arg *arg);
>  void en_fdb_aging_cleanup(void *data);
>
>  /* The FDB aging waker node functions. */
> -void en_fdb_aging_waker_run(struct engine_node *node, void *data);
> +enum engine_node_state en_fdb_aging_waker_run(struct engine_node *node,
> +                                              void *data);
>  void *en_fdb_aging_waker_init(struct engine_node *node,
>                                struct engine_arg *arg);
>  void en_fdb_aging_waker_cleanup(void *data);
> diff --git a/northd/en-acl-ids.c b/northd/en-acl-ids.c
> index 998b7a7fa..09c7955cb 100644
> --- a/northd/en-acl-ids.c
> +++ b/northd/en-acl-ids.c
> @@ -42,7 +42,7 @@ should_sync_to_sb(const struct nbrec_acl *nb_acl)
>                           false);
>  }
>
> -void
> +enum engine_node_state
>  en_acl_id_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -89,9 +89,9 @@ en_acl_id_run(struct engine_node *node, void *data
> OVS_UNUSED)
>          scan_start = new_id + 1;
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
>      uuidset_destroy(&visited);
>      bitmap_free(id_bitmap);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/northd/en-acl-ids.h b/northd/en-acl-ids.h
> index f878f55d9..cc0b58628 100644
> --- a/northd/en-acl-ids.h
> +++ b/northd/en-acl-ids.h
> @@ -8,6 +8,6 @@
>
>  bool northd_acl_id_handler(struct engine_node *node, void *data);
>  void *en_acl_id_init(struct engine_node *, struct engine_arg *);
> -void en_acl_id_run(struct engine_node *, void *data);
> +enum engine_node_state en_acl_id_run(struct engine_node *, void *data);
>  void en_acl_id_cleanup(void *data);
>  #endif
> diff --git a/northd/en-advertised-route-sync.c
> b/northd/en-advertised-route-sync.c
> index 0f5c5e403..8bc1d999e 100644
> --- a/northd/en-advertised-route-sync.c
> +++ b/northd/en-advertised-route-sync.c
> @@ -232,7 +232,7 @@ en_advertised_route_sync_cleanup(void *data OVS_UNUSED)
>      routes_sync_destroy(data);
>  }
>
> -void
> +enum engine_node_state
>  en_advertised_route_sync_run(struct engine_node *node, void *data
> OVS_UNUSED)
>  {
>      routes_sync_clear(data);
> @@ -258,7 +258,7 @@ en_advertised_route_sync_run(struct engine_node *node,
> void *data OVS_UNUSED)
>                                  routes_sync_data);
>
>      stopwatch_stop(ADVERTISED_ROUTE_SYNC_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  /* This function adds a new route for each entry in lr_nat record
> @@ -511,7 +511,7 @@ en_dynamic_routes_cleanup(void *data_)
>      hmap_destroy(&data->routes);
>  }
>
> -void
> +enum engine_node_state
>  en_dynamic_routes_run(struct engine_node *node, void *data)
>  {
>      struct dynamic_routes_data *dynamic_routes_data = data;
> @@ -544,7 +544,7 @@ en_dynamic_routes_run(struct engine_node *node, void
> *data)
>                                    &dynamic_routes_data->routes);
>      }
>      stopwatch_stop(DYNAMIC_ROUTES_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static void
> diff --git a/northd/en-advertised-route-sync.h
> b/northd/en-advertised-route-sync.h
> index 0290f08d2..64a2e9f1b 100644
> --- a/northd/en-advertised-route-sync.h
> +++ b/northd/en-advertised-route-sync.h
> @@ -34,9 +34,10 @@ bool advertised_route_sync_northd_change_handler(struct
> engine_node *,
>                                                   void *data);
>  void *en_advertised_route_sync_init(struct engine_node *, struct
> engine_arg *);
>  void en_advertised_route_sync_cleanup(void *data);
> -void en_advertised_route_sync_run(struct engine_node *, void *data);
> +enum engine_node_state en_advertised_route_sync_run(struct engine_node *,
> +                                                    void *data);
>
>  void *en_dynamic_routes_init(struct engine_node *, struct engine_arg *);
>  void en_dynamic_routes_cleanup(void *data);
> -void en_dynamic_routes_run(struct engine_node *, void *data);
> +enum engine_node_state en_dynamic_routes_run(struct engine_node *, void
> *data);
>  #endif /* EN_ADVERTISED_ROUTE_SYNC_H */
> diff --git a/northd/en-ecmp-nexthop.c b/northd/en-ecmp-nexthop.c
> index 8bc0f8168..ccdf5af41 100644
> --- a/northd/en-ecmp-nexthop.c
> +++ b/northd/en-ecmp-nexthop.c
> @@ -194,7 +194,7 @@ en_ecmp_nexthop_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -void
> +enum engine_node_state
>  en_ecmp_nexthop_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -222,6 +222,6 @@ en_ecmp_nexthop_run(struct engine_node *node, void
> *data OVS_UNUSED)
>              sbrec_ecmp_nexthop_delete(sb_ecmp_nexthop);
>          }
>      }
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
> diff --git a/northd/en-ecmp-nexthop.h b/northd/en-ecmp-nexthop.h
> index a6ece39de..6983b799f 100644
> --- a/northd/en-ecmp-nexthop.h
> +++ b/northd/en-ecmp-nexthop.h
> @@ -25,7 +25,7 @@
>  #include "lib/inc-proc-eng.h"
>
>  bool ecmp_nexthop_mac_binding_handler(struct engine_node *, void *data);
> -void en_ecmp_nexthop_run(struct engine_node *, void *data);
> +enum engine_node_state en_ecmp_nexthop_run(struct engine_node *, void
> *data);
>  void *en_ecmp_nexthop_init(struct engine_node *, struct engine_arg *);
>  void en_ecmp_nexthop_cleanup(void *data);
>  struct ovsdb_idl_index *ecmp_nexthop_index_create(struct ovsdb_idl *idl);
> diff --git a/northd/en-global-config.c b/northd/en-global-config.c
> index c103b137f..5f508d979 100644
> --- a/northd/en-global-config.c
> +++ b/northd/en-global-config.c
> @@ -61,12 +61,12 @@ en_global_config_init(struct engine_node *node
> OVS_UNUSED,
>      return data;
>  }
>
> -void
> +enum engine_node_state
>  en_global_config_run(struct engine_node *node , void *data)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
>      if (!eng_ctx->ovnnb_idl_txn || !eng_ctx->ovnsb_idl_txn) {
> -        return;
> +        return EN_STALE;
>      }
>
>      const struct nbrec_nb_global_table *nb_global_table =
> @@ -177,7 +177,7 @@ en_global_config_run(struct engine_node *node , void
> *data)
>      /* Set up SB_Global (depends on chassis features). */
>      update_sb_config_options_to_sbrec(config_data, sb);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void en_global_config_cleanup(void *data OVS_UNUSED)
> diff --git a/northd/en-global-config.h b/northd/en-global-config.h
> index de88db18b..40ba90bcb 100644
> --- a/northd/en-global-config.h
> +++ b/northd/en-global-config.h
> @@ -53,7 +53,7 @@ struct ed_type_global_config {
>  };
>
>  void *en_global_config_init(struct engine_node *, struct engine_arg *);
> -void en_global_config_run(struct engine_node *, void *data);
> +enum engine_node_state en_global_config_run(struct engine_node *, void
> *data);
>  void en_global_config_cleanup(void *data);
>  void en_global_config_clear_tracked_data(void *data);
>
> diff --git a/northd/en-group-ecmp-route.c b/northd/en-group-ecmp-route.c
> index c55bbdd8b..1c6524f2e 100644
> --- a/northd/en-group-ecmp-route.c
> +++ b/northd/en-group-ecmp-route.c
> @@ -367,7 +367,7 @@ group_ecmp_route(struct group_ecmp_route_data *data,
>      }
>  }
>
> -void
> +enum engine_node_state
>  en_group_ecmp_route_run(struct engine_node *node, void *_data)
>  {
>      struct group_ecmp_route_data *data = _data;
> @@ -383,7 +383,7 @@ en_group_ecmp_route_run(struct engine_node *node, void
> *_data)
>      group_ecmp_route(data, routes_data, learned_route_data);
>
>      stopwatch_stop(GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  static void
> diff --git a/northd/en-group-ecmp-route.h b/northd/en-group-ecmp-route.h
> index b85e6014e..d593d4e94 100644
> --- a/northd/en-group-ecmp-route.h
> +++ b/northd/en-group-ecmp-route.h
> @@ -90,7 +90,8 @@ struct group_ecmp_route_data {
>  void *en_group_ecmp_route_init(struct engine_node *, struct engine_arg *);
>  void en_group_ecmp_route_cleanup(void *data);
>  void en_group_ecmp_route_clear_tracked_data(void *data);
> -void en_group_ecmp_route_run(struct engine_node *, void *data);
> +enum engine_node_state en_group_ecmp_route_run(struct engine_node *,
> +                                               void *data);
>
>  bool group_ecmp_route_learned_route_change_handler(struct engine_node *,
>                                                     void *data);
> diff --git a/northd/en-lb-data.c b/northd/en-lb-data.c
> index 0e810eaab..4d1699500 100644
> --- a/northd/en-lb-data.c
> +++ b/northd/en-lb-data.c
> @@ -92,7 +92,7 @@ en_lb_data_init(struct engine_node *node OVS_UNUSED,
>      return data;
>  }
>
> -void
> +enum engine_node_state
>  en_lb_data_run(struct engine_node *node, void *data)
>  {
>      struct ed_type_lb_data *lb_data = (struct ed_type_lb_data *) data;
> @@ -113,7 +113,7 @@ en_lb_data_run(struct engine_node *node, void *data)
>      build_od_lb_map(nb_ls_table, nb_lr_table, &lb_data->ls_lb_map,
>                      &lb_data->lr_lb_map);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/northd/en-lb-data.h b/northd/en-lb-data.h
> index 9d20a539b..6a5fe169b 100644
> --- a/northd/en-lb-data.h
> +++ b/northd/en-lb-data.h
> @@ -110,7 +110,7 @@ struct ed_type_lb_data {
>  };
>
>  void *en_lb_data_init(struct engine_node *, struct engine_arg *);
> -void en_lb_data_run(struct engine_node *, void *data);
> +enum engine_node_state en_lb_data_run(struct engine_node *, void *data);
>  void en_lb_data_cleanup(void *data);
>  void en_lb_data_clear_tracked_data(void *data);
>
> diff --git a/northd/en-learned-route-sync.c
> b/northd/en-learned-route-sync.c
> index 79b8bf213..b8252ff11 100644
> --- a/northd/en-learned-route-sync.c
> +++ b/northd/en-learned-route-sync.c
> @@ -121,7 +121,7 @@ en_learned_route_sync_clear_tracked_data(void *data)
>      routes_sync_clear_tracked(data);
>  }
>
> -void
> +enum engine_node_state
>  en_learned_route_sync_run(struct engine_node *node, void *data)
>  {
>      routes_sync_clear(data);
> @@ -139,7 +139,7 @@ en_learned_route_sync_run(struct engine_node *node,
> void *data)
>                        &routes_sync_data->parsed_routes);
>
>      stopwatch_stop(LEARNED_ROUTE_SYNC_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>
> diff --git a/northd/en-learned-route-sync.h
> b/northd/en-learned-route-sync.h
> index b2d079621..c9ad14c9e 100644
> --- a/northd/en-learned-route-sync.h
> +++ b/northd/en-learned-route-sync.h
> @@ -48,6 +48,7 @@ bool
> learned_route_sync_sb_learned_route_change_handler(struct engine_node *,
>  void *en_learned_route_sync_init(struct engine_node *, struct engine_arg
> *);
>  void en_learned_route_sync_cleanup(void *data);
>  void en_learned_route_sync_clear_tracked_data(void *data);
> -void en_learned_route_sync_run(struct engine_node *, void *data);
> +enum engine_node_state en_learned_route_sync_run(struct engine_node *,
> +                                                 void *data);
>
>  #endif /* EN_LEARNED_ROUTE_SYNC_H */
> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
> index 1aac6bc74..da83f7fd8 100644
> --- a/northd/en-lflow.c
> +++ b/northd/en-lflow.c
> @@ -104,7 +104,8 @@ lflow_get_input_data(struct engine_node *node,
>      lflow_input->sampling_apps = &sampling_app_data->apps;
>  }
>
> -void en_lflow_run(struct engine_node *node, void *data)
> +enum engine_node_state
> +en_lflow_run(struct engine_node *node, void *data)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
>
> @@ -122,7 +123,7 @@ void en_lflow_run(struct engine_node *node, void *data)
>                   lflow_data->lflow_table);
>      stopwatch_stop(BUILD_LFLOWS_STOPWATCH_NAME, time_msec());
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> diff --git a/northd/en-lflow.h b/northd/en-lflow.h
> index c5c74b171..9c54cbbf5 100644
> --- a/northd/en-lflow.h
> +++ b/northd/en-lflow.h
> @@ -15,7 +15,7 @@ struct lflow_data {
>      struct lflow_table *lflow_table;
>  };
>
> -void en_lflow_run(struct engine_node *node, void *data);
> +enum engine_node_state en_lflow_run(struct engine_node *node, void *data);
>  void *en_lflow_init(struct engine_node *node, struct engine_arg *arg);
>  void en_lflow_cleanup(void *data);
>  bool lflow_northd_handler(struct engine_node *, void *data);
> diff --git a/northd/en-lr-nat.c b/northd/en-lr-nat.c
> index 44009ca6f..916a90c8f 100644
> --- a/northd/en-lr-nat.c
> +++ b/northd/en-lr-nat.c
> @@ -101,7 +101,7 @@ en_lr_nat_clear_tracked_data(void *data_)
>      hmapx_clear(&data->trk_data.crupdated);
>  }
>
> -void
> +enum engine_node_state
>  en_lr_nat_run(struct engine_node *node, void *data_)
>  {
>      struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> @@ -113,7 +113,7 @@ en_lr_nat_run(struct engine_node *node, void *data_)
>                         &northd_data->lr_ports);
>
>      stopwatch_stop(LR_NAT_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  /* Handler functions. */
> diff --git a/northd/en-lr-nat.h b/northd/en-lr-nat.h
> index a73933390..7de22f471 100644
> --- a/northd/en-lr-nat.h
> +++ b/northd/en-lr-nat.h
> @@ -118,7 +118,7 @@ struct ed_type_lr_nat_data {
>  void *en_lr_nat_init(struct engine_node *, struct engine_arg *);
>  void en_lr_nat_cleanup(void *data);
>  void en_lr_nat_clear_tracked_data(void *data);
> -void en_lr_nat_run(struct engine_node *, void *data);
> +enum engine_node_state en_lr_nat_run(struct engine_node *, void *data);
>
>  bool lr_nat_logical_router_handler(struct engine_node *, void *data);
>  bool lr_nat_northd_handler(struct engine_node *, void *data);
> @@ -134,4 +134,4 @@ lr_nat_has_tracked_data(struct lr_nat_tracked_data
> *trk_data) {
>      return !hmapx_is_empty(&trk_data->crupdated);
>  }
>
> -#endif /* EN_LR_NAT_H */
> \ No newline at end of file
> +#endif /* EN_LR_NAT_H */
> diff --git a/northd/en-lr-stateful.c b/northd/en-lr-stateful.c
> index f09691af6..15c8f83c2 100644
> --- a/northd/en-lr-stateful.c
> +++ b/northd/en-lr-stateful.c
> @@ -111,7 +111,7 @@ en_lr_stateful_clear_tracked_data(void *data_)
>      hmapx_clear(&data->trk_data.crupdated);
>  }
>
> -void
> +enum engine_node_state
>  en_lr_stateful_run(struct engine_node *node, void *data_)
>  {
>      struct lr_stateful_input input_data =
> lr_stateful_get_input_data(node);
> @@ -126,7 +126,7 @@ en_lr_stateful_run(struct engine_node *node, void
> *data_)
>                              input_data.lbgrp_datapaths_map);
>
>      stopwatch_stop(LR_STATEFUL_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> diff --git a/northd/en-lr-stateful.h b/northd/en-lr-stateful.h
> index e15c61e57..1a86f311d 100644
> --- a/northd/en-lr-stateful.h
> +++ b/northd/en-lr-stateful.h
> @@ -123,7 +123,7 @@ struct lr_stateful_input {
>  void *en_lr_stateful_init(struct engine_node *, struct engine_arg *);
>  void en_lr_stateful_cleanup(void *data);
>  void en_lr_stateful_clear_tracked_data(void *data);
> -void en_lr_stateful_run(struct engine_node *, void *data);
> +enum engine_node_state en_lr_stateful_run(struct engine_node *, void
> *data);
>
>  bool lr_stateful_northd_handler(struct engine_node *, void *data);
>  bool lr_stateful_lr_nat_handler(struct engine_node *, void *data);
> diff --git a/northd/en-ls-stateful.c b/northd/en-ls-stateful.c
> index 69cda5008..c2965a88c 100644
> --- a/northd/en-ls-stateful.c
> +++ b/northd/en-ls-stateful.c
> @@ -113,7 +113,7 @@ en_ls_stateful_clear_tracked_data(void *data_)
>      hmapx_clear(&data->trk_data.crupdated);
>  }
>
> -void
> +enum engine_node_state
>  en_ls_stateful_run(struct engine_node *node, void *data_)
>  {
>      struct ls_stateful_input input_data =
> ls_stateful_get_input_data(node);
> @@ -126,7 +126,7 @@ en_ls_stateful_run(struct engine_node *node, void
> *data_)
>                            input_data.ls_port_groups);
>
>      stopwatch_stop(LS_STATEFUL_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  /* Handler functions. */
> diff --git a/northd/en-ls-stateful.h b/northd/en-ls-stateful.h
> index 18a7398a6..275fa05b1 100644
> --- a/northd/en-ls-stateful.h
> +++ b/northd/en-ls-stateful.h
> @@ -103,7 +103,7 @@ struct ed_type_ls_stateful {
>  void *en_ls_stateful_init(struct engine_node *, struct engine_arg *);
>  void en_ls_stateful_cleanup(void *data);
>  void en_ls_stateful_clear_tracked_data(void *data);
> -void en_ls_stateful_run(struct engine_node *, void *data);
> +enum engine_node_state en_ls_stateful_run(struct engine_node *, void
> *data);
>
>  bool ls_stateful_northd_handler(struct engine_node *, void *data);
>  bool ls_stateful_port_group_handler(struct engine_node *, void *data);
> diff --git a/northd/en-meters.c b/northd/en-meters.c
> index 793a46335..a0352c34b 100644
> --- a/northd/en-meters.c
> +++ b/northd/en-meters.c
> @@ -52,7 +52,7 @@ en_sync_meters_cleanup(void *data_)
>      shash_destroy(&data->meter_groups);
>  }
>
> -void
> +enum engine_node_state
>  en_sync_meters_run(struct engine_node *node, void *data_)
>  {
>      struct sync_meters_data *data = data_;
> @@ -76,7 +76,7 @@ en_sync_meters_run(struct engine_node *node, void *data_)
>                  sb_meter_table, &data->meter_groups);
>
>      stopwatch_stop(SYNC_METERS_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  const struct nbrec_meter*
> diff --git a/northd/en-meters.h b/northd/en-meters.h
> index a1743282e..e0ef07fad 100644
> --- a/northd/en-meters.h
> +++ b/northd/en-meters.h
> @@ -28,7 +28,7 @@ struct sync_meters_data {
>
>  void *en_sync_meters_init(struct engine_node *, struct engine_arg *);
>  void en_sync_meters_cleanup(void *data);
> -void en_sync_meters_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_meters_run(struct engine_node *, void
> *data);
>
>  const struct nbrec_meter *fair_meter_lookup_by_name(
>      const struct shash *meter_groups,
> diff --git a/northd/en-multicast.c b/northd/en-multicast.c
> index 7f3a6077c..0522fcd9a 100644
> --- a/northd/en-multicast.c
> +++ b/northd/en-multicast.c
> @@ -114,7 +114,7 @@ en_multicast_igmp_init(struct engine_node *node
> OVS_UNUSED,
>      return data;
>  }
>
> -void
> +enum engine_node_state
>  en_multicast_igmp_run(struct engine_node *node, void *data_)
>  {
>      struct multicast_igmp_data *data = data_;
> @@ -142,7 +142,7 @@ en_multicast_igmp_run(struct engine_node *node, void
> *data_)
>                                  &northd_data->ls_datapaths.datapaths,
>                                  &northd_data->lr_datapaths.datapaths);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> diff --git a/northd/en-multicast.h b/northd/en-multicast.h
> index 131c01d65..9a0ebf533 100644
> --- a/northd/en-multicast.h
> +++ b/northd/en-multicast.h
> @@ -84,7 +84,7 @@ struct ovn_mcast_sw_stats {
>  };
>
>  void *en_multicast_igmp_init(struct engine_node *,struct engine_arg *);
> -void en_multicast_igmp_run(struct engine_node *, void *);
> +enum engine_node_state en_multicast_igmp_run(struct engine_node *, void
> *);
>  bool multicast_igmp_northd_handler(struct engine_node *, void *);
>  void en_multicast_igmp_cleanup(void *);
>  struct sbrec_multicast_group *create_sb_multicast_group(
> diff --git a/northd/en-northd-output.c b/northd/en-northd-output.c
> index e69a7eebb..879d16e49 100644
> --- a/northd/en-northd-output.c
> +++ b/northd/en-northd-output.c
> @@ -30,10 +30,11 @@ en_northd_output_init(struct engine_node *node
> OVS_UNUSED,
>      return NULL;
>  }
>
> -void
> -en_northd_output_run(struct engine_node *node, void *data OVS_UNUSED)
> +enum engine_node_state
> +en_northd_output_run(struct engine_node *node OVS_UNUSED,
> +                     void *data OVS_UNUSED)
>  {
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/northd/en-northd-output.h b/northd/en-northd-output.h
> index 783587cb6..399ff8125 100644
> --- a/northd/en-northd-output.h
> +++ b/northd/en-northd-output.h
> @@ -5,8 +5,8 @@
>
>  void *en_northd_output_init(struct engine_node *node OVS_UNUSED,
>                              struct engine_arg *arg OVS_UNUSED);
> -void en_northd_output_run(struct engine_node *node OVS_UNUSED,
> -                          void *data OVS_UNUSED);
> +enum engine_node_state en_northd_output_run(struct engine_node *,
> +                                            void *data OVS_UNUSED);
>
>  void en_northd_output_cleanup(void *data);
>  bool northd_output_sync_to_sb_handler(struct engine_node *node,
> diff --git a/northd/en-northd.c b/northd/en-northd.c
> index 7cea8863c..82db29427 100644
> --- a/northd/en-northd.c
> +++ b/northd/en-northd.c
> @@ -112,7 +112,7 @@ northd_get_input_data(struct engine_node *node,
>      input_data->features = &global_config->features;
>  }
>
> -void
> +enum engine_node_state
>  en_northd_run(struct engine_node *node, void *data)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -129,7 +129,7 @@ en_northd_run(struct engine_node *node, void *data)
>      ovnnb_db_run(&input_data, data, eng_ctx->ovnnb_idl_txn,
>                   eng_ctx->ovnsb_idl_txn);
>      stopwatch_stop(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> @@ -261,7 +261,7 @@ route_policies_northd_change_handler(struct
> engine_node *node,
>      return true;
>  }
>
> -void
> +enum engine_node_state
>  en_route_policies_run(struct engine_node *node, void *data)
>  {
>      struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> @@ -280,7 +280,7 @@ en_route_policies_run(struct engine_node *node, void
> *data)
>                               &route_policies_data->chain_ids);
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> @@ -312,7 +312,7 @@ routes_northd_change_handler(struct engine_node *node,
>      return true;
>  }
>
> -void
> +enum engine_node_state
>  en_routes_run(struct engine_node *node, void *data)
>  {
>      struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> @@ -338,10 +338,10 @@ en_routes_run(struct engine_node *node, void *data)
>                              &routes_data->bfd_active_connections);
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
> -void
> +enum engine_node_state
>  en_bfd_run(struct engine_node *node, void *data)
>  {
>      struct bfd_data *bfd_data = data;
> @@ -354,7 +354,7 @@ en_bfd_run(struct engine_node *node, void *data)
>      bfd_init(data);
>      build_bfd_map(nbrec_bfd_table, sbrec_bfd_table,
>                    &bfd_data->bfd_connections);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> @@ -377,7 +377,7 @@ bfd_sync_northd_change_handler(struct engine_node
> *node, void *data OVS_UNUSED)
>      return true;
>  }
>
> -void
> +enum engine_node_state
>  en_bfd_sync_run(struct engine_node *node, void *data)
>  {
>      struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> @@ -398,7 +398,7 @@ en_bfd_sync_run(struct engine_node *node, void *data)
>                     &route_policies_data->bfd_active_connections,
>                     &routes_data->bfd_active_connections,
>                     &bfd_sync_data->bfd_ports);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/northd/en-northd.h b/northd/en-northd.h
> index b676a0ad3..ad2ca671e 100644
> --- a/northd/en-northd.h
> +++ b/northd/en-northd.h
> @@ -9,7 +9,8 @@
>
>  #include "lib/inc-proc-eng.h"
>
> -void en_northd_run(struct engine_node *node OVS_UNUSED, void *data
> OVS_UNUSED);
> +enum engine_node_state en_northd_run(struct engine_node *node OVS_UNUSED,
> +                                     void *data OVS_UNUSED);
>  void *en_northd_init(struct engine_node *node OVS_UNUSED,
>                       struct engine_arg *arg);
>  void en_northd_cleanup(void *data);
> @@ -25,22 +26,23 @@ void *en_routes_init(struct engine_node *node
> OVS_UNUSED,
>  void en_route_policies_cleanup(void *data);
>  bool route_policies_northd_change_handler(struct engine_node *node,
>                                            void *data OVS_UNUSED);
> -void en_route_policies_run(struct engine_node *node, void *data);
> +enum engine_node_state en_route_policies_run(struct engine_node *node,
> +                                             void *data);
>  void *en_route_policies_init(struct engine_node *node OVS_UNUSED,
>                               struct engine_arg *arg OVS_UNUSED);
>  void en_routes_cleanup(void *data);
>  bool routes_northd_change_handler(struct engine_node *node,
>                                           void *data OVS_UNUSED);
> -void en_routes_run(struct engine_node *node, void *data);
> +enum engine_node_state en_routes_run(struct engine_node *node, void
> *data);
>  void *en_bfd_init(struct engine_node *node OVS_UNUSED,
>                    struct engine_arg *arg OVS_UNUSED);
>  void en_bfd_cleanup(void *data);
> -void en_bfd_run(struct engine_node *node, void *data);
> +enum engine_node_state en_bfd_run(struct engine_node *node, void *data);
>  void *en_bfd_sync_init(struct engine_node *node OVS_UNUSED,
>                         struct engine_arg *arg OVS_UNUSED);
>  bool bfd_sync_northd_change_handler(struct engine_node *node,
>                                      void *data OVS_UNUSED);
> -void en_bfd_sync_run(struct engine_node *node, void *data);
> +enum engine_node_state en_bfd_sync_run(struct engine_node *node, void
> *data);
>  void en_bfd_sync_cleanup(void *data OVS_UNUSED);
>
>  #endif /* EN_NORTHD_H */
> diff --git a/northd/en-port-group.c b/northd/en-port-group.c
> index 0de9dc5f6..45dd37b2c 100644
> --- a/northd/en-port-group.c
> +++ b/northd/en-port-group.c
> @@ -483,7 +483,7 @@ en_port_group_clear_tracked_data(void *data_)
>      data->ls_port_groups_sets_changed = true;
>  }
>
> -void
> +enum engine_node_state
>  en_port_group_run(struct engine_node *node, void *data_)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -505,7 +505,7 @@ en_port_group_run(struct engine_node *node, void
> *data_)
>                               eng_ctx->ovnsb_idl_txn);
>
>      stopwatch_stop(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec());
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  bool
> diff --git a/northd/en-port-group.h b/northd/en-port-group.h
> index 54014062c..5991fec15 100644
> --- a/northd/en-port-group.h
> +++ b/northd/en-port-group.h
> @@ -110,7 +110,7 @@ struct port_group_data {
>  void *en_port_group_init(struct engine_node *, struct engine_arg *);
>  void en_port_group_cleanup(void *data);
>  void en_port_group_clear_tracked_data(void *data);
> -void en_port_group_run(struct engine_node *, void *data);
> +enum engine_node_state en_port_group_run(struct engine_node *, void
> *data);
>
>  bool port_group_nb_port_group_handler(struct engine_node *, void *data);
>
> diff --git a/northd/en-sampling-app.c b/northd/en-sampling-app.c
> index e6c816c40..3ae0561de 100644
> --- a/northd/en-sampling-app.c
> +++ b/northd/en-sampling-app.c
> @@ -44,7 +44,7 @@ en_sampling_app_cleanup(void *data OVS_UNUSED)
>  {
>  }
>
> -void
> +enum engine_node_state
>  en_sampling_app_run(struct engine_node *node, void *data_)
>  {
>      const struct nbrec_sampling_app_table *nb_sampling_app_table =
> @@ -58,7 +58,7 @@ en_sampling_app_run(struct engine_node *node, void
> *data_)
>          sampling_app_table_add(&data->apps, sa);
>      }
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  uint8_t
> diff --git a/northd/en-sampling-app.h b/northd/en-sampling-app.h
> index a5b5ae422..a3e5c9c04 100644
> --- a/northd/en-sampling-app.h
> +++ b/northd/en-sampling-app.h
> @@ -44,7 +44,7 @@ struct ed_type_sampling_app_data {
>
>  void *en_sampling_app_init(struct engine_node *, struct engine_arg *);
>  void en_sampling_app_cleanup(void *data);
> -void en_sampling_app_run(struct engine_node *, void *data);
> +enum engine_node_state en_sampling_app_run(struct engine_node *, void
> *data);
>  uint8_t sampling_app_get_id(const struct sampling_app_table *,
>                              enum sampling_app);
>
> diff --git a/northd/en-sync-from-sb.c b/northd/en-sync-from-sb.c
> index 8c05239b4..3c39d001e 100644
> --- a/northd/en-sync-from-sb.c
> +++ b/northd/en-sync-from-sb.c
> @@ -43,7 +43,7 @@ en_sync_from_sb_init(struct engine_node *node OVS_UNUSED,
>      return NULL;
>  }
>
> -void
> +enum engine_node_state
>  en_sync_from_sb_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -58,6 +58,8 @@ en_sync_from_sb_run(struct engine_node *node, void *data
> OVS_UNUSED)
>                   sb_pb_table, sb_ha_ch_grp_table,
>                   &nd->ls_ports, &nd->lr_ports);
>      stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());
> +
> +    return EN_UNCHANGED;
>  }
>
>  bool
> diff --git a/northd/en-sync-from-sb.h b/northd/en-sync-from-sb.h
> index 1f0cfd2cd..78824ac67 100644
> --- a/northd/en-sync-from-sb.h
> +++ b/northd/en-sync-from-sb.h
> @@ -4,7 +4,7 @@
>  #include "lib/inc-proc-eng.h"
>
>  void *en_sync_from_sb_init(struct engine_node *, struct engine_arg *);
> -void en_sync_from_sb_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_from_sb_run(struct engine_node *, void
> *data);
>  void en_sync_from_sb_cleanup(void *data);
>  bool sync_from_sb_northd_handler(struct engine_node *, void *data
> OVS_UNUSED);
>
> diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
> index b6fb78ee7..38131dfc3 100644
> --- a/northd/en-sync-sb.c
> +++ b/northd/en-sync-sb.c
> @@ -65,10 +65,10 @@ en_sync_to_sb_init(struct engine_node *node OVS_UNUSED,
>      return NULL;
>  }
>
> -void
> -en_sync_to_sb_run(struct engine_node *node, void *data OVS_UNUSED)
> +enum engine_node_state
> +en_sync_to_sb_run(struct engine_node *node OVS_UNUSED, void *data
> OVS_UNUSED)
>  {
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> @@ -84,7 +84,7 @@ en_sync_to_sb_addr_set_init(struct engine_node *node
> OVS_UNUSED,
>      return NULL;
>  }
>
> -void
> +enum engine_node_state
>  en_sync_to_sb_addr_set_run(struct engine_node *node, void *data
> OVS_UNUSED)
>  {
>      const struct nbrec_address_set_table *nb_address_set_table =
> @@ -106,7 +106,7 @@ en_sync_to_sb_addr_set_run(struct engine_node *node,
> void *data OVS_UNUSED)
>                     &northd_data->lr_datapaths,
>                     global_config->svc_monitor_mac);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> @@ -278,7 +278,7 @@ en_sync_to_sb_lb_init(struct engine_node *node
> OVS_UNUSED,
>      return data;
>  }
>
> -void
> +enum engine_node_state
>  en_sync_to_sb_lb_run(struct engine_node *node, void *data_)
>  {
>      struct northd_data *northd_data = engine_get_input_data("northd",
> node);
> @@ -300,7 +300,7 @@ en_sync_to_sb_lb_run(struct engine_node *node, void
> *data_)
>                                 &northd_data->lr_datapaths,
>                                 &global_config->features);
>
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> @@ -359,7 +359,7 @@ en_sync_to_sb_pb_init(struct engine_node *node
> OVS_UNUSED,
>      return NULL;
>  }
>
> -void
> +enum engine_node_state
>  en_sync_to_sb_pb_run(struct engine_node *node, void *data OVS_UNUSED)
>  {
>      const struct engine_context *eng_ctx = engine_get_context();
> @@ -370,7 +370,7 @@ en_sync_to_sb_pb_run(struct engine_node *node, void
> *data OVS_UNUSED)
>      sync_pbs(eng_ctx->ovnsb_idl_txn, &northd_data->ls_ports,
>               &northd_data->lr_ports,
>               &lr_stateful_data->table);
> -    engine_set_node_state(node, EN_UPDATED);
> +    return EN_UPDATED;
>  }
>
>  void
> diff --git a/northd/en-sync-sb.h b/northd/en-sync-sb.h
> index f08565eee..6cfac7f86 100644
> --- a/northd/en-sync-sb.h
> +++ b/northd/en-sync-sb.h
> @@ -4,11 +4,12 @@
>  #include "lib/inc-proc-eng.h"
>
>  void *en_sync_to_sb_init(struct engine_node *, struct engine_arg *);
> -void en_sync_to_sb_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_to_sb_run(struct engine_node *, void
> *data);
>  void en_sync_to_sb_cleanup(void *data);
>
>  void *en_sync_to_sb_addr_set_init(struct engine_node *, struct engine_arg
> *);
> -void en_sync_to_sb_addr_set_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_to_sb_addr_set_run(struct engine_node *,
> +                                                  void *data);
>  void en_sync_to_sb_addr_set_cleanup(void *data);
>
>  bool sync_to_sb_addr_set_nb_address_set_handler(struct engine_node *,
> @@ -18,12 +19,12 @@ bool sync_to_sb_addr_set_nb_port_group_handler(struct
> engine_node *,
>
>
>  void *en_sync_to_sb_lb_init(struct engine_node *, struct engine_arg *);
> -void en_sync_to_sb_lb_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_to_sb_lb_run(struct engine_node *, void
> *data);
>  void en_sync_to_sb_lb_cleanup(void *data);
>  bool sync_to_sb_lb_northd_handler(struct engine_node *, void *data
> OVS_UNUSED);
>
>  void *en_sync_to_sb_pb_init(struct engine_node *, struct engine_arg *);
> -void en_sync_to_sb_pb_run(struct engine_node *, void *data);
> +enum engine_node_state en_sync_to_sb_pb_run(struct engine_node *, void
> *data);
>  void en_sync_to_sb_pb_cleanup(void *data);
>  bool sync_to_sb_pb_northd_handler(struct engine_node *, void *data
> OVS_UNUSED);
>
> --
> 2.47.0
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Looks good to me, thanks.

Acked-by: Ales Musil <amu...@redhat.com>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to