Hi Lorenzo

Thanks for the review.
I'll adjust the patch with your suggestions.

Regards,
Lucas

Em ter., 3 de fev. de 2026 às 08:31, Lorenzo Bianconi <
[email protected]> escreveu:

> > Consider the scenario with multiple points of dynamic routing and
> > interconnection between different AZs, dynamic routes could be exchanged
> > inside ovn interconnection. This options enables that scenario.
> > Also, if scenario is multihomed and user doesn't want to re-route the
> same ip prefix
> > between the point of distribution, it could be disable this option.
> >
> > scenario 1 (hub-spoke enable):
> > Dynamic Routing 1 (adv 10.10.10.0/24, learn 11.11.11.0/24) -> | TS | <-
> (adv 11.11.11.0/24, learn 10.10.10.0/24) Dynamic Routing 2
> >
> > scenario 2 (hub-spoke disable), same ip prefix is advertised for
> redundancy, but it is not exchanged between them:
> >                                           ________
> > Dynamic Routing 1 (adv 10.10.10.0/24) -> | TS     |
> > Dynamic Routing 2 (adv 10.10.10.0/24) -> |________|  <- logical_router
> (learn both paths by ovn-ic)
> >
> > Signed-off-by: Lucas Vargas Dias <[email protected]>
>
> Hi Lucas,
>
> I guess you need to add an entry in NEWS for this new feature.
>
> > ---
> >  ic/ovn-ic.c                       | 28 ++++++---
> >  northd/en-advertised-route-sync.c |  3 +
> >  northd/northd.c                   | 13 ++++-
> >  northd/northd.h                   |  5 +-
> >  northd/ovn-northd.c               |  1 -
> >  ovn-nb.xml                        | 12 ++++
> >  tests/ovn-ic.at                   | 97 +++++++++++++++++++++++++++++++
> >  7 files changed, 149 insertions(+), 10 deletions(-)
> >
> > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> > index fd5ecefb3..e9fff2d4d 100644
> > --- a/ic/ovn-ic.c
> > +++ b/ic/ovn-ic.c
> > @@ -1283,6 +1283,7 @@ struct ic_route_info {
> >      struct in6_addr prefix;
> >      unsigned int plen;
> >      struct in6_addr nexthop;
> > +    bool is_src_dynamic;
> >      const char *origin;
> >      const char *route_table;
> >      const char *route_tag;
> > @@ -1554,7 +1555,7 @@ add_to_routes_ad(struct hmap *routes_ad, const
> struct in6_addr prefix,
> >                   const struct nbrec_logical_router_static_route
> *nb_route,
> >                   const struct nbrec_logical_router *nb_lr,
> >                   const struct nbrec_load_balancer *nb_lb,
> > -                 const char *route_tag)
> > +                 const char *route_tag, bool is_src_dynamic)
> >  {
> >      ovs_assert(nb_route || nb_lrp || nb_lb || nb_lr);
> >
> > @@ -1573,6 +1574,7 @@ add_to_routes_ad(struct hmap *routes_ad, const
> struct in6_addr prefix,
> >          ic_route->nb_route = nb_route;
> >          ic_route->origin = origin;
> >          ic_route->route_table = route_table;
> > +        ic_route->is_src_dynamic = is_src_dynamic;
> >          ic_route->nb_lrp = nb_lrp;
> >          ic_route->nb_lr = nb_lr;
> >          ic_route->nb_lb = nb_lb;
> > @@ -1649,7 +1651,7 @@ add_static_to_routes_ad(
> >
> >      add_to_routes_ad(routes_ad, prefix, plen, nexthop,
> ROUTE_ORIGIN_STATIC,
> >                       nb_route->route_table, NULL, nb_route, nb_lr,
> > -                     NULL, route_tag);
> > +                     NULL, route_tag, false);
> >  }
> >
> >  static void
> > @@ -1659,7 +1661,8 @@ add_network_to_routes_ad(struct hmap *routes_ad,
> const char *network,
> >                           const struct smap *nb_options,
> >                           const struct nbrec_logical_router *nb_lr,
> >                           const char *route_tag,
> > -                         const struct nbrec_logical_router_port *ts_lrp)
> > +                         const struct nbrec_logical_router_port *ts_lrp,
> > +                         bool is_src_dynamic)
> >  {
> >      struct in6_addr prefix, nexthop;
> >      unsigned int plen;
> > @@ -1711,7 +1714,8 @@ add_network_to_routes_ad(struct hmap *routes_ad,
> const char *network,
> >
> >      /* directly-connected routes go to <main> route table */
> >      add_to_routes_ad(routes_ad, prefix, plen, nexthop,
> ROUTE_ORIGIN_CONNECTED,
> > -                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag);
> > +                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag,
> > +                     is_src_dynamic);
> >  }
> >
> >  static void
> > @@ -1769,7 +1773,7 @@ add_lb_vip_to_routes_ad(struct hmap *routes_ad,
> const char *vip_key,
> >
> >      /* Lb vip routes go to <main> route table */
> >      add_to_routes_ad(routes_ad, vip_ip, plen, nexthop, ROUTE_ORIGIN_LB,
> > -                     NULL, NULL, NULL, nb_lr, nb_lb, route_tag);
> > +                     NULL, NULL, NULL, nb_lr, nb_lb, route_tag, false);
> >  out:
> >      free(vip_str);
> >  }
> > @@ -2187,6 +2191,12 @@ sync_learned_routes(struct ic_context *ctx,
> >                  nbrec_logical_router_static_route_update_options_setkey(
> >                      nb_route, "origin", isb_route->origin);
> >                  free(uuid_s);
> > +                bool is_src_dynamic =
> smap_get_bool(&isb_route->external_ids,
> > +                    "ic-source-dynamic", false);
>
> please document "ic-source-dynamic" as other ic parameters
>
> > +                char *ic_source_dynamic_str = is_src_dynamic ?
> > +                    "true" : "false";
> > +
> nbrec_logical_router_static_route_update_external_ids_setkey(
> > +                    nb_route, "ic-source-dynamic",
> ic_source_dynamic_str);
> >
> nbrec_logical_router_update_static_routes_addvalue(ic_lr->lr,
> >                      nb_route);
> >              }
> > @@ -2243,6 +2253,10 @@ ad_route_sync_external_ids(const struct
> ic_route_info *route_adv,
> >                                                       "ic-route-tag");
> >          }
> >      }
> > +
> > +    char *ic_src_dynamic_str = route_adv->is_src_dynamic ? "true" :
> "false";
> > +    icsbrec_route_update_external_ids_setkey(isb_route,
> "ic-source-dynamic",
> > +                                             ic_src_dynamic_str);
> >  }
> >
> >  /* Sync routes from routes_ad to IC-SB. */
> > @@ -2372,7 +2386,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,
> >                  add_network_to_routes_ad(routes_ad, lrp->networks[j],
> lrp,
> >                                           ts_port_addrs,
> >                                           &nb_global->options,
> > -                                         lr, route_tag, ts_lrp);
> > +                                         lr, route_tag, ts_lrp, false);
> >              }
> >          } else {
> >              /* The router port of the TS port is ignored. */
> > @@ -2427,7 +2441,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,
> >          add_network_to_routes_ad(routes_ad, sb_route->ip_prefix, NULL,
> >                                   ts_port_addrs,
> >                                   &nb_global->options,
> > -                                 lr, route_tag, ts_lrp);
> > +                                 lr, route_tag, ts_lrp, true);
> >      }
> >      sbrec_learned_route_index_destroy_row(filter);
> >  }
> > diff --git a/northd/en-advertised-route-sync.c
> b/northd/en-advertised-route-sync.c
> > index be771391d..be046769f 100644
> > --- a/northd/en-advertised-route-sync.c
> > +++ b/northd/en-advertised-route-sync.c
> > @@ -675,6 +675,8 @@ should_advertise_route(const struct uuidset
> *host_route_lrps,
> >          return drr_mode_NAT_is_set(drr);
> >      case ROUTE_SOURCE_LB:
> >          return drr_mode_LB_is_set(drr);
> > +    case ROUTE_SOURCE_IC_DYNAMIC:
> > +        return drr_mode_IC_DYNAMIC_is_set(drr);
> >      case ROUTE_SOURCE_LEARNED:
> >          OVS_NOT_REACHED();
> >      default:
> > @@ -745,6 +747,7 @@ advertise_route_track_od(struct
> advertised_route_sync_data *data,
> >                             &tracked_op->od->nbr->header_.uuid);
> >          }
> >          break;
> > +    case ROUTE_SOURCE_IC_DYNAMIC:
> >      case ROUTE_SOURCE_CONNECTED:
> >      case ROUTE_SOURCE_STATIC:
> >          break;
> > diff --git a/northd/northd.c b/northd/northd.c
> > index adaa94e85..3cbc41386 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -868,6 +868,10 @@ parse_dynamic_routing_redistribute(
> >              out |= DRRM_LB;
> >              continue;
> >          }
> > +        if (!strcmp(token, "hub-spoke")) {
> > +            out |= DRRM_IC_DYNAMIC;
> > +            continue;
> > +        }
> >          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> >          VLOG_WARN_RL(&rl,
> >                       "unknown dynamic-routing-redistribute option '%s'
> on %s",
> > @@ -11894,7 +11898,13 @@ parsed_routes_add_static(const struct
> ovn_datapath *od,
> >      enum route_source source;
> >      if (!strcmp(smap_get_def(&route->options, "origin", ""),
> >                  ROUTE_ORIGIN_CONNECTED)) {
> > -        source = ROUTE_SOURCE_CONNECTED;
> > +        bool ic_src_dynamic = smap_get_bool(&route->external_ids,
> > +                                            "ic-source-dynamic", false);
> > +        if (ic_src_dynamic) {
> > +           source = ROUTE_SOURCE_IC_DYNAMIC;
> > +        } else {
> > +            source = ROUTE_SOURCE_CONNECTED;
>
> please fix indentation here
>
> > +        }
> >      } else {
> >          source = ROUTE_SOURCE_STATIC;
> >      }
> > @@ -11989,6 +11999,7 @@ route_source_to_offset(enum route_source source)
> >  {
> >      switch (source) {
> >      case ROUTE_SOURCE_CONNECTED:
> > +    case ROUTE_SOURCE_IC_DYNAMIC:
> >          return ROUTE_PRIO_OFFSET_CONNECTED;
> >      case ROUTE_SOURCE_STATIC:
> >          return ROUTE_PRIO_OFFSET_STATIC;
> > diff --git a/northd/northd.h b/northd/northd.h
> > index e4d7de9f9..62e2cf689 100644
> > --- a/northd/northd.h
> > +++ b/northd/northd.h
> > @@ -372,7 +372,8 @@ struct mcast_port_info {
> >      DRR_MODE(CONNECTED_AS_HOST, 1) \
> >      DRR_MODE(STATIC,            2) \
> >      DRR_MODE(NAT,               3) \
> > -    DRR_MODE(LB,                4)
> > +    DRR_MODE(LB,                4) \
> > +    DRR_MODE(IC_DYNAMIC,        5)
> >
> >  enum dynamic_routing_redistribute_mode_bits {
> >  #define DRR_MODE(PROTOCOL, BIT) DRRM_##PROTOCOL##_BIT = BIT,
> > @@ -825,6 +826,8 @@ enum route_source {
> >      ROUTE_SOURCE_NAT,
> >      /* The route is derived from a LB's VIP. */
> >      ROUTE_SOURCE_LB,
> > +    /* The route is derived from an ovn-controller and advertised to
> IC. */
> > +    ROUTE_SOURCE_IC_DYNAMIC,
> >  };
> >
> >  struct parsed_route {
> > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> > index 7d7568c6f..bc3969053 100644
> > --- a/northd/ovn-northd.c
> > +++ b/northd/ovn-northd.c
> > @@ -905,7 +905,6 @@ main(int argc, char *argv[])
> >          &nbrec_load_balancer_col_external_ids,
> >          &nbrec_load_balancer_health_check_col_external_ids,
> >          &nbrec_logical_router_policy_col_external_ids,
> > -        &nbrec_logical_router_static_route_col_external_ids,
> >          &nbrec_meter_col_external_ids,
> >          &nbrec_meter_band_col_external_ids,
> >          &nbrec_mirror_col_external_ids,
> > diff --git a/ovn-nb.xml b/ovn-nb.xml
> > index e9ca27413..aedda71da 100644
> > --- a/ovn-nb.xml
> > +++ b/ovn-nb.xml
> > @@ -3371,6 +3371,12 @@ or
> >            Logical Switch.
> >          </p>
> >
> > +        <p>
> > +          If <code>hub-spoke</code> is in the list then northd will
> synchronize
> > +          all dynamic routes from other router that announce them in
> ovn-ic in
> > +          <ref table="Advertised_Route" db="OVN_Southbound"/> table.
> > +        </p>
>
> this explanation is not very clear (at least to me), can you please
> elaborate?
>
> > +
> >          <p>
> >            This value can be overwritten on a per LRP basis using
> >            <ref column="options" key="dynamic-routing-redistribute"
> > @@ -4458,6 +4464,12 @@ or
> >            via shared Logical Switch.
> >          </p>
> >
> > +        <p>
> > +          If <code>hub-spoke</code> is in the list then northd will
> synchronize
> > +          all dynamic routes from other router that announce them in
> ovn-ic in
> > +          <ref table="Advertised_Route" db="OVN_Southbound"/> table.
> > +        </p>
> > +
>
> ditto
>
> >          <p>
> >            If not set the value from <ref column="options"
> >            key="dynamic-routing-redistribute" table="Logical_Router"/>
> on the
> > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> > index 370a755be..77c5d0034 100644
> > --- a/tests/ovn-ic.at
> > +++ b/tests/ovn-ic.at
> > @@ -4586,3 +4586,100 @@ OVN_CLEANUP_IC([az1], [az2])
> >
> >  AT_CLEANUP
> >  ])
> > +
> > +
> > +OVN_FOR_EACH_NORTHD([
> > +AT_SETUP([ovn-ic -- Check ovn-ic adv and learn from SB Learned Route -
> hub and spoke mode])
> > +
> > +ovn_init_ic_db
> > +
> > +for i in 1 2; do
> > +    ovn_start az$i
> > +    ovn_as az$i
> > +
> > +    # Enable route learning at AZ level
> > +    check ovn-nbctl set nb_global . options:ic-route-learn=true
> > +    # Enable route advertising at AZ level
> > +    check ovn-nbctl set nb_global . options:ic-route-adv=true
> > +done
> > +
> > +# Create new transit switches and LRs. Test topology is next:
> > +#
> > +#
> > +# logical router (lr11) - transit switch (ts11) - logical router (lr12)
> > +#
> > +#
> > +
> > +# Create lr11, lr12 and ts11 and connect them
> > +for i in 1 2; do
> > +    ovn_as az$i
> > +
> > +    lr=lr1$i
> > +    check ovn-nbctl lr-add $lr
> > +
> > +    for j in 1; do
>
> you do not need this for loop here
>
> > +        ts=ts1$j
> > +        check ovn-ic-nbctl --wait=sb --may-exist ts-add $ts
> > +
> > +        lrp=lrp-$lr-$ts
> > +        lsp=lsp-$ts-$lr
> > +        # Create LRP and connect to TS
> > +        check ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i
> 169.254.10$j.$i/24
> > +        check ovn-nbctl lsp-add $ts $lsp \
> > +                -- lsp-set-addresses $lsp router \
> > +                -- lsp-set-type $lsp router \
> > +                -- lsp-set-options $lsp router-port=$lrp
> > +    done
> > +done
> > +
> > +# Create directly-connected route in lr11
>
> it should be lr12
>
> Regards,
> Lorenzo
>
> > +check ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12 aa:aa:aa:aa:bb:01 "
> 192.168.0.1/24"
> > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep
> 192.168 |
> > +             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
> > +192.168.0.0/24 169.254.101.2
> > +])
> > +
> > +ovn_as az2
> > +check ovn-nbctl --wait=sb set Logical_Router lr12
> option:dynamic-routing=true \
> > +    option:dynamic-routing-redistribute="connected,static"
> > +check ovn_as az2 ovn-nbctl --wait=sb lrp-add lr12 lr12-dr1
> 00:00:00:00:ff:01 10.0.0.1/24
> > +dr1=$(fetch_column port_binding _uuid logical_port=lr12-dr1)
> > +datapath=$(fetch_column datapath_binding _uuid external_ids:name=lr12)
> > +
> > +check_uuid ovn-sbctl create Learned_Route \
> > +    datapath=$datapath                    \
> > +    logical_port=$dr1                     \
> > +    ip_prefix=192.168.1.0/24              \
> > +    nexthop=10.0.0.20
> > +
> > +# Check Learned_Route adv in ovn-ic
> > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 |
> > +             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
> > +10.0.0.0/24 169.254.101.2
> > +192.168.0.0/24 169.254.101.2
> > +192.168.1.0/24 169.254.101.2
> > +])
> > +
> > +ovn_as az1
> > +check ovn-nbctl --wait=sb set Logical_Router lr11
> option:dynamic-routing=true \
> > +    option:dynamic-routing-redistribute="connected,static"
> > +# Advertise just 10.0.0.0/24 and 192.168.0.0/24 routes
> > +check_row_count Advertised_Route 1 ip_prefix=192.168.0.0/24
> > +check_row_count Advertised_Route 1 ip_prefix=10.0.0.0/24
> > +check_row_count Advertised_Route 0 ip_prefix=192.168.1.0/24
> > +
> > +
> > +ovn_as az1
> > +check ovn-nbctl --wait=sb set Logical_Router lr11 \
> > +    option:dynamic-routing-redistribute="connected,static,hub-spoke"
> > +# Advertise just 10.0.0.0/24, 192.168.0.0/24 and 192.168.1.0/24 routes
> > +# Route 192.168.1.0/24 is learned by DR from other logical routes
> (lr12)
> > +# And lr12 Advertised it in ovn-ic. Hub-spoke option enable re-routing
> in lr11
> > +check_row_count Advertised_Route 1 ip_prefix=192.168.0.0/24
> > +check_row_count Advertised_Route 1 ip_prefix=10.0.0.0/24
> > +check_row_count Advertised_Route 1 ip_prefix=192.168.1.0/24
> > +
> > +OVN_CLEANUP_IC([az1], [az2])
> > +
> > +AT_CLEANUP
> > +])
> > --
> > 2.43.0
> >
> >
> > --
> >
> >
> >
> >
> > _'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
> >
>

-- 




_‘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