On Thu, Sep 4, 2025 at 2:57 PM Dumitru Ceara via dev <
[email protected]> wrote:

> Commit f2deb24c5c43 ("northd: Sync Advertised_Route to sb.") correctly
> skipped over "link-local connected networks" not creating
> Advertised_Route records for the link-local subnet.  However, when
> implementing the connected-as-host semantics it shouldn't have skipped
> over the (non-LLA) IPs configured on routers/switches connected to said
> interfaces.
>
> It introduced an inconsistency between the case (a) when a router port is
> configured with an explicit IP (and network) and the case (b) when the
> router port is only configured with MAC address (just a link-local IPv6
> address).  In (a), if the router port is configured to advertise
> "connected-as-host" ovn-northd creates Advertised_Route records for all
> IPs known to be configured on the peer switch/router.  In (b), however
> it does not.
>
> This forces CMS to always configure an explicit IP on the router port
> even though that's not necessary for any of the routing decisions.
>
> Fix it by advertising the connected-as-host routes for all connected
> routes generated for a router port.
>
> NOTE: we don't try to verify that advertised host routes are actually
> reachable (there's a route prefix on the router that matches on them).
> This was already the ovn-northd behavior.
>
> Reported-at: https://issues.redhat.com/browse/FDP-1563
> Reported-by: Jakub Libosvar <[email protected]>
> Fixes: f2deb24c5c43 ("northd: Sync Advertised_Route to sb.")
> Signed-off-by: Dumitru Ceara <[email protected]>
> ---
>  northd/en-advertised-route-sync.c | 72 +++++++++++++++++--------------
>  tests/ovn-northd.at               | 72 +++++++++++++++++++++++++++++++
>  2 files changed, 112 insertions(+), 32 deletions(-)
>
> diff --git a/northd/en-advertised-route-sync.c
> b/northd/en-advertised-route-sync.c
> index dfa9f9c447..35def9d227 100644
> --- a/northd/en-advertised-route-sync.c
> +++ b/northd/en-advertised-route-sync.c
> @@ -649,36 +649,44 @@ should_advertise_route(const struct uuidset
> *host_route_lrps,
>      }
>  }
>
> -/* Returns true if the route has already been fully processed for
> - * advertising (e.g., for connected routes when connected-as-host is set).
> - * Returns false otherwise, in which case the a new 'ar_entry' needs to
> - * be created for this route.
> - */
> +/* Returns true if the connected route was advertised as a set of host
> routes
> + * (/32 for IPv4 and /128 for IPv6), one for each individual IP known to
> be
> + * reachable in the connected route's subnet.  Returns false otherwise. */
>  static bool
> -process_prereqs_advertise_route(
> +advertise_routes_as_host_prefix(
>      struct advertised_route_sync_data *data,
>      struct uuidset *host_route_lrps,
>      struct hmap *sync_routes,
>      const struct ovn_datapath *advertising_od,
>      const struct ovn_port *advertising_op,
> -    const struct ovn_port *tracked_op,
> -    enum route_source source)
> +    enum route_source source
> +)
>  {
> +    if (source != ROUTE_SOURCE_CONNECTED) {
> +        return false;
> +    }
> +
>      enum dynamic_routing_redistribute_mode drr =
>          advertising_op->dynamic_routing_redistribute;
> +    if (!drr_mode_CONNECTED_AS_HOST_is_set(drr)) {
> +        return false;
> +    }
> +
> +    uuidset_insert(host_route_lrps, &advertising_op->nbrp->header_.uuid);
> +    publish_host_routes(sync_routes, advertising_od, advertising_op,
> data);
> +    return true;
> +}
>
> +/* Track datapaths (routers/switches) whose changes should trigger
> + * the set of advertised routes.  That includes NAT and LB related
> + * advertised routes. */
> +static void
> +advertise_route_track_od(struct advertised_route_sync_data *data,
> +                         const struct ovn_datapath *advertising_od,
> +                         const struct ovn_port *tracked_op,
> +                         enum route_source source)
> +{
>      switch (source) {
> -    case ROUTE_SOURCE_CONNECTED:
> -        if (drr_mode_CONNECTED_AS_HOST_is_set(drr)) {
> -            const struct uuid *lrp_uuid =
> &advertising_op->nbrp->header_.uuid;
> -            uuidset_insert(host_route_lrps, lrp_uuid);
> -            publish_host_routes(sync_routes, advertising_od,
> advertising_op,
> -                                data);
> -            return true;
> -        }
> -        break;
> -    case ROUTE_SOURCE_STATIC:
> -        break;
>      case ROUTE_SOURCE_NAT:
>          /* If NAT route tracks port on a different DP than the one that
>           * advertises the route, we need to watch for changes on that DP
> as
> @@ -702,12 +710,14 @@ process_prereqs_advertise_route(
>                             &tracked_op->od->nbr->header_.uuid);
>          }
>          break;
> +    case ROUTE_SOURCE_CONNECTED:
> +    case ROUTE_SOURCE_STATIC:
> +        break;
>      case ROUTE_SOURCE_LEARNED:
>          OVS_NOT_REACHED();
>      default:
>          OVS_NOT_REACHED();
>      }
> -    return false;
>  }
>
>  static void
> @@ -728,23 +738,25 @@ advertised_route_table_sync(
>              continue;
>          }
>
> -        if (prefix_is_link_local(&route->prefix, route->plen)) {
> -            continue;
> -        }
> -
>          if (!should_advertise_route(&host_route_lrps, route->od,
>                                      route->out_port, route->source)) {
>              continue;
>          }
>
> -        if (process_prereqs_advertise_route(data, &host_route_lrps,
> +        if (advertise_routes_as_host_prefix(data, &host_route_lrps,
>                                              &sync_routes, route->od,
>                                              route->out_port,
> -                                            route->tracked_port,
>                                              route->source)) {
>              continue;
>          }
>
> +        if (prefix_is_link_local(&route->prefix, route->plen)) {
> +            continue;
> +        }
> +
> +        advertise_route_track_od(data, route->od, route->tracked_port,
> +                                 route->source);
> +
>          ar_entry_add_nocopy(&sync_routes, route->od, route->out_port,
>                              normalize_v46_prefix(&route->prefix,
> route->plen),
>                              route->tracked_port,
> @@ -759,12 +771,8 @@ advertised_route_table_sync(
>              continue;
>          }
>
> -        if (process_prereqs_advertise_route(data, &host_route_lrps,
> -                                            &sync_routes, route_e->od,
> -                                            route_e->op,
> route_e->tracked_port,
> -                                            route_e->source)) {
> -            continue;
> -        }
> +        advertise_route_track_od(data, route_e->od, route_e->tracked_port,
> +                                 route_e->source);
>
>          const struct sbrec_port_binding *tracked_pb =
>              route_e->tracked_port ? route_e->tracked_port->sb : NULL;
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 3d27f10cde..208bef20dc 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -15591,6 +15591,78 @@ AT_CHECK([fetch_column sb:Port_Binding options
> logical_port=lr0-sw0 | grep -q 'd
>  AT_CLEANUP
>  ])
>
> +OVN_FOR_EACH_NORTHD_NO_HV([
> +AT_SETUP([dynamic-routing - host routes - unnumbered LRP interfaces])
> +AT_KEYWORDS([dynamic-routing])
> +ovn_start
> +
> +dnl Logical topology:
> +dnl
> +dnl                       internal-lr
> +dnl                           |
> +dnl                           |
> +dnl                       internal-ls
> +dnl                           |
> +dnl                   +-------+----+
> +dnl                   |            |
> +dnl                   |            +--- ovs-bridge
> +dnl                   |            |
> +dnl                   |       +----+
> +dnl                   |       |
> +dnl                   |   public-ls
> +dnl                   |       |
> +dnl                   |       |
> +dnl                   |       | (explicit IP)
> +dnl  (no explicit IP) +-- public-lr (BGP enabled)
> +dnl     (just LLA)            |
> +dnl                           |
> +dnl                        <fabric>
> +dnl
> +dnl When configured to advertise connected-routes "as-host" prefixes
> +dnl router ports should also include connected router/switch IPs reachable
> +dnl via unnumbered router ports (that only have LLA configured).
> +
> +check ovn-nbctl --wait=sb                                             \
> +  -- lr-add internal-lr                                               \
> +     -- lrp-add internal-lr internal-lrp 00:00:00:00:00:01 1.1.1.1/24 \
> +  -- ls-add internal-ls                                               \
> +     -- lsp-add internal-ls internal-ls-lrp                           \
> +     -- lsp-set-type internal-ls-lrp router                           \
> +     -- lsp-set-options internal-ls-lrp router-port=internal-lrp      \
> +     -- lsp-set-addresses internal-ls-lrp router                      \
> +     -- lsp-add internal-ls internal-ls-lla-lrp                       \
> +     -- lsp-set-type internal-ls-lla-lrp router                       \
> +     -- lsp-set-options internal-ls-lla-lrp router-port=lla-lrp       \
> +     -- lsp-set-addresses internal-ls-lla-lrp router                  \
> +     -- lsp-add internal-ls internal-ls-localnet                      \
> +     -- lsp-set-type internal-ls-localnet localnet                    \
> +  -- ls-add public-ls                                                 \
> +     -- lsp-add public-ls public-ls-lrp                               \
> +     -- lsp-set-type public-ls-lrp router                             \
> +     -- lsp-set-options public-ls-lrp router-port=public-lrp          \
> +     -- lsp-set-addresses public-ls-lrp router                        \
> +     -- lsp-add public-ls public-ls-localnet                          \
> +     -- lsp-set-type public-ls-localnet localnet                      \
> +  -- lr-add public-lr                                                 \
> +     -- lrp-add public-lr public-lrp 00:00:00:00:00:02 1.1.1.2/24     \
> +     -- lrp-add public-lr lla-lrp 00:00:00:00:00:03                   \
> +     -- lrp-add public-lr fab-lrp 00:00:00:00:00:04 2.2.2.1/24        \
> +     -- set Logical_Router public-lr option:dynamic-routing=true      \
> +     -- set Logical_Router_Port lla-lrp                               \
> +        options:dynamic-routing-redistribute="connected-as-host"
> +
> +pub_lr_dp=$(fetch_column Datapath_Binding _uuid
> external_ids:name=public-lr)
> +lla_lrp_pb=$(fetch_column Port_Binding _uuid logical_port=lla-lrp)
> +int_lrp_pb=$(fetch_column Port_Binding _uuid logical_port=internal-lrp)
> +check_column 1.1.1.1 Advertised_Route ip_prefix \
> +    datapath=$pub_lr_dp                         \
> +    logical_port=$lla_lrp_pb                    \
> +    tracked_port=$int_lrp_pb
> +check_row_count Advertised_Route 1
> +
> +AT_CLEANUP
> +])
> +
>  OVN_FOR_EACH_NORTHD_NO_HV([
>  AT_SETUP([dynamic-routing incremental processing])
>  AT_KEYWORDS([dynamic-routing])
> --
> 2.50.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Looks good to me, thanks.
Acked-by: Ales Musil <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to