(reposting, sorry, I had dropped ovs-dev from CC by accident)

On 6/13/26 5:28 PM, Lucas Vargas Dias wrote:
> Hi Dumitru,
> 

Hi Lucas,

> You're right, I'm not using stale directly.
> I marked it because It was used in other parts of the code. Maybe it's
> useless. I'll test.
> 

OK, we'll definitely need a new version of this patch though.

> My problem is the number of openflows operations related to static
> routes. So I think for my case, I'll still need the incremental
> processing. But I can test with your patch.

Hmm, I wonder why openflows would change that wildly when one static
route is added.  That shouldn't be the case, only the affected route's
openflows should be added/updated/deleted.

> You can include me in CC.

Will do, thanks again!

> 
> Regards,
> Lucas
> 

Regards,
Dumitru

> Em sex., 12 de jun. de 2026, 19:21, Dumitru Ceara <[email protected]
> <mailto:[email protected]>> escreveu:
> 
>     On 6/11/26 11:06 PM, Lucas Vargas Dias wrote:
>     > Create a handler for static routes. It handles update, create or
>     > delete.
>     > Full recompute is triggered when update bfd column for static route.
>     >
>     > Test with 2000 static routes created in the same logical router
>     > and add a new one:
>     > Without the incremental processing:
>     > ovn-nbctl --print-wait-time --wait=sb lr-route-add lr1-2
>     10.0.0.1/32 <http://10.0.0.1/32> 192.168.20.2
>     > Time spent on processing nb_cfg 4:
>     >       ovn-northd delay before processing:     4ms
>     >       ovn-northd completion:                  62ms
>     >
>     > With the incremental processing:
>     > ovn-nbctl --print-wait-time --wait=sb lr-route-add lr1-2
>     10.0.0.1/32 <http://10.0.0.1/32> 192.168.20.2
>     > Time spent on processing nb_cfg 6:
>     >       ovn-northd delay before processing:     4ms
>     >       ovn-northd completion:                  21ms
>     >
>     > Test with 2000 static routes created in the same logical router
>     > and delete one:
>     > Without the incremental processing:
>     > ovn-nbctl --print-wait-time --wait=sb lr-route-del lr1-2
>     10.0.0.1/32 <http://10.0.0.1/32> 192.168.20.2
>     > Time spent on processing nb_cfg 5:
>     >       ovn-northd delay before processing:     3ms
>     >       ovn-northd completion:                  62ms
>     >
>     > With the incremental processing:
>     > ovn-nbctl --print-wait-time --wait=sb lr-route-del lr1-2
>     10.0.0.1/32 <http://10.0.0.1/32> 192.168.20.2
>     > Time spent on processing nb_cfg 9:
>     >       ovn-northd delay before processing:     2ms
>     >       ovn-northd completion:                  32ms
>     >
>     > Signed-off-by: Lucas Vargas Dias <[email protected]>
>     > ---
> 
>     Hi Lucas,
> 
>     I wanted to mention that I didn't review this new version yet but I did
>     spot a bunch of bad issues in the way we handle recomputations of
>     en_route and en_route_policies.  I had initially posted:
> 
>     https://mail.openvswitch.org/pipermail/ovs-dev/2026-June/433164.html
>     <https://mail.openvswitch.org/pipermail/ovs-dev/2026-June/433164.html>
> 
>     but realized there's even more to gain and I am working on a v2:
>     https://github.com/dceara/ovn/commits/refs/heads/improve-northd-
>     route-recompute-v2/ <https://github.com/dceara/ovn/commits/refs/
>     heads/improve-northd-route-recompute-v2/>
> 
>     In that branch I have reworked the parsed_route_hash() as well but I
>     think what you have in patch 1/2 might be better.
> 
>     However, in my branch, I'm removing the parsed_route "stale" field as
>     it's not really needed for the recompute case:
> 
>     https://github.com/dceara/ovn/commit/edab614 <https://github.com/
>     dceara/ovn/commit/edab614>
> 
>     And it improves the recompute case significantly, for 1.6K routers with
>     a total number of 28K routes.
> 
>     Before the change:
>       node: routes, recompute (forced) took 5841ms
>     After the change:
>       node: routes, recompute (forced) took 177ms
> 
>     Now I'm really confused about how the "stale" field is used in your
>     patch.  It doesn't seem to be checked anywhere.
> 
>     I'll probably apply patch 1/2 of your series to main next week and
>     rebase my series on top of that and post it for review too.  I'll CC you
>     on it so we can sync up about the right way (if we still need one) to do
>     incremental processing for static routes.
> 
>     Regards,
>     Dumitru
> 
>     >  northd/en-group-ecmp-route.c     |  54 +++++++++++
>     >  northd/en-group-ecmp-route.h     |   4 +
>     >  northd/en-lflow.c                |  20 ++++
>     >  northd/en-lflow.h                |   2 +
>     >  northd/en-northd.c               | 154 ++++++++++++++++++++++++++
>     +++--
>     >  northd/en-northd.h               |   3 +
>     >  northd/inc-proc-northd.c         |  13 ++-
>     >  northd/northd.c                  | 142 +++++++++++++++++++++-------
>     >  northd/northd.h                  |  41 +++++++-
>     >  tests/ovn-inc-proc-graph-dump.at <http://ovn-inc-proc-graph-
>     dump.at> |   6 +-
>     >  tests/ovn-northd.at <http://ovn-northd.at>              | 128 +++
>     +++++++++++++++++++---
>     >  tests/system-ovn.at <http://system-ovn.at>              |   5 +-
>     >  12 files changed, 514 insertions(+), 58 deletions(-)
>     >
>     > diff --git a/northd/en-group-ecmp-route.c b/northd/en-group-ecmp-
>     route.c
>     > index c4c93fd84..892ce29b7 100644
>     > --- a/northd/en-group-ecmp-route.c
>     > +++ b/northd/en-group-ecmp-route.c
>     > @@ -519,3 +519,57 @@
>     group_ecmp_route_learned_route_change_handler(struct engine_node
>     *eng_node,
>     >      }
>     >      return EN_HANDLED_UNCHANGED;
>     >  }
>     > +
>     > +enum engine_input_handler_result
>     > +group_ecmp_static_route_change_handler(struct engine_node *eng_node,
>     > +                                       void *_data)
>     > +{
>     > +    struct routes_data *routes_data
>     > +        = engine_get_input_data("routes", eng_node);
>     > +    struct group_ecmp_route_data *data = _data;
>     > +    if (!routes_data->tracked) {
>     > +        data->tracked = false;
>     > +        return EN_UNHANDLED;
>     > +    }
>     > +
>     > +    struct parsed_route *pr;
>     > +    struct hmapx updated_routes = HMAPX_INITIALIZER(&updated_routes);
>     > +
>     > +    const struct hmapx_node *hmapx_node;
>     > +    HMAPX_FOR_EACH (hmapx_node,
>     > +                    &routes_data-
>     >trk_data.trk_deleted_parsed_route) {
>     > +        pr = hmapx_node->data;
>     > +        if (!handle_deleted_route(data, pr, &updated_routes)) {
>     > +            hmapx_destroy(&updated_routes);
>     > +            return EN_UNHANDLED;
>     > +        }
>     > +
>     > +        parsed_route_free(pr);
>     > +    }
>     > +
>     > +    HMAPX_FOR_EACH (hmapx_node,
>     > +                    &routes_data-
>     >trk_data.trk_crupdated_parsed_route) {
>     > +        pr = hmapx_node->data;
>     > +        handle_added_route(data, pr, &updated_routes);
>     > +    }
>     > +
>     > +    HMAPX_FOR_EACH (hmapx_node, &updated_routes) {
>     > +        struct group_ecmp_datapath *node = hmapx_node->data;
>     > +        if (hmap_is_empty(&node->unique_routes) &&
>     > +                hmap_is_empty(&node->ecmp_groups)) {
>     > +            hmapx_add(&data->trk_data.deleted_datapath_routes, node);
>     > +            hmap_remove(&data->datapaths, &node->hmap_node);
>     > +        } else {
>     > +            hmapx_add(&data->trk_data.crupdated_datapath_routes,
>     node);
>     > +        }
>     > +    }
>     > +
>     > +    hmapx_destroy(&updated_routes);
>     > +
>     > +    if (!hmapx_is_empty(&data->trk_data.crupdated_datapath_routes) ||
>     > +        !hmapx_is_empty(&data->trk_data.deleted_datapath_routes)) {
>     > +        data->tracked = true;
>     > +        return EN_HANDLED_UPDATED;
>     > +    }
>     > +    return EN_HANDLED_UNCHANGED;
>     > +}
>     > diff --git a/northd/en-group-ecmp-route.h b/northd/en-group-ecmp-
>     route.h
>     > index d4a3248d0..246ca06bf 100644
>     > --- a/northd/en-group-ecmp-route.h
>     > +++ b/northd/en-group-ecmp-route.h
>     > @@ -98,6 +98,10 @@ enum engine_input_handler_result
>     >  group_ecmp_route_learned_route_change_handler(struct engine_node *,
>     >                                                void *data);
>     > 
>     > +enum engine_input_handler_result
>     > +group_ecmp_static_route_change_handler(struct engine_node *,
>     > +                                       void *data);
>     > +
>     >  struct group_ecmp_datapath *group_ecmp_datapath_lookup(
>     >      const struct group_ecmp_route_data *data,
>     >      const struct ovn_datapath *od);
>     > diff --git a/northd/en-lflow.c b/northd/en-lflow.c
>     > index 8cb987777..12dd9af6f 100644
>     > --- a/northd/en-lflow.c
>     > +++ b/northd/en-lflow.c
>     > @@ -268,6 +268,21 @@ lflow_multicast_igmp_handler(struct
>     engine_node *node, void *data)
>     >      return EN_HANDLED_UPDATED;
>     >  }
>     > 
>     > +enum engine_input_handler_result
>     > +lflow_group_route_change_handler(struct engine_node *node,
>     > +                                 void *data OVS_UNUSED)
>     > +{
>     > +    struct routes_data *route_data =
>     > +        engine_get_input_data("routes", node);
>     > +
>     > +    /* If we do not have tracked data we need to recompute. */
>     > +    if (!route_data->tracked) {
>     > +        return EN_UNHANDLED;
>     > +    }
>     > +
>     > +    return EN_HANDLED_UNCHANGED;
>     > +}
>     > +
>     >  enum engine_input_handler_result
>     >  lflow_group_ecmp_route_change_handler(struct engine_node *node,
>     >                                        void *data OVS_UNUSED)
>     > @@ -317,6 +332,11 @@ lflow_group_ecmp_route_change_handler(struct
>     engine_node *node,
>     >              route_node->od, lflow_data->lflow_table,
>     >              route_node, lflow_input.bfd_ports);
>     > 
>     > +        build_arp_request_flows_for_lrouter(route_node->od,
>     > +                                            lflow_data->lflow_table,
>     > +                                            lflow_input.meter_groups,
>     > +                                            route_node->lflow_ref);
>     > +
>     >          bool handled = lflow_ref_sync_lflows(
>     >              route_node->lflow_ref, lflow_data->lflow_table,
>     >              eng_ctx->ovnsb_idl_txn, lflow_input.dps,
>     > diff --git a/northd/en-lflow.h b/northd/en-lflow.h
>     > index 99bcfda15..31ccc0925 100644
>     > --- a/northd/en-lflow.h
>     > +++ b/northd/en-lflow.h
>     > @@ -29,5 +29,7 @@ lflow_multicast_igmp_handler(struct engine_node
>     *node, void *data);
>     >  enum engine_input_handler_result
>     >  lflow_group_ecmp_route_change_handler(struct engine_node *node,
>     void *data);
>     >  enum engine_input_handler_result
>     > +lflow_group_route_change_handler(struct engine_node *node, void
>     *data);
>     > +enum engine_input_handler_result
>     >  lflow_ic_learned_svc_mons_handler(struct engine_node *node, void
>     *data);
>     >  #endif /* EN_LFLOW_H */
>     > diff --git a/northd/en-northd.c b/northd/en-northd.c
>     > index c34818dba..9d247ffa6 100644
>     > --- a/northd/en-northd.c
>     > +++ b/northd/en-northd.c
>     > @@ -207,7 +207,8 @@ northd_nb_logical_router_handler(struct
>     engine_node *node,
>     >      }
>     > 
>     >      if (northd_has_lr_nats_in_tracked_data(&nd->trk_data) ||
>     > -        northd_has_lrouters_in_tracked_data(&nd->trk_data)) {
>     > +        northd_has_lrouters_in_tracked_data(&nd->trk_data) ||
>     > +        northd_has_lr_route_in_tracked_data(&nd->trk_data)) {
>     >          return EN_HANDLED_UPDATED;
>     >      }
>     > 
>     > @@ -329,7 +330,7 @@ en_route_policies_run(struct engine_node
>     *node, void *data)
>     > 
>     >  enum engine_input_handler_result
>     >  routes_northd_change_handler(struct engine_node *node,
>     > -                                    void *data OVS_UNUSED)
>     > +                             void *data OVS_UNUSED)
>     >  {
>     >      struct northd_data *northd_data =
>     engine_get_input_data("northd", node);
>     >      if (!northd_has_tracked_data(&northd_data->trk_data)) {
>     > @@ -347,14 +348,148 @@ routes_northd_change_handler(struct
>     engine_node *node,
>     >       *      Note: When we add I-P to the created/deleted logical
>     routers or
>     >       *      logical router ports, we need to revisit this handler.
>     >       *
>     > -     *      This node also accesses the static routes of the
>     logical router.
>     > -     *      When these static routes gets updated, en_northd
>     engine recomputes
>     > -     *      and so does this node.
>     > -     *      Note: When we add I-P to handle static routes
>     changes, we need
>     > -     *      to revisit this handler.
>     >       */
>     >      return EN_HANDLED_UNCHANGED;
>     >  }
>     > +enum engine_input_handler_result
>     > +routes_static_route_change_handler(struct engine_node *node,
>     > +                                   void *data)
>     > +{
>     > +    struct routes_data *routes_data = data;
>     > +    const struct nbrec_logical_router_static_route_table *
>     > +      nb_lr_static_route_table =
>     > +   
>     EN_OVSDB_GET(engine_get_input("NB_logical_router_static_route", node));
>     > +
>     > +    struct northd_data *northd_data =
>     engine_get_input_data("northd", node);
>     > +    struct bfd_data *bfd_data = engine_get_input_data("bfd", node);
>     > +    struct parsed_route *pr;
>     > +    const struct nbrec_logical_router_static_route
>     *changed_static_route;
>     > +    NBREC_LOGICAL_ROUTER_STATIC_ROUTE_TABLE_FOR_EACH_TRACKED (
>     > +                            changed_static_route,
>     nb_lr_static_route_table) {
>     > +
>     > +        bool is_deleted =
>     nbrec_logical_router_static_route_is_deleted(
>     > +                                                       
>     changed_static_route);
>     > +        bool is_new = nbrec_logical_router_static_route_is_new(
>     > +                                                       
>     changed_static_route);
>     > +
>     > +
>     > +        if (is_new && is_deleted) {
>     > +            continue;
>     > +        }
>     > +
>     > +        if (is_new) {
>     > +            struct ovn_datapath *od =
>     ovn_datapath_find_by_static_route(
>     > +                                        &northd_data-
>     >trk_data.trk_lrs_routes,
>     > +                                        &changed_static_route-
>     >header_.uuid);
>     > +            if (!od) {
>     > +                continue;
>     > +            }
>     > +            pr = parsed_routes_add_static(od, &northd_data->lr_ports,
>     > +                                        changed_static_route,
>     > +                                        &bfd_data->bfd_connections,
>     > +                                        &routes_data->parsed_routes,
>     > +                                        &routes_data->route_tables,
>     > +                                        &routes_data-
>     >bfd_active_connections);
>     > +            if (!pr) {
>     > +                return EN_UNHANDLED;
>     > +            }
>     > +            hmapx_add(&routes_data-
>     >trk_data.trk_crupdated_parsed_route,
>     > +                       pr);
>     > +        }
>     > +
>     > +        if (is_deleted) {
>     > +            pr = parsed_route_lookup_by_source(
>     > +                                            ROUTE_SOURCE_STATIC,
>     > +                                           
>     &changed_static_route->header_,
>     > +                                            &routes_data-
>     >parsed_routes);
>     > +            if (!pr) {
>     > +                pr =
>     parsed_route_lookup_by_source(ROUTE_SOURCE_IC_DYNAMIC,
>     > +                                           
>     &changed_static_route->header_,
>     > +                                            &routes_data-
>     >parsed_routes);
>     > +            }
>     > +            if (pr) {
>     > +                pr->stale = true;
>     > +                hmapx_add(&routes_data-
>     >trk_data.trk_deleted_parsed_route, pr);
>     > +                hmap_remove(&routes_data->parsed_routes, &pr-
>     >key_node);
>     > +
>     > +            }
>     > +            continue;
>     > +        }
>     > +
>     > +        if (!is_new &&
>     > +            (nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                    NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_NEXTHOP)
>     > +            || nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                    NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_IP_PREFIX)
>     > +            || nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                   
>     NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_OUTPUT_PORT)
>     > +            || nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                    NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_POLICY)
>     > +            || nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                   
>     NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_ROUTE_TABLE)
>     > +            || nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                   
>     NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_SELECTION_FIELDS)
>     > +            ||  nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                   
>     NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_OPTIONS))) {
>     > +            pr = parsed_route_lookup_by_source(
>     > +                                            ROUTE_SOURCE_STATIC,
>     > +                                           
>     &changed_static_route->header_,
>     > +                                            &routes_data-
>     >parsed_routes);
>     > +            if (!pr) {
>     > +                pr = parsed_route_lookup_by_source(
>     > +                                               
>     ROUTE_SOURCE_IC_DYNAMIC,
>     > +                                               
>     &changed_static_route->header_,
>     > +                                                &routes_data-
>     >parsed_routes);
>     > +            }
>     > +
>     > +            if (!pr || !pr->od) {
>     > +                return EN_UNHANDLED;
>     > +            }
>     > +            struct parsed_route *old_pr = pr;
>     > +            struct hmapx_node *route_node =
>     > +                hmapx_add(&routes_data-
>     >trk_data.trk_deleted_parsed_route,
>     > +                          old_pr);
>     > +            hmap_remove(&routes_data->parsed_routes, &old_pr-
>     >key_node);
>     > +            pr = parsed_routes_add_static(old_pr->od,
>     &northd_data->lr_ports,
>     > +                                        changed_static_route,
>     > +                                        &bfd_data->bfd_connections,
>     > +                                        &routes_data->parsed_routes,
>     > +                                        &routes_data->route_tables,
>     > +                                        &routes_data-
>     >bfd_active_connections);
>     > +            if (!pr) {
>     > +                hmapx_delete(&routes_data-
>     >trk_data.trk_deleted_parsed_route,
>     > +                             route_node);
>     > +                return EN_UNHANDLED;
>     > +            }
>     > +            old_pr->stale = true;
>     > +
>     > +            hmapx_add(&routes_data-
>     >trk_data.trk_crupdated_parsed_route,
>     > +                       pr);
>     > +        }
>     > +
>     > +        if (!is_new && nbrec_logical_router_static_route_is_updated(
>     > +                    changed_static_route,
>     > +                    NBREC_LOGICAL_ROUTER_STATIC_ROUTE_COL_BFD))
>     > +        {
>     > +                return EN_UNHANDLED;
>     > +        }
>     > +    }
>     > +
>     > +    if (!hmapx_is_empty(&routes_data-
>     >trk_data.trk_crupdated_parsed_route) ||
>     > +        !hmapx_is_empty(&routes_data-
>     >trk_data.trk_deleted_parsed_route)) {
>     > +        routes_data->tracked = true;
>     > +        return EN_HANDLED_UPDATED;
>     > +    }
>     > +
>     > +    return EN_HANDLED_UNCHANGED;
>     > +}
>     > 
>     >  enum engine_node_state
>     >  en_routes_run(struct engine_node *node, void *data)
>     > @@ -590,6 +725,11 @@ en_routes_cleanup(void *data)
>     >      routes_destroy(data);
>     >  }
>     > 
>     > +void
>     > +en_routes_clear_tracked_data(void *data)
>     > +{
>     > +    routes_clear_tracked(data);
>     > +}
>     >  void
>     >  en_bfd_cleanup(void *data)
>     >  {
>     > diff --git a/northd/en-northd.h b/northd/en-northd.h
>     > index 7794739b9..8da8b7ceb 100644
>     > --- a/northd/en-northd.h
>     > +++ b/northd/en-northd.h
>     > @@ -39,9 +39,12 @@ 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_clear_tracked_data(void *data);
>     >  void en_routes_cleanup(void *data);
>     >  enum engine_input_handler_result
>     >  routes_northd_change_handler(struct engine_node *node, void *data
>     OVS_UNUSED);
>     > +enum engine_input_handler_result
>     > +routes_static_route_change_handler(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);
>     > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
>     > index a2b464411..1b6bdf322 100644
>     > --- a/northd/inc-proc-northd.c
>     > +++ b/northd/inc-proc-northd.c
>     > @@ -75,7 +75,9 @@ static unixctl_cb_func chassis_features_list;
>     >      NB_NODE(sampling_app) \
>     >      NB_NODE(network_function) \
>     >      NB_NODE(network_function_group) \
>     > -    NB_NODE(logical_switch_port_health_check)
>     > +    NB_NODE(logical_switch_port_health_check) \
>     > +    NB_NODE(logical_router_static_route)
>     > +
>     > 
>     >      enum nb_engine_node {
>     >  #define NB_NODE(NAME) NB_##NAME,
>     > @@ -177,7 +179,7 @@ static ENGINE_NODE(lr_nat, CLEAR_TRACKED_DATA);
>     >  static ENGINE_NODE(lr_stateful, CLEAR_TRACKED_DATA);
>     >  static ENGINE_NODE(ls_stateful, CLEAR_TRACKED_DATA);
>     >  static ENGINE_NODE(route_policies);
>     > -static ENGINE_NODE(routes);
>     > +static ENGINE_NODE(routes, CLEAR_TRACKED_DATA);
>     >  static ENGINE_NODE(bfd);
>     >  static ENGINE_NODE(bfd_sync, SB_WRITE);
>     >  static ENGINE_NODE(ecmp_nexthop, SB_WRITE);
>     > @@ -336,6 +338,8 @@ void inc_proc_northd_init(struct
>     ovsdb_idl_loop *nb,
>     >      engine_add_input(&en_routes, &en_bfd, NULL);
>     >      engine_add_input(&en_routes, &en_northd,
>     >                       routes_northd_change_handler);
>     > +    engine_add_input(&en_routes, &en_nb_logical_router_static_route,
>     > +                     routes_static_route_change_handler);
>     > 
>     >      engine_add_input(&en_bfd_sync, &en_bfd, NULL);
>     >      engine_add_input(&en_bfd_sync, &en_nb_bfd, NULL);
>     > @@ -375,7 +379,8 @@ void inc_proc_northd_init(struct
>     ovsdb_idl_loop *nb,
>     >      engine_add_input(&en_learned_route_sync, &en_northd,
>     >                       learned_route_sync_northd_change_handler);
>     > 
>     > -    engine_add_input(&en_group_ecmp_route, &en_routes, NULL);
>     > +    engine_add_input(&en_group_ecmp_route, &en_routes,
>     > +                     group_ecmp_static_route_change_handler);
>     >      engine_add_input(&en_group_ecmp_route, &en_learned_route_sync,
>     >                       group_ecmp_route_learned_route_change_handler);
>     > 
>     > @@ -394,7 +399,7 @@ void inc_proc_northd_init(struct
>     ovsdb_idl_loop *nb,
>     >      engine_add_input(&en_lflow, &en_sb_logical_dp_group, NULL);
>     >      engine_add_input(&en_lflow, &en_bfd_sync, NULL);
>     >      engine_add_input(&en_lflow, &en_route_policies, NULL);
>     > -    engine_add_input(&en_lflow, &en_routes, NULL);
>     > +    engine_add_input(&en_lflow, &en_routes,
>     lflow_group_route_change_handler);
>     >      /* XXX: The incremental processing only supports changes to
>     learned routes.
>     >       * All other changes trigger a full recompute. */
>     >      engine_add_input(&en_lflow, &en_group_ecmp_route,
>     > diff --git a/northd/northd.c b/northd/northd.c
>     > index 99aaa19df..85312916c 100644
>     > --- a/northd/northd.c
>     > +++ b/northd/northd.c
>     > @@ -659,6 +659,26 @@ ovn_datapath_find_by_key(struct hmap
>     *datapaths, uint32_t dp_key)
>     >      return NULL;
>     >  }
>     > 
>     > +struct ovn_datapath *
>     > +ovn_datapath_find_by_static_route(struct hmapx *datapaths,
>     > +                                  const struct uuid *route_uuid)
>     > +{
>     > +
>     > +    struct hmapx_node *hmapx_node;
>     > +    HMAPX_FOR_EACH (hmapx_node, datapaths) {
>     > +        struct ovn_datapath *od = hmapx_node->data;
>     > +        if (od->nbr) {
>     > +            for (int i = 0; i < od->nbr->n_static_routes; i++) {
>     > +                struct nbrec_logical_router_static_route
>     *static_route =
>     > +                    od->nbr->static_routes[i];
>     > +                if (uuid_equals(route_uuid, &static_route-
>     >header_.uuid)) {
>     > +                    return od;
>     > +                }
>     > +            }
>     > +        }
>     > +    }
>     > +    return NULL;
>     > +}
>     >  struct ovn_datapath *
>     >  ovn_datapath_from_sbrec_(const struct hmap *datapaths,
>     >                           const struct sbrec_datapath_binding *sb)
>     > @@ -4522,6 +4542,7 @@ destroy_northd_data_tracked_changes(struct
>     northd_data *nd)
>     >      destroy_tracked_ovn_ports(&trk_changes->trk_lsps);
>     >      destroy_tracked_lbs(&trk_changes->trk_lbs);
>     >      hmapx_clear(&trk_changes->trk_nat_lrs);
>     > +    hmapx_clear(&trk_changes->trk_lrs_routes);
>     >      hmapx_clear(&trk_changes->ls_with_changed_lbs);
>     >      hmapx_clear(&trk_changes->ls_with_changed_acls);
>     >      hmapx_clear(&trk_changes->ls_with_changed_ipam);
>     > @@ -4545,6 +4566,7 @@ init_northd_tracked_data(struct northd_data *nd)
>     >      hmapx_init(&trk_data->trk_lbs.crupdated);
>     >      hmapx_init(&trk_data->trk_lbs.deleted);
>     >      hmapx_init(&trk_data->trk_nat_lrs);
>     > +    hmapx_init(&trk_data->trk_lrs_routes);
>     >      hmapx_init(&trk_data->ls_with_changed_lbs);
>     >      hmapx_init(&trk_data->ls_with_changed_acls);
>     >      hmapx_init(&trk_data->ls_with_changed_ipam);
>     > @@ -4563,6 +4585,7 @@ destroy_northd_tracked_data(struct
>     northd_data *nd)
>     >      hmapx_destroy(&trk_data->trk_lbs.crupdated);
>     >      hmapx_destroy(&trk_data->trk_lbs.deleted);
>     >      hmapx_destroy(&trk_data->trk_nat_lrs);
>     > +    hmapx_destroy(&trk_data->trk_lrs_routes);
>     >      hmapx_destroy(&trk_data->ls_with_changed_lbs);
>     >      hmapx_destroy(&trk_data->ls_with_changed_acls);
>     >      hmapx_destroy(&trk_data->ls_with_changed_ipam);
>     > @@ -5387,7 +5410,8 @@ lr_changes_can_be_handled(const struct
>     nbrec_logical_router *lr)
>     >          if (nbrec_logical_router_is_updated(lr, col)) {
>     >              if (col == NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER
>     >                  || col ==
>     NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER_GROUP
>     > -                || col == NBREC_LOGICAL_ROUTER_COL_NAT) {
>     > +                || col == NBREC_LOGICAL_ROUTER_COL_NAT
>     > +                || col == NBREC_LOGICAL_ROUTER_COL_STATIC_ROUTES) {
>     >                  continue;
>     >              }
>     >              return false;
>     > @@ -5412,12 +5436,7 @@ lr_changes_can_be_handled(const struct
>     nbrec_logical_router *lr)
>     >              return false;
>     >          }
>     >      }
>     > -    for (size_t i = 0; i < lr->n_static_routes; i++) {
>     > -        if (nbrec_logical_router_static_route_row_get_seqno(
>     > -            lr->static_routes[i], OVSDB_IDL_CHANGE_MODIFY) > 0) {
>     > -            return false;
>     > -        }
>     > -    }
>     > +
>     >      return true;
>     >  }
>     > 
>     > @@ -5443,6 +5462,27 @@ is_lr_nats_changed(const struct
>     nbrec_logical_router *nbr) {
>     >              || is_lr_nats_seqno_changed(nbr));
>     >  }
>     > 
>     > +static bool
>     > +is_lr_static_routes_seqno_changed(const struct
>     nbrec_logical_router *nbr)
>     > +{
>     > +    for (size_t i = 0; i < nbr->n_static_routes; i++) {
>     > +        if (nbrec_logical_router_static_route_row_get_seqno(
>     > +                        nbr->static_routes[i],
>     OVSDB_IDL_CHANGE_MODIFY) > 0) {
>     > +            return true;
>     > +        }
>     > +    }
>     > +
>     > +    return false;
>     > +}
>     > +
>     > +static bool
>     > +is_lr_static_routes_changed(const struct nbrec_logical_router *nbr) {
>     > +    return nbrec_logical_router_is_updated(nbr,
>     > +                                 
>      NBREC_LOGICAL_ROUTER_COL_STATIC_ROUTES)
>     > +           || is_lr_static_routes_seqno_changed(nbr);
>     > +}
>     > +
>     > +
>     >  /* Return true if changes are handled incrementally, false otherwise.
>     >   *
>     >   * Note: Changes to load balancer and load balancer groups
>     associated with
>     > @@ -5514,6 +5554,22 @@ northd_handle_lr_changes(const struct
>     northd_input *ni,
>     > 
>     >              hmapx_add(&nd->trk_data.trk_nat_lrs, od);
>     >          }
>     > +
>     > +        /* Static Route was added or deleted. */
>     > +        if (is_lr_static_routes_changed(changed_lr)) {
>     > +            struct ovn_datapath *od = ovn_datapath_find_(
>     > +                                    &nd->lr_datapaths.datapaths,
>     > +                                    &changed_lr->header_.uuid);
>     > +
>     > +            if (!od) {
>     > +                static struct vlog_rate_limit rl =
>     VLOG_RATE_LIMIT_INIT(1, 1);
>     > +                VLOG_WARN_RL(&rl, "Internal error: a tracked
>     updated LR "
>     > +                            "doesn't exist in lr_datapaths:
>     "UUID_FMT,
>     > +                            UUID_ARGS(&changed_lr->header_.uuid));
>     > +                goto fail;
>     > +            }
>     > +            hmapx_add(&nd->trk_data.trk_lrs_routes, od);
>     > +        }
>     >      }
>     > 
>     >      HMAPX_FOR_EACH (node, &ni->synced_lrs->deleted) {
>     > @@ -5554,6 +5610,9 @@ northd_handle_lr_changes(const struct
>     northd_input *ni,
>     >      if (!hmapx_is_empty(&nd->trk_data.trk_nat_lrs)) {
>     >          nd->trk_data.type |= NORTHD_TRACKED_LR_NATS;
>     >      }
>     > +    if (!hmapx_is_empty(&nd->trk_data.trk_lrs_routes)) {
>     > +        nd->trk_data.type |= NORTHD_TRACKED_LR_ROUTES;
>     > +    }
>     >      if (!hmapx_is_empty(&nd->trk_data.trk_routers.crupdated) ||
>     >          !hmapx_is_empty(&nd->trk_data.trk_routers.deleted)) {
>     >          nd->trk_data.type |= NORTHD_TRACKED_ROUTERS;
>     > @@ -12337,7 +12396,7 @@ parsed_route_add(const struct ovn_datapath
>     *od,
>     >      }
>     >  }
>     > 
>     > -static void
>     > +struct parsed_route *
>     >  parsed_routes_add_static(const struct ovn_datapath *od,
>     >                           const struct hmap *lr_ports,
>     >                           const struct
>     nbrec_logical_router_static_route *route,
>     > @@ -12358,8 +12417,9 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >                           UUID_FMT, route->nexthop,
>     >                           UUID_ARGS(&route->header_.uuid));
>     >              free(nexthop);
>     > -            return;
>     > +            return NULL;
>     >          }
>     > +
>     >          if ((IN6_IS_ADDR_V4MAPPED(nexthop) && plen != 32) ||
>     >              (!IN6_IS_ADDR_V4MAPPED(nexthop) && plen != 128)) {
>     >              static struct vlog_rate_limit rl =
>     VLOG_RATE_LIMIT_INIT(5, 1);
>     > @@ -12367,7 +12427,7 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >                           UUID_FMT, route->nexthop,
>     >                           UUID_ARGS(&route->header_.uuid));
>     >              free(nexthop);
>     > -            return;
>     > +            return NULL;
>     >          }
>     >      }
>     > 
>     > @@ -12379,7 +12439,7 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >                       UUID_FMT, route->ip_prefix,
>     >                       UUID_ARGS(&route->header_.uuid));
>     >          free(nexthop);
>     > -        return;
>     > +        return NULL;
>     >      }
>     > 
>     >      /* Verify that ip_prefix and nexthop are on the same network. */
>     > @@ -12391,7 +12451,7 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >                                     : IN6_IS_ADDR_V4MAPPED(&prefix),
>     >                                     &lrp_addr_s, &out_port)) {
>     >          free(nexthop);
>     > -        return;
>     > +        return NULL;
>     >      }
>     > 
>     >      const struct nbrec_bfd *nb_bt = route->bfd;
>     > @@ -12401,7 +12461,7 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >                                                    nb_bt->dst_ip);
>     >          if (!bfd_e) {
>     >              free(nexthop);
>     > -            return;
>     > +            return NULL;
>     >          }
>     > 
>     >          /* This static route is linked to an active bfd session. */
>     > @@ -12418,10 +12478,9 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >              bfd_set_status(bfd_sr, "down");
>     >          }
>     > 
>     > -
>     >          if (!strcmp(bfd_sr->status, "down")) {
>     > -            free(nexthop);
>     > -            return;
>     > +           free(nexthop);
>     > +           return NULL;
>     >          }
>     >      }
>     > 
>     > @@ -12465,12 +12524,17 @@ parsed_routes_add_static(const struct
>     ovn_datapath *od,
>     >      bool dynamic_routing_advertise = smap_get_bool(&route->options,
>     >                                                     "dynamic-
>     routing-advertise",
>     >                                                     true);
>     > -    parsed_route_add(od, nexthop, &prefix, plen,
>     is_discard_route, lrp_addr_s,
>     > -                     out_port, route_table_id, is_src_route,
>     > -                     ecmp_symmetric_reply, override_connected,
>     > -                     &ecmp_selection_fields, source,
>     dynamic_routing_advertise,
>     > -                     &route->header_, NULL, routes);
>     > +    struct parsed_route *pr = parsed_route_add(od, nexthop,
>     &prefix, plen,
>     > +                                               is_discard_route,
>     lrp_addr_s,
>     > +                                               out_port,
>     route_table_id,
>     > +                                               is_src_route,
>     > +                                               ecmp_symmetric_reply,
>     > +                                               override_connected,
>     > +                                             
>      &ecmp_selection_fields, source,
>     > +                                             
>      dynamic_routing_advertise,
>     > +                                               &route->header_,
>     NULL, routes);
>     >      sset_destroy(&ecmp_selection_fields);
>     > +    return pr;
>     >  }
>     > 
>     >  static void
>     > @@ -16374,13 +16438,14 @@ build_lr_gateway_redirect_flows_for_nats(
>     >   * In the common case where the Ethernet destination has been
>     resolved,
>     >   * this table outputs the packet (priority 0).  Otherwise, it
>     composes
>     >   * and sends an ARP/IPv6 NA request (priority 100). */
>     > -static void
>     > +void
>     >  build_arp_request_flows_for_lrouter(
>     > -        struct ovn_datapath *od, struct lflow_table *lflows,
>     > -        struct ds *match, struct ds *actions,
>     > +        const struct ovn_datapath *od, struct lflow_table *lflows,
>     >          const struct shash *meter_groups,
>     >          struct lflow_ref *lflow_ref)
>     >  {
>     > +    struct ds match =  DS_EMPTY_INITIALIZER;
>     > +    struct ds actions = DS_EMPTY_INITIALIZER;
>     >      ovs_assert(od->nbr);
>     >      for (int i = 0; i < od->nbr->n_static_routes; i++) {
>     >          const struct nbrec_logical_router_static_route *route;
>     > @@ -16394,8 +16459,8 @@ build_arp_request_flows_for_lrouter(
>     >              continue;
>     >          }
>     > 
>     > -        ds_clear(match);
>     > -        ds_put_format(match, "eth.dst == 00:00:00:00:00:00 && "
>     > +        ds_clear(&match);
>     > +        ds_put_format(&match, "eth.dst == 00:00:00:00:00:00 && "
>     >                        REGBIT_NEXTHOP_IS_IPV4" == 0 && "
>     >                        REG_NEXT_HOP_IPV6 " == %s",
>     >                        route->nexthop);
>     > @@ -16407,8 +16472,8 @@ build_arp_request_flows_for_lrouter(
>     >          char sn_addr_s[INET6_ADDRSTRLEN + 1];
>     >          ipv6_string_mapped(sn_addr_s, &sn_addr);
>     > 
>     > -        ds_clear(actions);
>     > -        ds_put_format(actions,
>     > +        ds_clear(&actions);
>     > +        ds_put_format(&actions,
>     >                        "nd_ns { "
>     >                        "eth.dst = "ETH_ADDR_FMT"; "
>     >                        "ip6.dst = %s; "
>     > @@ -16418,7 +16483,7 @@ build_arp_request_flows_for_lrouter(
>     >                        route->nexthop);
>     > 
>     >          ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
>     > -                      ds_cstr(match), ds_cstr(actions), lflow_ref,
>     > +                      ds_cstr(&match), ds_cstr(&actions), lflow_ref,
>     >                       
>     WITH_CTRL_METER(copp_meter_get(COPP_ND_NS_RESOLVE,
>     >                                                       od->nbr->copp,
>     >                                                       meter_groups)),
>     > @@ -16450,6 +16515,8 @@ build_arp_request_flows_for_lrouter(
>     >                                                             
>     meter_groups)));
>     >      ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1",
>     "next;",
>     >                    lflow_ref);
>     > +    ds_destroy(&match);
>     > +    ds_destroy(&actions);
>     >  }
>     > 
>     >  static void
>     > @@ -19578,8 +19645,7 @@
>     build_lswitch_and_lrouter_iterate_by_lr(struct ovn_datapath *od,
>     >      build_gateway_redirect_flows_for_lrouter(od, lsi->lflows,
>     &lsi->match,
>     >                                               &lsi->actions,
>     >                                               od->datapath_lflows);
>     > -    build_arp_request_flows_for_lrouter(od, lsi->lflows, &lsi->match,
>     > -                                        &lsi->actions,
>     > +    build_arp_request_flows_for_lrouter(od, lsi->lflows,
>     >                                          lsi->meter_groups,
>     >                                          od->datapath_lflows);
>     >      build_ecmp_stateful_egr_flows_for_lrouter(od, lsi->lflows,
>     > @@ -21076,6 +21142,9 @@ routes_init(struct routes_data *data)
>     >      hmap_init(&data->parsed_routes);
>     >      simap_init(&data->route_tables);
>     >      hmap_init(&data->bfd_active_connections);
>     > +    data->tracked = false;
>     > +    hmapx_init(&data->trk_data.trk_deleted_parsed_route);
>     > +    hmapx_init(&data->trk_data.trk_crupdated_parsed_route);
>     >  }
>     > 
>     >  void
>     > @@ -21206,6 +21275,17 @@ routes_destroy(struct routes_data *data)
>     > 
>     >      simap_destroy(&data->route_tables);
>     >      __bfd_destroy(&data->bfd_active_connections);
>     > +    data->tracked = false;
>     > +    hmapx_destroy(&data->trk_data.trk_crupdated_parsed_route);
>     > +    hmapx_destroy(&data->trk_data.trk_deleted_parsed_route);
>     > +}
>     > +
>     > +void
>     > +routes_clear_tracked(struct routes_data *data)
>     > +{
>     > +    data->tracked = false;
>     > +    hmapx_clear(&data->trk_data.trk_crupdated_parsed_route);
>     > +    hmapx_clear(&data->trk_data.trk_deleted_parsed_route);
>     >  }
>     > 
>     >  void
>     > diff --git a/northd/northd.h b/northd/northd.h
>     > index 726a416e4..bda218341 100644
>     > --- a/northd/northd.h
>     > +++ b/northd/northd.h
>     > @@ -110,6 +110,10 @@ ods_size(const struct ovn_datapaths *datapaths)
>     >  struct ovn_datapath *
>     >  ovn_datapath_find_by_key(struct hmap *datapaths, uint32_t dp_key);
>     > 
>     > +struct ovn_datapath *
>     > +ovn_datapath_find_by_static_route(struct hmapx *,
>     > +                                  const struct uuid *route_uuid);
>     > +
>     >  bool od_has_lb_vip(const struct ovn_datapath *od);
>     > 
>     >  /* List of routing and routing-related protocols which
>     > @@ -159,6 +163,7 @@ enum northd_tracked_data_type {
>     >      NORTHD_TRACKED_LS_ACLS  = (1 << 4),
>     >      NORTHD_TRACKED_SWITCHES = (1 << 5),
>     >      NORTHD_TRACKED_ROUTERS  = (1 << 6),
>     > +    NORTHD_TRACKED_LR_ROUTES  = (1 << 7),
>     >  };
>     > 
>     >  /* Track what's changed in the northd engine node.
>     > @@ -176,6 +181,10 @@ struct northd_tracked_data {
>     >       * hmapx node is 'struct ovn_datapath *'. */
>     >      struct hmapx trk_nat_lrs;
>     > 
>     > +    /* Tracked logical routers whose static routes have changed.
>     > +     * hmapx node is 'struct ovn_datapath *'. */
>     > +    struct hmapx trk_lrs_routes;
>     > +
>     >      /* Tracked logical switches whose load balancers have changed.
>     >       * hmapx node is 'struct ovn_datapath *'. */
>     >      struct hmapx ls_with_changed_lbs;
>     > @@ -216,10 +225,23 @@ struct route_policy {
>     >      uint32_t jump_chain_id;
>     >  };
>     > 
>     > +struct route_tracked_data {
>     > +    /* Contains references to group_ecmp_route_node. Each of the
>     referenced
>     > +     * datapaths contains at least one route. */
>     > +    struct hmapx trk_crupdated_parsed_route;
>     > +
>     > +    /* Contains references to group_ecmp_route_node. Each of the
>     referenced
>     > +     * datapath previously had some routes. The datapath now no
>     longer
>     > +     * contains any route.*/
>     > +    struct hmapx trk_deleted_parsed_route;
>     > +};
>     > +
>     >  struct routes_data {
>     >      struct hmap parsed_routes; /* Stores struct parsed_route. */
>     >      struct simap route_tables;
>     >      struct hmap bfd_active_connections;
>     > +    bool tracked;
>     > +    struct route_tracked_data trk_data;
>     >  };
>     > 
>     >  struct route_policies_data {
>     > @@ -886,6 +908,14 @@ struct parsed_route *parsed_route_add(
>     >      const struct ovn_port *tracked_port,
>     >      struct hmap *routes);
>     > 
>     > +struct  parsed_route * parsed_routes_add_static(
>     > +    const struct ovn_datapath *od,
>     > +    const struct hmap *lr_ports,
>     > +    const struct nbrec_logical_router_static_route *route,
>     > +    const struct hmap *bfd_connections,
>     > +    struct hmap *routes, struct simap *route_tables,
>     > +    struct hmap *bfd_active_connections);
>     > +
>     >  struct svc_monitors_map_data {
>     >      const struct hmap *local_svc_monitors_map;
>     >      const struct hmap *ic_learned_svc_monitors_map;
>     > @@ -930,7 +960,7 @@ void build_parsed_routes(const struct
>     ovn_datapath *, const struct hmap *,
>     >  uint32_t get_route_table_id(struct simap *, const char *);
>     >  void routes_init(struct routes_data *);
>     >  void routes_destroy(struct routes_data *);
>     > -
>     > +void routes_clear_tracked(struct routes_data *);
>     >  void bfd_init(struct bfd_data *);
>     >  void bfd_destroy(struct bfd_data *);
>     > 
>     > @@ -956,6 +986,10 @@ void build_route_data_flows_for_lrouter(
>     >      const struct ovn_datapath *od, struct lflow_table *lflows,
>     >      const struct group_ecmp_datapath *route_node,
>     >      const struct sset *bfd_ports);
>     > +void build_arp_request_flows_for_lrouter(
>     > +    const struct ovn_datapath *od, struct lflow_table *lflows,
>     > +    const struct shash *meter_groups,
>     > +    struct lflow_ref *lflow_ref);
>     > 
>     >  bool lflow_handle_northd_lr_changes(struct ovsdb_idl_txn *ovnsh_txn,
>     >                                       struct tracked_dps *,
>     > @@ -1042,6 +1076,11 @@ northd_has_lr_nats_in_tracked_data(struct
>     northd_tracked_data *trk_nd_changes)
>     >  {
>     >      return trk_nd_changes->type & NORTHD_TRACKED_LR_NATS;
>     >  }
>     > +static inline bool
>     > +northd_has_lr_route_in_tracked_data(struct northd_tracked_data
>     *trk_nd_changes)
>     > +{
>     > +    return trk_nd_changes->type & NORTHD_TRACKED_LR_ROUTES;
>     > +}
>     > 
>     >  static inline bool
>     >  northd_has_ls_lbs_in_tracked_data(struct northd_tracked_data
>     *trk_nd_changes)
>     > diff --git a/tests/ovn-inc-proc-graph-dump.at <http://ovn-inc-
>     proc-graph-dump.at> b/tests/ovn-inc-proc-graph-dump.at <http://ovn-
>     inc-proc-graph-dump.at>
>     > index 3750339d0..50fe0d5be 100644
>     > --- a/tests/ovn-inc-proc-graph-dump.at <http://ovn-inc-proc-graph-
>     dump.at>
>     > +++ b/tests/ovn-inc-proc-graph-dump.at <http://ovn-inc-proc-graph-
>     dump.at>
>     > @@ -151,9 +151,11 @@ digraph "Incremental-Processing-Engine" {
>     >       bfd [[style=filled, shape=box, fillcolor=white, label="bfd"]];
>     >       NB_bfd -> bfd [[label=""]];
>     >       SB_bfd -> bfd [[label=""]];
>     > +     NB_logical_router_static_route [[style=filled, shape=box,
>     fillcolor=white, label="NB_logical_router_static_route"]];
>     >       routes [[style=filled, shape=box, fillcolor=white,
>     label="routes"]];
>     >       bfd -> routes [[label=""]];
>     >       northd -> routes [[label="routes_northd_change_handler"]];
>     > +     NB_logical_router_static_route -> routes
>     [[label="routes_static_route_change_handler"]];
>     >       route_policies [[style=filled, shape=box, fillcolor=white,
>     label="route_policies"]];
>     >       bfd -> route_policies [[label=""]];
>     >       northd -> route_policies
>     [[label="route_policies_northd_change_handler"]];
>     > @@ -168,7 +170,7 @@ digraph "Incremental-Processing-Engine" {
>     >       SB_learned_route -> learned_route_sync
>     [[label="learned_route_sync_sb_learned_route_change_handler"]];
>     >       northd -> learned_route_sync
>     [[label="learned_route_sync_northd_change_handler"]];
>     >       group_ecmp_route [[style=filled, shape=box, fillcolor=white,
>     label="group_ecmp_route"]];
>     > -     routes -> group_ecmp_route [[label=""]];
>     > +     routes -> group_ecmp_route
>     [[label="group_ecmp_static_route_change_handler"]];
>     >       learned_route_sync -> group_ecmp_route
>     [[label="group_ecmp_route_learned_route_change_handler"]];
>     >       ls_stateful [[style=filled, shape=box, fillcolor=white,
>     label="ls_stateful"]];
>     >       northd -> ls_stateful [[label="ls_stateful_northd_handler"]];
>     > @@ -186,7 +188,7 @@ digraph "Incremental-Processing-Engine" {
>     >       SB_logical_dp_group -> lflow [[label=""]];
>     >       bfd_sync -> lflow [[label=""]];
>     >       route_policies -> lflow [[label=""]];
>     > -     routes -> lflow [[label=""]];
>     > +     routes -> lflow [[label="lflow_group_route_change_handler"]];
>     >       group_ecmp_route -> lflow
>     [[label="lflow_group_ecmp_route_change_handler"]];
>     >       global_config -> lflow [[label="node_global_config_handler"]];
>     >       sampling_app -> lflow [[label=""]];
>     > diff --git a/tests/ovn-northd.at <http://ovn-northd.at> b/tests/
>     ovn-northd.at <http://ovn-northd.at>
>     > index f87b14c9a..ed7574854 100644
>     > --- a/tests/ovn-northd.at <http://ovn-northd.at>
>     > +++ b/tests/ovn-northd.at <http://ovn-northd.at>
>     > @@ -4383,7 +4383,7 @@ check ovn-nbctl --bfd=$uuid lr-route-add r0
>     100.0.0.0/8 <http://100.0.0.0/8> 192.168.1.2
>     >  wait_column down bfd status logical_port=r0-sw1
>     >  AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.1.2 | grep -q
>     bfd], [0], [], [ignore])
>     > 
>     > -check_engine_stats northd recompute nocompute
>     > +check_engine_stats northd norecompute compute
>     >  check_engine_stats bfd recompute nocompute
>     >  check_engine_stats routes recompute nocompute
>     >  check_engine_stats lflow recompute nocompute
>     > @@ -4399,7 +4399,7 @@ check ovn-nbctl --bfd lr-route-add r0
>     240.0.0.0/8 <http://240.0.0.0/8> 192.168.5.2 r0-sw5
>     >  wait_column down bfd status logical_port=r0-sw5
>     >  AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.5.2 | grep -q
>     bfd], [0], [], [ignore])
>     > 
>     > -check_engine_stats northd recompute nocompute
>     > +check_engine_stats northd norecompute compute
>     >  check_engine_stats bfd recompute nocompute
>     >  check_engine_stats routes recompute nocompute
>     >  check_engine_stats lflow recompute nocompute
>     > @@ -4411,7 +4411,7 @@ check ovn-nbctl --bfd --policy=src-ip lr-
>     route-add r0 192.168.6.1/32 <http://192.168.6.1/32> 192.168.10.
>     >  wait_column down bfd status logical_port=r0-sw6
>     >  AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.6.1 | grep -q
>     bfd], [0], [], [ignore])
>     > 
>     > -check_engine_stats northd recompute nocompute
>     > +check_engine_stats northd norecompute compute
>     >  check_engine_stats bfd recompute nocompute
>     >  check_engine_stats route_policies recompute nocompute
>     >  check_engine_stats lflow recompute nocompute
>     > @@ -4446,10 +4446,10 @@ wait_column down bfd status
>     logical_port=r0-sw8
>     >  bfd_route_policy_uuid=$(fetch_column nb:bfd _uuid
>     logical_port=r0-sw8)
>     >  AT_CHECK([ovn-nbctl list logical_router_policy | grep -q
>     $bfd_route_policy_uuid])
>     > 
>     > -check_engine_stats northd recompute nocompute
>     > +check_engine_stats northd recompute incremental
>     >  check_engine_stats bfd recompute nocompute
>     > -check_engine_stats routes recompute nocompute
>     > -check_engine_stats lflow recompute nocompute
>     > +check_engine_stats routes recompute incremental
>     > +check_engine_stats lflow recompute incremental
>     >  check_engine_stats northd_output norecompute compute
>     >  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>     >  check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > @@ -16818,12 +16818,12 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
>     > 
>     >  check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     >  check ovn-nbctl --wait=sb lr-route-add lr0 192.168.0.0/24
>     <http://192.168.0.0/24> 10.0.0.10
>     > -check_engine_compute northd recompute
>     > -check_engine_compute routes recompute
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     >  check_engine_compute advertised_route_sync recompute
>     > -check_engine_compute learned_route_sync recompute
>     > -check_engine_compute group_ecmp_route recompute
>     > -check_engine_compute lflow recompute
>     > +check_engine_compute learned_route_sync incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     >  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>     > 
>     >  check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > @@ -20933,3 +20933,109 @@ check_column "$global_svc_mon_mac"
>     sb:Service_Monitor src_mac port=2
>     >  OVN_CLEANUP_NORTHD
>     >  AT_CLEANUP
>     >  ])
>     > +
>     > +OVN_FOR_EACH_NORTHD_NO_HV([
>     > +AT_SETUP([Static Route incremental processing])
>     > +ovn_start
>     > +
>     > +check ovn-nbctl lr-add r0
>     > +
>     > +check ovn-nbctl --wait=sb lrp-add r0 r0-lrp1 00:00:00:00:00:01
>     192.168.1.1/24 <http://192.168.1.1/24> fe80::1/64
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb lr-route-add r0 10.0.0.0/24
>     <http://10.0.0.0/24> 192.168.1.2
>     > +
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +
>     > +static_route_uuid=`ovn-nbctl --bare --columns _uuid find
>     Logical_Router_Static_Route nexthop=192.168.1.2`
>     > +AT_CHECK([test "$static_route_uuid" != ""])
>     > +
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.0.0/24 <http://10.0.0.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid nexthop=192.168.1.3
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.0.0/24 <http://10.0.0.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid ip_prefix=10.0.1.0/24 <http://10.0.1.0/24>
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid_old=$(fetch_column Logical_flow _uuid match='"reg7
>     == 0 && ip4.dst == 10.0.0.0/24 <http://10.0.0.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid_old" == ""])
>     > +
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check ovn-nbctl --wait=sb lrp-add r0 r0-lrp2 00:00:00:00:00:02
>     192.168.1.10/24 <http://192.168.1.10/24>
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid output_port=r0-lrp2
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid policy=src-ip
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.src == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid policy=dst-ip
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid selection_fields="ip_proto,ip_src,ip_dst"
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid options:ecmp_symmetric_reply=true
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl --wait=sb set logical_router_static_route
>     $static_route_uuid nexthop=\"fe80::2\"
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.dst == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" != ""])
>     > +sr_lflow_uuid_nexthop_ipv6=$(fetch_column Logical_flow _uuid
>     match='"eth.dst == 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 ==
>     fe80::2"')
>     > +AT_CHECK([test "$sr_lflow_uuid_nexthop_ipv6" != ""])
>     > +
>     > +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>     > +check ovn-nbctl remove logical_router r0 static_routes
>     $static_route_uuid
>     > +check_engine_compute northd incremental
>     > +check_engine_compute routes incremental
>     > +check_engine_compute group_ecmp_route incremental
>     > +check_engine_compute lflow incremental
>     > +sr_lflow_uuid=$(fetch_column Logical_flow _uuid match='"reg7 == 0
>     && ip4.src == 10.0.1.0/24 <http://10.0.1.0/24>"')
>     > +AT_CHECK([test "$sr_lflow_uuid" == ""])
>     > +
>     > +OVN_CLEANUP_NORTHD
>     > +AT_CLEANUP
>     > +])
>     > diff --git a/tests/system-ovn.at <http://system-ovn.at> b/tests/
>     system-ovn.at <http://system-ovn.at>
>     > index cfcc3f197..9ff463ce0 100644
>     > --- a/tests/system-ovn.at <http://system-ovn.at>
>     > +++ b/tests/system-ovn.at <http://system-ovn.at>
>     > @@ -7352,7 +7352,8 @@ wait_column "up" nb:bfd status
>     logical_port=rp-public
>     >  OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |
>     grep 'ip4.dst == 100.0.0.0/8 <http://100.0.0.0/8>' |grep -q
>     172.16.1.50])
>     > 
>     >  # un-associate the bfd connection and the static route
>     > -check ovn-nbctl clear logical_router_static_route $route_uuid bfd
>     > +check ovn-nbctl --wait=sb clear logical_router_static_route
>     $route_uuid bfd
>     > +cat northd/ovn-northd.log
>     >  wait_column "admin_down" nb:bfd status logical_port=rp-public
>     >  OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -
>     qi state=Down])
>     > 
>     > @@ -7416,7 +7417,7 @@ wait_column "up" nb:bfd status
>     logical_port=rp-public
>     >  OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 |grep lr_in_ip_routing |
>     grep 'ip4.dst == 100.0.0.0/8 <http://100.0.0.0/8>' |grep -q
>     172.16.1.50])
>     >  check_row_count Advertised_Route 1 ip_prefix=100.0.0.0/8
>     <http://100.0.0.0/8>
>     > 
>     > -check ovn-nbctl clear logical_router_static_route $route_uuid bfd
>     > +check ovn-nbctl --wait=sb clear logical_router_static_route
>     $route_uuid bfd
>     >  wait_column "admin_down" nb:bfd status logical_port=rp-public
>     >  OVS_WAIT_UNTIL([ip netns exec server bfdd-control status | grep -
>     qi state=Down])
>     >  check ovn-nbctl destroy bfd $uuid
> 
> 
> 
> /‘Esta mensagem é direcionada apenas para os endereços constantes no
> cabeçalho inicial. Se você não está listado nos endereços constantes no
> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa
> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas
> estão imediatamente anuladas e proibidas’./
> 
> / //‘Apesar do Magazine Luiza tomar todas as precauções razoáveis para
> assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não
> poderá aceitar a responsabilidade por quaisquer perdas ou danos causados
> por esse e-mail ou por seus anexos’./
> 

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

Reply via email to