On Thu, Feb 20, 2025 at 02:46:28PM +0100, Dumitru Ceara wrote:
> On 2/18/25 3:02 PM, Felix Huettner via dev wrote:
> > Add support for I+P handling of en-learned-route-sync for the
> > sb_learned_routes input.
> > 
> > Signed-off-by: Felix Huettner <[email protected]>
> > ---
> 
> Hi Felix,
> 
> Overall the patch looks good to me.  I do have some small comments below.

Hi Dumitru,

thanks a lot for the review.

> 
> > v1-v2: Fix test error
> > 
> >  northd/en-learned-route-sync.c | 123 ++++++++++++++++++++++++++++++---
> >  northd/en-learned-route-sync.h |  25 +++++++
> >  northd/inc-proc-northd.c       |   6 +-
> >  northd/northd.c                |   5 +-
> >  northd/northd.h                |  31 +++++----
> >  tests/ovn-northd.at            |  16 ++---
> >  6 files changed, 170 insertions(+), 36 deletions(-)
> > 
> > diff --git a/northd/en-learned-route-sync.c b/northd/en-learned-route-sync.c
> > index 4e87b3265..312141208 100644
> > --- a/northd/en-learned-route-sync.c
> > +++ b/northd/en-learned-route-sync.c
> > @@ -60,6 +60,19 @@ learned_route_sync_northd_change_handler(struct 
> > engine_node *node,
> >      return true;
> >  }
> >  
> > +static void
> > +routes_sync_clear_tracked(struct learned_route_sync_data *data)
> > +{
> > +    hmapx_clear(&data->trk_data.trk_created_parsed_route);
> > +    struct hmapx_node *hmapx_node;
> > +    HMAPX_FOR_EACH_SAFE (hmapx_node,
> > +                         &data->trk_data.trk_deleted_parsed_route) {
> > +        parsed_route_free(hmapx_node->data);
> > +        hmapx_delete(&data->trk_data.trk_deleted_parsed_route, hmapx_node);
> > +    }
> > +    data->trk_data.type = LEARNED_ROUTES_TRACKED_NONE;
> > +}
> > +
> >  static void
> >  routes_sync_clear(struct learned_route_sync_data *data)
> >  {
> > @@ -67,12 +80,16 @@ routes_sync_clear(struct learned_route_sync_data *data)
> >      HMAP_FOR_EACH_POP (r, key_node, &data->parsed_routes) {
> >          parsed_route_free(r);
> >      }
> > +    routes_sync_clear_tracked(data);
> >  }
> >  
> >  static void
> >  routes_sync_init(struct learned_route_sync_data *data)
> >  {
> >      hmap_init(&data->parsed_routes);
> > +    hmapx_init(&data->trk_data.trk_created_parsed_route);
> > +    hmapx_init(&data->trk_data.trk_deleted_parsed_route);
> > +    data->trk_data.type = LEARNED_ROUTES_TRACKED_NONE;
> >  }
> >  
> >  static void
> > @@ -80,6 +97,8 @@ routes_sync_destroy(struct learned_route_sync_data *data)
> >  {
> >      routes_sync_clear(data);
> >      hmap_destroy(&data->parsed_routes);
> > +    hmapx_destroy(&data->trk_data.trk_created_parsed_route);
> > +    hmapx_destroy(&data->trk_data.trk_deleted_parsed_route);
> >  }
> >  
> >  void *
> > @@ -97,6 +116,12 @@ en_learned_route_sync_cleanup(void *data)
> >      routes_sync_destroy(data);
> >  }
> >  
> > +void
> > +en_learned_route_sync_clear_tracked_data(void *data)
> > +{
> > +    routes_sync_clear_tracked(data);
> > +}
> > +
> >  void
> >  en_learned_route_sync_run(struct engine_node *node, void *data)
> >  {
> > @@ -122,7 +147,7 @@ en_learned_route_sync_run(struct engine_node *node, 
> > void *data)
> >  }
> >  
> >  
> > -static void
> > +static struct parsed_route *
> >  parse_route_from_sbrec_route(struct hmap *parsed_routes_out,
> >                               const struct hmap *lr_ports,
> >                               const struct hmap *lr_datapaths,
> > @@ -132,7 +157,7 @@ parse_route_from_sbrec_route(struct hmap 
> > *parsed_routes_out,
> >          NULL, lr_datapaths, route->datapath);
> >  
> >      if (!od || ovn_datapath_is_stale(od)) {
> > -        return;
> > +        return NULL;
> >      }
> >  
> >      /* Verify that the next hop is an IP address with an all-ones mask. */
> > @@ -144,7 +169,7 @@ parse_route_from_sbrec_route(struct hmap 
> > *parsed_routes_out,
> >                       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)) {
> > @@ -153,7 +178,7 @@ parse_route_from_sbrec_route(struct hmap 
> > *parsed_routes_out,
> >                       UUID_FMT, route->nexthop,
> >                       UUID_ARGS(&route->header_.uuid));
> >          free(nexthop);
> > -        return;
> > +        return NULL;
> >      }
> >  
> >      /* Parse ip_prefix */
> > @@ -164,7 +189,7 @@ parse_route_from_sbrec_route(struct hmap 
> > *parsed_routes_out,
> >                       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. */
> > @@ -175,14 +200,18 @@ parse_route_from_sbrec_route(struct hmap 
> > *parsed_routes_out,
> >                              IN6_IS_ADDR_V4MAPPED(&prefix),
> >                              false,
> >                              &out_port, &lrp_addr_s)) {
> > +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> > +        VLOG_WARN_RL(&rl, "could not find output port %s for learned route 
> > "
> > +                     UUID_FMT, route->logical_port->logical_port,
> > +                     UUID_ARGS(&route->header_.uuid));
> >          free(nexthop);
> > -        return;
> > +        return NULL;
> >      }
> >  
> > -    parsed_route_add(od, nexthop, &prefix, plen, false, lrp_addr_s,
> > -                     out_port, 0, false, false, NULL,
> > -                     ROUTE_SOURCE_LEARNED, &route->header_, NULL,
> > -                     parsed_routes_out);
> > +    return parsed_route_add(od, nexthop, &prefix, plen, false, lrp_addr_s,
> > +                            out_port, 0, false, false, NULL,
> > +                            ROUTE_SOURCE_LEARNED, &route->header_, NULL,
> > +                            parsed_routes_out);
> >  }
> >  
> >  static void
> > @@ -212,3 +241,77 @@ routes_table_sync(
> >                      parsed_route_hash(route));
> >      }
> >  }
> > +
> > +static struct parsed_route *
> > +find_learned_route(const struct sbrec_learned_route *learned_route,
> > +                   const struct ovn_datapaths *lr_datapaths,
> > +                   const struct hmap *routes)
> > +{
> > +    const struct ovn_datapath *od = ovn_datapath_from_sbrec(
> > +        NULL, &lr_datapaths->datapaths, learned_route->datapath);
> > +    if (!od) {
> > +        return NULL;
> > +    }
> > +    size_t hash = uuid_hash(&od->key);
> 
> 
> Let's not use parsed_route implementation internals.  Let's expose a
> parsed_route_lookup_by_source(source, source_hint) or similar instead.
> 
> Then we can just use that one directly in the change handler instead of
> re-implementing  the logic in find_learned_route() here.

Sounds good.

> 
> > +    struct parsed_route *route;
> > +    HMAP_FOR_EACH_WITH_HASH (route, key_node, hash, routes) {
> > +        if (route->source == ROUTE_SOURCE_LEARNED &&
> > +                uuid_equals(&route->source_hint->uuid,
> > +                            &learned_route->header_.uuid)) {
> > +            return route;
> > +        }
> > +    }
> > +    return NULL;
> > +}
> > +
> > +bool
> > +learned_route_sync_learned_route_change_handler(struct engine_node *node,
> > +                                                void *data_ OVS_UNUSED)
> > +{
> > +    struct learned_route_sync_data *data = data_;
> > +
> > +    const struct sbrec_learned_route_table *sbrec_learned_route_table =
> > +        EN_OVSDB_GET(engine_get_input("SB_learned_route", node));
> > +    struct northd_data *northd_data = engine_get_input_data("northd", 
> > node);
> > +
> > +    const struct sbrec_learned_route *changed_route;
> > +    SBREC_LEARNED_ROUTE_TABLE_FOR_EACH_TRACKED (changed_route,
> > +                                                sbrec_learned_route_table) 
> > {
> > +        if (sbrec_learned_route_is_new(changed_route)) {
> > +            struct parsed_route *route = parse_route_from_sbrec_route(
> > +                &data->parsed_routes, &northd_data->lr_ports,
> > +                &northd_data->lr_datapaths.datapaths, changed_route);
> > +            if (route) {
> > +                hmapx_add(&data->trk_data.trk_created_parsed_route, route);
> > +                data->trk_data.type |= LEARNED_ROUTES_TRACKED_LEARNED;
> > +                continue;
> > +            }
> > +        }
> > +
> > +        if (sbrec_learned_route_is_deleted(changed_route)) {
> > +            struct parsed_route *route = find_learned_route(
> > +                changed_route, &northd_data->lr_datapaths,
> > +                &data->parsed_routes);
> > +            if (!route) {
> > +                goto fail;
> > +            }
> > +            hmap_remove(&data->parsed_routes, &route->key_node);
> > +            hmapx_add(&data->trk_data.trk_deleted_parsed_route, route);
> > +            data->trk_data.type |= LEARNED_ROUTES_TRACKED_LEARNED;
> > +            continue;
> > +        }
> > +
> > +        /* The learned routes should never be updated, so we just fail the
> > +         * handler here if that happens. */
> > +        goto fail;
> > +    }
> > +
> > +    if ((data->trk_data.type & LEARNED_ROUTES_TRACKED_LEARNED) != 0) {
> > +        engine_set_node_state(node, EN_UPDATED);
> > +    }
> > +
> > +    return true;
> 
> Nit: I'd add a newline here.
> 
> > +fail:
> > +    routes_sync_clear_tracked(data);
> > +    return false;
> > +}
> > diff --git a/northd/en-learned-route-sync.h b/northd/en-learned-route-sync.h
> > index 1a5d6ff23..34baadaa1 100644
> > --- a/northd/en-learned-route-sync.h
> > +++ b/northd/en-learned-route-sync.h
> > @@ -18,15 +18,40 @@
> >  
> >  #include "lib/inc-proc-eng.h"
> >  #include "openvswitch/hmap.h"
> > +#include "hmapx.h"
> > +
> > +enum learned_routes_tracked_data_type {
> > +    LEARNED_ROUTES_TRACKED_NONE,
> > +    LEARNED_ROUTES_TRACKED_LEARNED  = (1 << 0),
> > +};
> 
> I'm confused, will we ever need more than NONE / LEARNED?  If not can we
> change this too bool?

I'm also confused what my orgiginal plan with this was. I'll change it :)

> 
> > +
> > +/* Track what's changed in the learned routes engine node.
> > + * For now only tracks changed learned routes. */
> > +struct learned_routes_tracked_data {
> > +    /* Indicates the type of data tracked.  One or all of 
> > ROUTES_TRACKED_*. */
> 
> 
> Nit: LEARNED_ROUTES_TRACKED_*?
> 
> > +    enum learned_routes_tracked_data_type type;
> > +
> > +    /* Tracked created routes based on sb_learned_routes.
> > +     * hmapx node is 'struct parsed_route *'. */
> > +    struct hmapx trk_created_parsed_route;
> > +
> > +    /* Tracked deleted routes based on sb_learned_routes.
> > +     * hmapx node is 'struct parsed_route *'. */
> > +    struct hmapx trk_deleted_parsed_route;
> > +};
> >  
> >  struct learned_route_sync_data {
> >      struct hmap parsed_routes;
> > +    struct learned_routes_tracked_data trk_data;
> >  };
> >  
> >  bool learned_route_sync_northd_change_handler(struct engine_node *,
> >                                                void *data);
> > +bool learned_route_sync_learned_route_change_handler(struct engine_node *,
> > +                                                     void *data);
> >  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);
> >  
> >  #endif /* EN_LEARNED_ROUTE_SYNC_H */
> > diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
> > index 3fa99f637..bf0fbc62b 100644
> > --- a/northd/inc-proc-northd.c
> > +++ b/northd/inc-proc-northd.c
> > @@ -174,7 +174,8 @@ static ENGINE_NODE(ecmp_nexthop, "ecmp_nexthop");
> >  static ENGINE_NODE(multicast_igmp, "multicast_igmp");
> >  static ENGINE_NODE(acl_id, "acl_id");
> >  static ENGINE_NODE(advertised_route_sync, "advertised_route_sync");
> > -static ENGINE_NODE(learned_route_sync, "learned_route_sync");
> > +static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(learned_route_sync,
> > +                                         "learned_route_sync");
> >  static ENGINE_NODE(dynamic_routes, "dynamic_routes");
> >  
> >  void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> > @@ -307,7 +308,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
> >                       advertised_route_sync_northd_change_handler);
> >  
> >      engine_add_input(&en_learned_route_sync, &en_routes, NULL);
> > -    engine_add_input(&en_learned_route_sync, &en_sb_learned_route, NULL);
> > +    engine_add_input(&en_learned_route_sync, &en_sb_learned_route,
> > +                     learned_route_sync_learned_route_change_handler);
> 
> Nit: to be inline with the rest of the handlers this should be:
> 
> learned_route_sync_sb_learned_route_change_handler
> 
> that is:
> 
> <target_i_p_node>_<input_i_p_node>_change_handler

ok

> 
> >      engine_add_input(&en_learned_route_sync, &en_northd,
> >                       learned_route_sync_northd_change_handler);
> >  
> > diff --git a/northd/northd.c b/northd/northd.c
> > index f1f1ede43..52bb67c0e 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -11079,7 +11079,7 @@ parsed_route_free(struct parsed_route *pr) {
> >   * in there.
> >   * Takes ownership of the provided nexthop. All other parameters are 
> > cloned.
> >   * Elements of the routes hmap need to be freed using parsed_route_free. */
> > -void
> > +struct parsed_route *
> >  parsed_route_add(const struct ovn_datapath *od,
> >                   struct in6_addr *nexthop,
> >                   const struct in6_addr *prefix,
> > @@ -11108,9 +11108,11 @@ parsed_route_add(const struct ovn_datapath *od,
> >      struct parsed_route *pr = parsed_route_lookup(routes, hash, new_pr);
> >      if (!pr) {
> >          hmap_insert(routes, &new_pr->key_node, hash);
> > +        return new_pr;
> >      } else {
> >          pr->stale = false;
> >          parsed_route_free(new_pr);
> > +        return pr;
> >      }
> >  }
> >  
> > @@ -19116,6 +19118,7 @@ routes_destroy(struct routes_data *data)
> >  
> >      simap_destroy(&data->route_tables);
> >      __bfd_destroy(&data->bfd_active_connections);
> > +
> 
> Nit: unrelated change.
> 
> >  }
> >  
> >  void
> > diff --git a/northd/northd.h b/northd/northd.h
> > index 1fbc93c8e..9402e4a4b 100644
> > --- a/northd/northd.h
> > +++ b/northd/northd.h
> > @@ -783,21 +783,22 @@ struct parsed_route *parsed_route_clone(const struct 
> > parsed_route *);
> >  size_t parsed_route_hash(const struct parsed_route *);
> >  void parsed_route_free(struct parsed_route *);
> >  
> > -void parsed_route_add(const struct ovn_datapath *od,
> > -                      struct in6_addr *nexthop,
> > -                      const struct in6_addr *prefix,
> > -                      unsigned int plen,
> > -                      bool is_discard_route,
> > -                      const char *lrp_addr_s,
> > -                      const struct ovn_port *out_port,
> > -                      uint32_t route_table_id,
> > -                      bool is_src_route,
> > -                      bool ecmp_symmetric_reply,
> > -                      const struct sset *ecmp_selection_fields,
> > -                      enum route_source source,
> > -                      const struct ovsdb_idl_row *source_hint,
> > -                      const struct ovn_port *tracked_port,
> > -                      struct hmap *routes);
> > +struct parsed_route * parsed_route_add(
> 
> 
> Nit: should be:
> 
> struct parsed_route *parsed_route_add(
> 
> > +    const struct ovn_datapath *od,
> > +    struct in6_addr *nexthop,
> > +    const struct in6_addr *prefix,
> > +    unsigned int plen,
> > +    bool is_discard_route,
> > +    const char *lrp_addr_s,
> > +    const struct ovn_port *out_port,
> > +    uint32_t route_table_id,
> > +    bool is_src_route,
> > +    bool ecmp_symmetric_reply,
> > +    const struct sset *ecmp_selection_fields,
> > +    enum route_source source,
> > +    const struct ovsdb_idl_row *source_hint,
> > +    const struct ovn_port *tracked_port,
> > +    struct hmap *routes);
> >  
> >  bool
> >  find_route_outport(const struct hmap *lr_ports, const char *output_port,
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index 6a58ccc27..bb77f2abc 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -15324,8 +15324,8 @@ ovn-sbctl dump-flows lr0 > lr0flows
> >  AT_CHECK([grep -w "lr_in_ip_routing" lr0flows | ovn_strip_lflows], [0], 
> > [dnl
> >    table=??(lr_in_ip_routing   ), priority=0    , match=(1), action=(drop;)
> >    table=??(lr_in_ip_routing   ), priority=10550, match=(nd_rs || nd_ra), 
> > action=(drop;)
> > -  table=??(lr_in_ip_routing   ), priority=194  , match=(reg7 == 0 && 
> > ip4.dst == 192.168.1.0/24), action=(ip.ttl--; flags.loopback = 1; 
> > reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);)
> > -  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && 
> > ip4.dst == 192.168.0.0/24), action=(ip.ttl--; flags.loopback = 1; 
> > reg8[[0..15]] = 2; reg8[[16..31]] = select(1, 2);)
> > +  table=??(lr_in_ip_routing   ), priority=194  , match=(reg7 == 0 && 
> > ip4.dst == 192.168.1.0/24), action=(ip.ttl--; flags.loopback = 1; 
> > reg8[[0..15]] = 2; reg8[[16..31]] = select(1, 2);)
> > +  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && 
> > ip4.dst == 192.168.0.0/24), action=(ip.ttl--; flags.loopback = 1; 
> > reg8[[0..15]] = 1; reg8[[16..31]] = select(1, 2);)
> >    table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
> > 10.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
> > 10.0.0.1; eth.src = 00:00:00:00:ff:01; outport = "lr0-sw0"; flags.loopback 
> > = 1; reg9[[9]] = 1; next;)
> >    table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
> > 10.0.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
> > 10.0.1.1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback 
> > = 1; reg9[[9]] = 1; next;)
> >    table=??(lr_in_ip_routing   ), priority=518  , match=(inport == 
> > "lr0-sw0" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; 
> > xxreg0 = ip6.dst; xxreg1 = fe80::200:ff:fe00:ff01; eth.src = 
> > 00:00:00:00:ff:01; outport = "lr0-sw0"; flags.loopback = 1; reg9[[9]] = 0; 
> > next;)
> > @@ -15333,10 +15333,10 @@ AT_CHECK([grep -w "lr_in_ip_routing" lr0flows | 
> > ovn_strip_lflows], [0], [dnl
> >  ])
> >  AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed -e 
> > 's/10\.0\..\./10.0.??./g' -e 's/lr0-sw./lr0-sw??/' -e 
> > 's/00:ff:0./00:ff:0?/' | ovn_strip_lflows], [0], [dnl
> >    table=??(lr_in_ip_routing_ecmp), priority=0    , match=(1), 
> > action=(drop;)
> > -  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 1 && reg8[[16..31]] == 1), action=(reg0 = 10.0.??.20; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > -  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 1 && reg8[[16..31]] == 2), action=(reg0 = 10.0.??.20; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > -  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 2 && reg8[[16..31]] == 1), action=(reg0 = 10.0.??.10; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > -  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 2 && reg8[[16..31]] == 2), action=(reg0 = 10.0.??.10; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > +  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 1 && reg8[[16..31]] == 1), action=(reg0 = 10.0.??.10; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > +  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 1 && reg8[[16..31]] == 2), action=(reg0 = 10.0.??.10; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > +  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 2 && reg8[[16..31]] == 1), action=(reg0 = 10.0.??.20; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> > +  table=??(lr_in_ip_routing_ecmp), priority=100  , match=(reg8[[0..15]] == 
> > 2 && reg8[[16..31]] == 2), action=(reg0 = 10.0.??.20; reg5 = 10.0.??.1; 
> > eth.src = 00:00:00:00:ff:0?; outport = "lr0-sw??"; reg9[[9]] = 1; next;)
> >    table=??(lr_in_ip_routing_ecmp), priority=150  , match=(reg8[[0..15]] == 
> > 0), action=(next;)
> >  ])
> >  
> > @@ -15630,7 +15630,7 @@ check ovn-nbctl --wait=sb sync
> >  check_engine_compute northd unchanged
> >  check_engine_compute routes unchanged
> >  check_engine_compute advertised_route_sync unchanged
> > -check_engine_compute learned_route_sync recompute
> > +check_engine_compute learned_route_sync incremental
> >  check_engine_compute lflow recompute
> >  CHECK_NO_CHANGE_AFTER_RECOMPUTE
> >  
> > @@ -15640,7 +15640,7 @@ check ovn-nbctl --wait=sb sync
> >  check_engine_compute northd unchanged
> >  check_engine_compute routes unchanged
> >  check_engine_compute advertised_route_sync unchanged
> > -check_engine_compute learned_route_sync recompute
> > +check_engine_compute learned_route_sync incremental
> >  check_engine_compute lflow recompute
> >  CHECK_NO_CHANGE_AFTER_RECOMPUTE
> >  

Nits will be also addressed in the next version.

Thanks a lot,
Felix

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

Reply via email to