Enable east-west traffic rerouting for locally connected networks between
Availability Zones (AZs). This allows traffic destined to a locally connected
network to be forcibly forwarded to a remote AZ for processing (e.g.,
firewalling, inspection, service chaining) and then delivered back.

Introduce new option (override-connected) for static routes. Static route with
this option set overrides local directly connected route. ovn-ic is extended to
pass this option during advertise-learn processing. Also, route_table column in
ic database now used for connected routes too.

IC route priorities are changed to raise the priority of learned connected
routes that have a route table set. The new priority order for the same
prefix (highest to lowest) is:

  1. Static routes (local or IC-learned) with override-connected=true
  2. IC-learned connected routes with route_table set (auto-marked)
  3. All other connected routes (local and learned)
  4. All other static routes
  5. Routes learned from external sources (e.g., BGP)
  6. Source-IP routes (lowest priority)

(It's also now described in ovn-northd manpage)

Signed-off-by: Alexandra Rukomoinikova <[email protected]>
---
v5 --> v6: 1) fixed review comments in docs
           2) fixed ovn-k test: problem was in the incorrect
              calculation of metrics for src-ip static routes
v4 --> v5: Rebased, added documentation to ovn-northd manpage AD for routing
v4 
(https://patchwork.ozlabs.org/project/ovn/patch/[email protected]/)
---
 NEWS                           |   4 +
 ic/ovn-ic.c                    |  81 ++++++++---
 lib/ovn-util.h                 |   3 +
 northd/en-learned-route-sync.c |   2 +-
 northd/northd.c                | 158 +++++++++++++---------
 northd/northd.h                |   8 +-
 northd/ovn-northd.8.xml        |  44 ++++++
 ovn-ic-sb.ovsschema            |   7 +-
 ovn-ic-sb.xml                  |  27 ++++
 ovn-nb.xml                     |   8 ++
 tests/ovn-ic.at                | 182 ++++++++++++++++++++++++-
 tests/ovn-northd.at            | 238 ++++++++++++++++-----------------
 utilities/ovn-nbctl.8.xml      |   6 +
 utilities/ovn-nbctl.c          |  28 +++-
 14 files changed, 585 insertions(+), 211 deletions(-)

diff --git a/NEWS b/NEWS
index 8633ba8bb..fdc02b4a8 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,10 @@ Post v26.03.0
    - Dynamic Routing:
      * Add support for hub-and-spoke propagation via the "hub-spoke" option
        in dynamic-routing-redistribute settings.
+   - Added "override-connected" option to Logical Router Static Routes to mark
+     static routes as higher-priority than connected routes, which in turn led
+     to changes in administrative distance for specific route types. Please see
+     the "Route Administrative Distance" section of the ovn-northd manpage.
 
 OVN v26.03.0 - xxx xx xxxx
 --------------------------
diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index ba9490658..fb7723641 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -1309,6 +1309,7 @@ struct ic_route_info {
     const char *origin;
     const char *route_table;
     const char *route_tag;
+    bool override_connected;
     struct uuid ic_route_uuid;
 
     const struct nbrec_logical_router *nb_lr;
@@ -1326,16 +1327,25 @@ struct ic_route_info {
     const struct nbrec_load_balancer *nb_lb;
 };
 
+static inline bool
+get_override_connected(const struct smap *options)
+{
+    return smap_get_bool(options, ROUTE_OVERRIDE_CONNECTED, false);
+}
+
 static uint32_t
 ic_route_hash(const struct in6_addr *prefix, unsigned int plen,
               const struct in6_addr *nexthop, const char *origin,
-              const char *route_table, const struct uuid *ic_route_uuid)
+              const char *route_table,
+              const struct uuid *ic_route_uuid,
+              bool override_connected)
 {
     uint32_t basis = ic_route_uuid ? uuid_hash(ic_route_uuid) : 0;
     basis = hash_bytes(prefix, sizeof *prefix, basis);
     basis = hash_int((uint32_t) plen, basis);
     basis = hash_string(origin, basis);
     basis = hash_string(route_table, basis);
+    basis = hash_boolean(override_connected, basis);
     return hash_bytes(nexthop, sizeof *nexthop, basis);
 }
 
@@ -1343,16 +1353,18 @@ static struct ic_route_info *
 ic_route_find(struct hmap *routes, const struct in6_addr *prefix,
               unsigned int plen, const struct in6_addr *nexthop,
               const char *origin, const char *route_table,
-              const struct uuid *ic_route_uuid, uint32_t hash)
+              const struct uuid *ic_route_uuid,
+              bool override_connected, uint32_t hash)
 {
     struct ic_route_info *r;
     if (!hash) {
         hash = ic_route_hash(prefix, plen, nexthop, origin, route_table,
-                             ic_route_uuid);
+                             ic_route_uuid, override_connected);
     }
     HMAP_FOR_EACH_WITH_HASH (r, node, hash, routes) {
         if (ipv6_addr_equals(&r->prefix, prefix) &&
             r->plen == plen &&
+            r->override_connected == override_connected &&
             ipv6_addr_equals(&r->nexthop, nexthop) &&
             !strcmp(r->origin, origin) &&
             !strcmp(r->route_table ? r->route_table : "", route_table) &&
@@ -1410,11 +1422,14 @@ add_to_routes_learned(struct hmap *routes_learned,
         return false;
     }
     const char *origin = smap_get_def(&nb_route->options, "origin", "");
+    bool override_connected = get_override_connected(&nb_route->options);
 
     uint32_t hash = ic_route_hash(&prefix, plen, &nexthop, origin,
-                                  nb_route->route_table, ic_route_uuid);
+                                  nb_route->route_table, ic_route_uuid,
+                                  override_connected);
     if (ic_route_find(routes_learned, &prefix, plen, &nexthop, origin,
-                      nb_route->route_table, ic_route_uuid, hash)) {
+                      nb_route->route_table, ic_route_uuid,
+                      override_connected, hash)) {
         /* Route was added to learned on previous iteration. */
         return true;
     }
@@ -1428,6 +1443,7 @@ add_to_routes_learned(struct hmap *routes_learned,
     ic_route->route_table = nb_route->route_table;
     ic_route->nb_lr = nb_lr;
     ic_route->ic_route_uuid = *ic_route_uuid;
+    ic_route->override_connected = override_connected;
     hmap_insert(routes_learned, &ic_route->node, hash);
 
     return true;
@@ -1588,7 +1604,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 override_connected)
 {
     ovs_assert(nb_route || nb_lrp || nb_lb || nb_lr);
 
@@ -1597,10 +1613,10 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
in6_addr prefix,
     }
 
     uint hash = ic_route_hash(&prefix, plen, &nexthop, origin,
-                              route_table, NULL);
+                              route_table, NULL, override_connected);
 
     if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, route_table,
-                       NULL, hash)) {
+                       NULL, override_connected, hash)) {
         struct ic_route_info *ic_route = xzalloc(sizeof *ic_route);
         ic_route->prefix = prefix;
         ic_route->plen = plen;
@@ -1612,6 +1628,7 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
in6_addr prefix,
         ic_route->nb_lr = nb_lr;
         ic_route->nb_lb = nb_lb;
         ic_route->route_tag = route_tag;
+        ic_route->override_connected = override_connected;
         hmap_insert(routes_ad, &ic_route->node, hash);
     } else {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
@@ -1645,6 +1662,8 @@ add_static_to_routes_ad(
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
+    bool override_connected = get_override_connected(&nb_route->options);
+
     if (!parse_route(nb_route->ip_prefix, nb_route->nexthop,
                      &prefix, &plen, &nexthop)) {
         return;
@@ -1684,7 +1703,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, override_connected);
 }
 
 static void
@@ -1693,8 +1712,9 @@ add_network_to_routes_ad(struct hmap *routes_ad, const 
char *network,
                          const struct lport_addresses *nexthop_addresses,
                          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 char *route_tag,
+                         const char *ts_route_table,
                          bool is_src_dynamic)
 {
     struct in6_addr prefix, nexthop;
@@ -1745,11 +1765,25 @@ add_network_to_routes_ad(struct hmap *routes_ad, const 
char *network,
         ds_destroy(&msg);
     }
 
+    /* Create additional route to local and remote networks that have
+     * common route table name with port attached to transit switch having
+     * same route table name.
+     * As a result, traffic that is processed within such route table and is
+     * routed cross az will select port attached to transit switch specially
+     * allocated to process traffic within that route table.
+     */
+
+    if (*ts_route_table) {
+        add_to_routes_ad(routes_ad, prefix, plen, nexthop,
+                         ROUTE_ORIGIN_CONNECTED, ts_route_table,
+                         nb_lrp, NULL, nb_lr, NULL, route_tag, true);
+    }
+
     const char *origin = is_src_dynamic ? ROUTE_ORIGIN_CONNECTED_DYNAMIC :
                                           ROUTE_ORIGIN_CONNECTED;
     /* directly-connected routes go to <main> route table */
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, origin,
-                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag);
+                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag, false);
 }
 
 static void
@@ -1807,7 +1841,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);
 }
@@ -2189,11 +2223,15 @@ sync_learned_routes(struct ic_context *ctx,
                 continue;
             }
 
+            bool override_connected =
+                get_override_connected(&isb_route->options);
             struct ic_route_info *route_learned
                 = ic_route_find(&ic_lr->routes_learned, &prefix, plen,
                                 &nexthop, isb_route->origin,
                                 isb_route->route_table,
-                                &isb_route->header_.uuid, 0);
+                                &isb_route->header_.uuid,
+                                override_connected, 0);
+
             if (route_learned) {
                 hmap_remove(&ic_lr->routes_learned, &route_learned->node);
                 free(route_learned);
@@ -2214,6 +2252,10 @@ sync_learned_routes(struct ic_context *ctx,
                 nbrec_logical_router_static_route_update_options_setkey(
                     nb_route, "origin", isb_route->origin);
                 free(uuid_s);
+                if (override_connected) {
+                    nbrec_logical_router_static_route_update_options_setkey(
+                        nb_route, ROUTE_OVERRIDE_CONNECTED, "true");
+                }
                 nbrec_logical_router_update_static_routes_addvalue(ic_lr->lr,
                     nb_route);
             }
@@ -2300,9 +2342,11 @@ advertise_routes(struct ic_context *ctx,
             icsbrec_route_delete(isb_route);
             continue;
         }
+        bool override_connected = get_override_connected(&isb_route->options);
         struct ic_route_info *route_adv =
             ic_route_find(routes_ad, &prefix, plen, &nexthop,
-                          isb_route->origin, isb_route->route_table, NULL, 0);
+                          isb_route->origin, isb_route->route_table,
+                          NULL, override_connected, 0);
         if (!route_adv) {
             /* Delete the extra route from IC-SB. */
             VLOG_DBG("Delete route %s -> %s from IC-SB, which is not found"
@@ -2346,6 +2390,10 @@ advertise_routes(struct ic_context *ctx,
         icsbrec_route_set_route_table(isb_route, route_adv->route_table
                                                  ? route_adv->route_table
                                                  : "");
+        if (route_adv->override_connected) {
+            icsbrec_route_update_options_setkey(isb_route,
+                ROUTE_OVERRIDE_CONNECTED, "true");
+        }
         free(prefix_s);
         free(nexthop_s);
 
@@ -2400,7 +2448,8 @@ 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, false);
+                                         lr, ts_lrp, route_tag,
+                                         ts_route_table, false);
             }
         } else {
             /* The router port of the TS port is ignored. */
@@ -2455,7 +2504,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, true);
+                                 lr, ts_lrp, route_tag, ts_route_table, true);
     }
     sbrec_learned_route_index_destroy_row(filter);
 }
diff --git a/lib/ovn-util.h b/lib/ovn-util.h
index b44c9c770..4e8cf6f52 100644
--- a/lib/ovn-util.h
+++ b/lib/ovn-util.h
@@ -34,6 +34,7 @@
 #define ROUTE_ORIGIN_STATIC "static"
 #define ROUTE_ORIGIN_LB "loadbalancer"
 #define ROUTE_ORIGIN_CONNECTED_DYNAMIC "connected-dynamic"
+#define ROUTE_OVERRIDE_CONNECTED "override-connected"
 
 #define ETH_CRC_LENGTH 4
 #define ETHERNET_OVERHEAD (ETH_HEADER_LEN + ETH_CRC_LENGTH)
@@ -43,6 +44,8 @@
 
 #define IDL_LOOP_MAX_DURATION_MS 500
 
+#define MAX_PREFIX_LEN 128
+
 struct eth_addr;
 struct nbrec_logical_router;
 struct nbrec_logical_router_port;
diff --git a/northd/en-learned-route-sync.c b/northd/en-learned-route-sync.c
index 4f7a12a28..0d1953276 100644
--- a/northd/en-learned-route-sync.c
+++ b/northd/en-learned-route-sync.c
@@ -200,7 +200,7 @@ parse_route_from_sbrec_route(struct hmap *parsed_routes_out,
     }
 
     return parsed_route_add(od, nexthop, &prefix, plen, false, lrp_addr_s,
-                            out_port, 0, false, false, NULL,
+                            out_port, 0, false, false, false, NULL,
                             ROUTE_SOURCE_LEARNED, &route->header_, NULL,
                             parsed_routes_out);
 }
diff --git a/northd/northd.c b/northd/northd.c
index 0b52db6cf..6028bb8d3 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -377,14 +377,23 @@ static const char *reg_ct_state[] = {
 /*
  * Route offsets implement logic to prioritize traffic for routes with
  * same ip_prefix values:
- *  1. (highest priority) connected routes
- *  2. static routes
- *  3. routes learned from the outside via ovn-controller (e.g. bgp)
- *  4. (lowest priority) src-ip routes */
-#define ROUTE_PRIO_OFFSET_MULTIPLIER 8
-#define ROUTE_PRIO_OFFSET_LEARNED 2
-#define ROUTE_PRIO_OFFSET_STATIC 4
+ *  1. High-priority static routes,
+ *     (override-connected option is set), including ic-learned with
+ *     override-connected option set to true.
+ *  2. ic-learned connected routes with route_table set.
+ *  3. connected routes, including ic-learned.
+ *  4. static routes, including ic-learned.
+ *  5. routes learned from the outside via ovn-controller (e.g. bgp)
+ *  6. (lowest priority) src-ip routes */
+#define ROUTE_PRIO_OFFSET_MULTIPLIER 12
+#define ROUTE_PRIO_OFFSET_PRIORITY_STATIC 10
+#define ROUTE_PRIO_OFFSET_IC_LEARNED_CONNECTED_WITH_TABLEID 8
 #define ROUTE_PRIO_OFFSET_CONNECTED 6
+#define ROUTE_PRIO_OFFSET_STATIC 4
+#define ROUTE_PRIO_OFFSET_LEARNED 2
+
+#define ROUTE_PRIO_BASE_SHIFT ((MAX_PREFIX_LEN + 1) * \
+                              ROUTE_PRIO_OFFSET_MULTIPLIER)
 
 /* ovn_stages used by northd for logical switches and logical routers.
  * The first three components are combined to form the constant stage's
@@ -12145,6 +12154,10 @@ parsed_route_lookup(struct hmap *routes, size_t hash,
             continue;
         }
 
+        if (pr->override_connected != new_pr->override_connected) {
+            continue;
+        }
+
         if (pr->is_discard_route != new_pr->is_discard_route) {
             continue;
         }
@@ -12175,6 +12188,7 @@ parsed_route_init(const struct ovn_datapath *od,
                   uint32_t route_table_id,
                   bool is_src_route,
                   bool ecmp_symmetric_reply,
+                  bool override_connected,
                   const struct sset *ecmp_selection_fields,
                   enum route_source source,
                   const struct ovn_port *tracked_port,
@@ -12190,6 +12204,7 @@ parsed_route_init(const struct ovn_datapath *od,
     new_pr->is_src_route = is_src_route;
     new_pr->od = od;
     new_pr->ecmp_symmetric_reply = ecmp_symmetric_reply;
+    new_pr->override_connected = override_connected;
     new_pr->is_discard_route = is_discard_route;
     new_pr->lrp_addr_s = nullable_xstrdup(lrp_addr_s);
     new_pr->out_port = out_port;
@@ -12218,7 +12233,8 @@ parsed_route_clone(const struct parsed_route *pr)
     struct parsed_route *new_pr = parsed_route_init(
         pr->od, nexthop, pr->prefix, pr->plen, pr->is_discard_route,
         pr->lrp_addr_s, pr->out_port, pr->route_table_id, pr->is_src_route,
-        pr->ecmp_symmetric_reply, &pr->ecmp_selection_fields, pr->source,
+        pr->ecmp_symmetric_reply, pr->override_connected,
+        &pr->ecmp_selection_fields, pr->source,
         pr->tracked_port, pr->source_hint);
 
     new_pr->hash = pr->hash;
@@ -12279,6 +12295,7 @@ parsed_route_add(const struct ovn_datapath *od,
                  uint32_t route_table_id,
                  bool is_src_route,
                  bool ecmp_symmetric_reply,
+                 bool override_connected,
                  const struct sset *ecmp_selection_fields,
                  enum route_source source,
                  const struct ovsdb_idl_row *source_hint,
@@ -12286,10 +12303,12 @@ parsed_route_add(const struct ovn_datapath *od,
                  struct hmap *routes)
 {
 
-    struct parsed_route *new_pr = parsed_route_init(
-        od, nexthop, *prefix, plen, is_discard_route, lrp_addr_s, out_port,
-        route_table_id, is_src_route, ecmp_symmetric_reply,
-        ecmp_selection_fields, source, tracked_port, source_hint);
+    struct parsed_route *new_pr
+        = parsed_route_init(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, tracked_port, source_hint);
 
     new_pr->hash = route_hash(new_pr);
 
@@ -12417,6 +12436,8 @@ parsed_routes_add_static(const struct ovn_datapath *od,
     bool ecmp_symmetric_reply = smap_get_bool(&route->options,
                                          "ecmp_symmetric_reply",
                                          false);
+    bool override_connected = smap_get_bool(&route->options,
+                                            ROUTE_OVERRIDE_CONNECTED, false);
 
     const char *origin = smap_get_def(&route->options, "origin", "");
     enum route_source source;
@@ -12430,7 +12451,8 @@ parsed_routes_add_static(const struct ovn_datapath *od,
 
     parsed_route_add(od, nexthop, &prefix, plen, is_discard_route, lrp_addr_s,
                      out_port, route_table_id, is_src_route,
-                     ecmp_symmetric_reply, &ecmp_selection_fields, source,
+                     ecmp_symmetric_reply, override_connected,
+                     &ecmp_selection_fields, source,
                      &route->header_, NULL, routes);
     sset_destroy(&ecmp_selection_fields);
 }
@@ -12446,8 +12468,7 @@ parsed_routes_add_connected(const struct ovn_datapath 
*od,
 
         in6_addr_set_mapped_ipv4(&prefix, addr->network);
         parsed_route_add(od, NULL, &prefix, addr->plen,
-                         false, addr->addr_s, op,
-                         0, false,
+                         false, addr->addr_s, op, 0, false, false,
                          false, NULL, ROUTE_SOURCE_CONNECTED,
                          &op->nbrp->header_, NULL, routes);
     }
@@ -12455,10 +12476,9 @@ parsed_routes_add_connected(const struct ovn_datapath 
*od,
     for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
         const struct ipv6_netaddr *addr = &op->lrp_networks.ipv6_addrs[i];
 
-        parsed_route_add(od, NULL, &addr->network, addr->plen,
-                         false, addr->addr_s, op,
-                         0, false,
-                         false, NULL, ROUTE_SOURCE_CONNECTED,
+        parsed_route_add(od, NULL, &addr->network, addr->plen, false,
+                         addr->addr_s, op, 0, false, false, false,
+                         NULL, ROUTE_SOURCE_CONNECTED,
                          &op->nbrp->header_, NULL, routes);
     }
 }
@@ -12513,17 +12533,25 @@ build_route_prefix_s(const struct in6_addr *prefix, 
unsigned int plen)
     return prefix_s;
 }
 
-static uint16_t
-route_source_to_offset(enum route_source source)
+static int
+get_route_offset(enum route_source source,
+                 bool override_connected)
 {
     switch (source) {
     case ROUTE_SOURCE_CONNECTED:
     case ROUTE_SOURCE_IC_DYNAMIC:
-        return ROUTE_PRIO_OFFSET_CONNECTED;
+        return (override_connected)
+               ? ROUTE_PRIO_OFFSET_IC_LEARNED_CONNECTED_WITH_TABLEID
+               : ROUTE_PRIO_OFFSET_CONNECTED;
+
     case ROUTE_SOURCE_STATIC:
-        return ROUTE_PRIO_OFFSET_STATIC;
+        return (override_connected)
+               ? ROUTE_PRIO_OFFSET_PRIORITY_STATIC
+               : ROUTE_PRIO_OFFSET_STATIC;
+
     case ROUTE_SOURCE_LEARNED:
         return ROUTE_PRIO_OFFSET_LEARNED;
+
     /* Dynamic route types (NAT, LB, and connected-as-host) are not used. */
     case ROUTE_SOURCE_NAT:
     case ROUTE_SOURCE_LB:
@@ -12533,39 +12561,19 @@ route_source_to_offset(enum route_source source)
     }
 }
 
-static void
-build_route_match(const struct ovn_port *op_inport, uint32_t rtb_id,
-                  const char *network_s, int plen, bool is_src_route,
-                  bool is_ipv4, struct ds *match, uint16_t *priority,
-                  enum route_source source, bool has_protocol_match)
+static uint16_t
+calc_priority(int plen,
+              enum route_source source,
+              bool override_connected,
+              bool is_src_route,
+              bool has_protocol_match)
 {
-    const char *dir;
-    int ofs = route_source_to_offset(source);
-
-    /* The priority here is calculated to implement longest-prefix-match
-     * routing. */
-    if (is_src_route) {
-        dir = "src";
-        ofs = 0;
-    } else {
-        dir = "dst";
-    }
+    int priority = is_src_route ? 0 :
+                   get_route_offset(source, override_connected);
 
-    if (op_inport) {
-        ds_put_format(match, "inport == %s && ", op_inport->json_key);
-    }
-    if (rtb_id || source == ROUTE_SOURCE_STATIC ||
-            source == ROUTE_SOURCE_LEARNED) {
-        ds_put_format(match, "%s == %d && ", REG_ROUTE_TABLE_ID, rtb_id);
-    }
+    priority += (plen * ROUTE_PRIO_OFFSET_MULTIPLIER) + has_protocol_match;
 
-    if (has_protocol_match) {
-        ofs += 1;
-    }
-    *priority = (plen * ROUTE_PRIO_OFFSET_MULTIPLIER) + ofs;
-
-    ds_put_format(match, "ip%s.%s == %s/%d", is_ipv4 ? "4" : "6", dir,
-                  network_s, plen);
+    return priority + ROUTE_PRIO_BASE_SHIFT;
 }
 
 bool
@@ -12756,10 +12764,21 @@ build_ecmp_route_flow(struct lflow_table *lflows,
     struct ds route_match = DS_EMPTY_INITIALIZER;
 
     char *prefix_s = build_route_prefix_s(&eg->prefix, eg->plen);
-    build_route_match(NULL, eg->route_table_id, prefix_s, eg->plen,
-                      eg->is_src_route, is_ipv4_prefix, &route_match,
-                      &priority, eg->source,
-                      protocol != NULL);
+
+    if (eg->route_table_id || eg->source == ROUTE_SOURCE_STATIC
+        || eg->source == ROUTE_SOURCE_LEARNED) {
+        ds_put_format(&route_match, "%s == %d && ", REG_ROUTE_TABLE_ID,
+                      eg->route_table_id);
+    }
+
+    ds_put_format(&route_match, "ip%s.%s == %s/%d",
+                  is_ipv4_prefix ? "4" : "6",
+                  eg->is_src_route ? "src" : "dst",
+                  prefix_s, eg->plen);
+
+    priority = calc_priority(eg->plen, eg->source, false,
+                             eg->is_src_route, protocol != NULL);
+
     free(prefix_s);
 
     struct ds actions = DS_EMPTY_INITIALIZER;
@@ -12886,10 +12905,12 @@ add_route(struct lflow_table *lflows, const struct 
ovn_datapath *od,
           const struct sset *bfd_ports,
           const struct ovsdb_idl_row *stage_hint, bool is_discard_route,
           enum route_source source, struct lflow_ref *lflow_ref,
-          bool is_ipv4_prefix, bool is_ipv4_nexthop)
+          bool is_ipv4_prefix, bool is_ipv4_nexthop,
+          bool override_connected)
 {
     struct ds match = DS_EMPTY_INITIALIZER;
-    uint16_t priority;
+    uint16_t priority = calc_priority(plen, source, override_connected,
+                                      is_src_route, false);
     const struct ovn_port *op_inport = NULL;
 
     /* IPv6 link-local addresses must be scoped to the local router port. */
@@ -12900,8 +12921,19 @@ add_route(struct lflow_table *lflows, const struct 
ovn_datapath *od,
             op_inport = op;
         }
     }
-    build_route_match(op_inport, rtb_id, network_s, plen, is_src_route,
-                      is_ipv4_prefix, &match, &priority, source, false);
+
+    if (op_inport) {
+        ds_put_format(&match, "inport == %s && ", op_inport->json_key);
+    }
+    if (rtb_id || source == ROUTE_SOURCE_STATIC ||
+        source == ROUTE_SOURCE_LEARNED) {
+        ds_put_format(&match, "%s == %d && ", REG_ROUTE_TABLE_ID, rtb_id);
+    }
+
+    ds_put_format(&match, "ip%s.%s == %s/%d",
+                  is_ipv4_prefix ? "4" : "6",
+                  is_src_route ? "src" : "dst",
+                  network_s, plen);
 
     struct ds common_actions = DS_EMPTY_INITIALIZER;
     struct ds actions = DS_EMPTY_INITIALIZER;
@@ -12966,7 +12998,7 @@ build_route_flow(struct lflow_table *lflows, const 
struct ovn_datapath *od,
               route->route_table_id, bfd_ports,
               route->source_hint,
               route->is_discard_route, route->source, lflow_ref,
-              is_ipv4_prefix, is_ipv4_nexthop);
+              is_ipv4_prefix, is_ipv4_nexthop, route->override_connected);
 
     free(prefix_s);
 }
@@ -18706,7 +18738,7 @@ build_routable_flows_for_router_port(
                               bfd_ports, &router_port->nbrp->header_,
                               false, ROUTE_SOURCE_CONNECTED,
                               lrp->stateful_lflow_ref,
-                              true, is_ipv4_nexthop ? true : false);
+                              true, is_ipv4_nexthop ? true : false, false);
                 }
             }
         }
diff --git a/northd/northd.h b/northd/northd.h
index e86d39f9a..22c752c8a 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -840,15 +840,16 @@ enum route_source {
 struct parsed_route {
     struct hmap_node key_node;
     struct in6_addr prefix;
-    unsigned int plen;
     struct in6_addr *nexthop; /* NULL for ROUTE_SOURCE_CONNECTED */
-    bool is_src_route;
+    unsigned int plen;
     uint32_t route_table_id;
     uint32_t hash;
+    bool is_src_route;
     bool ecmp_symmetric_reply;
+    bool override_connected;
     bool is_discard_route;
-    const struct ovn_datapath *od;
     bool stale;
+    const struct ovn_datapath *od;
     struct sset ecmp_selection_fields;
     enum route_source source;
     const struct ovsdb_idl_row *source_hint;
@@ -875,6 +876,7 @@ struct parsed_route *parsed_route_add(
     uint32_t route_table_id,
     bool is_src_route,
     bool ecmp_symmetric_reply,
+    bool override_connected,
     const struct sset *ecmp_selection_fields,
     enum route_source source,
     const struct ovsdb_idl_row *source_hint,
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 4d6370da6..1d9e6b587 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -6293,6 +6293,50 @@ clone {
       </ul>
     </p>
 
+    <h1>Route Administrative Distance in OVN</h1>
+
+    <p>
+      In OVN, routes are selected based on an administrative distance, similar
+      to traditional networking but with some differences.
+      Routes with higher priority are preferred over those with lower priority.
+      The priority order, from highest to lowest, is as follows:
+    </p>
+
+    <p>
+      <ol>
+        <li>
+          High-priority static routes - includes routes with
+          <code>override-connected</code> option set, as well as ic-learned
+          routes with <code>override-connected</code> option set to true.
+        </li>
+
+        <li>
+          Ic-learned connected routes with route_table - connected routes
+          learned via IC that have the <code>route_table</code> parameter set.
+        </li>
+
+        <li>
+          Connected routes - directly connected routes, including ic-learned
+          connected routes that do not have a <code>route_table</code> set.
+        </li>
+
+        <li>
+          Static routes - manually configured static routes.
+        </li>
+
+        <li>
+          Learned routes - routes learned from outside via ovn-controller.
+        </li>
+
+        <li>
+          Src-ip routes - source-based static IP routes.
+          Please see the <code>OVN_Northbound</code> database
+          <code>Logical_Router_Static_Route</code> table documentation in
+          <code>ovn-nb</code> for details.
+        </li>
+      </ol>
+    </p>
+
     <h1>Drop sampling</h1>
 
     <p>
diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema
index e0e0fef5e..9208e7ab5 100644
--- a/ovn-ic-sb.ovsschema
+++ b/ovn-ic-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_IC_Southbound",
-    "version": "2.5.0",
-    "cksum": "1892994110 9713",
+    "version": "2.6.0",
+    "cksum": "2842701319 9868",
     "tables": {
         "IC_SB_Global": {
             "columns": {
@@ -118,6 +118,9 @@
                     "enum": ["set",
                              ["connected", "static", "loadbalancer",
                               "connected-dynamic"]]}}},
+                "options": {
+                    "type": {"key": "string", "value": "string",
+                             "min": 0, "max": "unlimited"}},
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
                              "min": 0, "max": "unlimited"}}},
diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml
index f30760100..f0d450681 100644
--- a/ovn-ic-sb.xml
+++ b/ovn-ic-sb.xml
@@ -358,6 +358,14 @@
         have more than one Transit Switch, which interconnects them,
         directly-connected routes will be added via each transit switch port
         and configured as ECMP routes.
+        Additionally, these routes will be advertised to other AZ and learned
+        into route table that has the same name in the remote logical router.
+        When learned, these routes are automatically marked with
+        the <code>override-connected</code> option, giving them higher priority
+        than any local connected route with same prefix in that route table.
+        This enables policy-based routing scenarios where traffic processed
+        within a specific route table can be forcibly forwarded to remote AZ
+        even when local connected route exists.
         </p>
         <p>
         Static routes within route tables will be advertised and learned only
@@ -399,6 +407,25 @@
         </p>
       </column>
     </group>
+
+    <group title="Options">
+      <column name="options">
+        This column provides general key/value settings. The supported
+        options are described individually below.
+      </column>
+
+      <column name="options" key="override-connected"
+              type='{"type": "boolean"}'>
+        <p>
+            This option is a copy of its Northbound DB counterpart.
+        </p>
+        <p>
+            For connected routes this option is set to true if there is a route
+            table associated with given connected route, i.e.
+            <ref table="Route" column="route_table"/> is not empty.
+        </p>
+     </column>
+    </group>
   </table>
 
   <table name="Connection" title="OVSDB client connections.">
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 592008745..916ae811e 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -5056,6 +5056,14 @@ or
           <li>static</li>
         </ol>
       </column>
+      <column name="options" key="override-connected">
+        This option can be manually set for local static routes and
+        automatically set for ovn-interconnected learned routes.
+        Default value: <code>false</code>.
+
+        This option raises route's priority to be highest among routes
+        with same prefix.
+      </column>
     </group>
 
   </table>
diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
index 0fa7c4f29..bf50da5de 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -885,9 +885,10 @@ check ovn_as az1 ovn-nbctl lb-add lb_v6 [[4242::1]]:80 
"[[4242::2]]:80"
 check ovn_as az1 ovn-nbctl lr-lb-add lr1 lb_v6
 OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
4242])
 
-AT_CHECK([ovn-ic-sbctl list route | grep 'ip_prefix.*4242' -A 2], [0], [dnl
+AT_CHECK([ovn-ic-sbctl list route | grep 'ip_prefix.*4242' -A 3], [0], [dnl
 ip_prefix           : "4242::1/128"
 nexthop             : "2001:db8:1::1"
+options             : {}
 origin              : loadbalancer
 ])
 
@@ -1211,6 +1212,7 @@ Route Table <main>:
 Route Table rtb1:
              10.11.1.0/24             169.254.100.1 dst-ip (learned)
              10.11.2.0/24               169.254.0.1 dst-ip
+           192.168.0.0/24             169.254.100.1 dst-ip (learned) 
override-connected
              10.22.2.0/24               169.254.0.2 src-ip
                 0.0.0.0/0             169.254.100.1 dst-ip (learned)
 ])
@@ -1332,8 +1334,11 @@ check ovn-ic-nbctl --wait=sb sync
 OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
              grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl
 192.168.0.0/24 169.254.101.2 ecmp
+192.168.0.0/24 169.254.101.2 override-connected
 192.168.0.0/24 169.254.102.2 ecmp
+192.168.0.0/24 169.254.102.2 override-connected
 192.168.0.0/24 169.254.103.2 ecmp
+192.168.0.0/24 169.254.103.2 override-connected
 ])
 
 # Test static routes from lr12 rtbs rtb1,rtb2,rtb3 were learned to lr11
@@ -1341,22 +1346,27 @@ OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl 
--route-table=rtb1 lr-route-list lr11]
 IPv4 Routes
 Route Table rtb1:
             10.10.10.0/24             169.254.101.2 dst-ip (learned)
+           192.168.0.0/24             169.254.101.2 dst-ip (learned) 
override-connected
 ])
 OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl --route-table=rtb2 lr-route-list 
lr11], [0], [dnl
 IPv4 Routes
 Route Table rtb2:
             10.10.10.0/24             169.254.102.2 dst-ip (learned)
+           192.168.0.0/24             169.254.102.2 dst-ip (learned) 
override-connected
 ])
 OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl --route-table=rtb3 lr-route-list 
lr11], [0], [dnl
 IPv4 Routes
 Route Table rtb3:
             10.10.10.0/24             169.254.103.2 dst-ip (learned)
+           192.168.0.0/24             169.254.103.2 dst-ip (learned) 
override-connected
 ])
 
 # Test routes from lr12 didn't leak as learned to lr21
 OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 192.168 | 
sort], [0], [dnl
            192.168.0.0/24             169.254.101.2 dst-ip (learned) ecmp
+           192.168.0.0/24             169.254.101.2 dst-ip (learned) 
override-connected
            192.168.0.0/24             169.254.102.2 dst-ip (learned) ecmp
+           192.168.0.0/24             169.254.102.2 dst-ip (learned) 
override-connected
 ])
 
 OVN_CLEANUP_IC([az1], [az2])
@@ -1457,8 +1467,11 @@ check ovn-ic-nbctl --wait=sb sync
 AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 2001:db8:200 |
              grep learned | awk '{print $1, $2, $5}' | sort], [0], [dnl
 2001:db8:200::/64 2001:db8:1::2 ecmp
+2001:db8:200::/64 2001:db8:1::2 override-connected
 2001:db8:200::/64 2001:db8:2::2 ecmp
+2001:db8:200::/64 2001:db8:2::2 override-connected
 2001:db8:200::/64 2001:db8:3::2 ecmp
+2001:db8:200::/64 2001:db8:3::2 override-connected
 ])
 
 # Test static routes from lr12 rtbs rtb1,rtb2,rtb3 were learned to lr11
@@ -1466,18 +1479,21 @@ OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl --route-table=rtb1 
lr-route-list lr11 | gre
 AT_CHECK([ovn_as az1 ovn-nbctl --route-table=rtb1 lr-route-list lr11], [0], 
[dnl
 IPv6 Routes
 Route Table rtb1:
+        2001:db8:200::/64             2001:db8:1::2 dst-ip (learned) 
override-connected
        2001:db8:aaaa::/64             2001:db8:1::2 dst-ip (learned)
 ])
 OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl --route-table=rtb2 lr-route-list lr11 | 
grep learned])
 AT_CHECK([ovn_as az1 ovn-nbctl --route-table=rtb2 lr-route-list lr11], [0], 
[dnl
 IPv6 Routes
 Route Table rtb2:
+        2001:db8:200::/64             2001:db8:2::2 dst-ip (learned) 
override-connected
        2001:db8:aaaa::/64             2001:db8:2::2 dst-ip (learned)
 ])
 OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl --route-table=rtb3 lr-route-list lr11 | 
grep learned])
 AT_CHECK([ovn_as az1 ovn-nbctl --route-table=rtb3 lr-route-list lr11], [0], 
[dnl
 IPv6 Routes
 Route Table rtb3:
+        2001:db8:200::/64             2001:db8:3::2 dst-ip (learned) 
override-connected
        2001:db8:aaaa::/64             2001:db8:3::2 dst-ip (learned)
 ])
 
@@ -1485,7 +1501,9 @@ Route Table rtb3:
 OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep "2001:db8:2::2" 
| grep learned])
 AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 2001 | sort], [0], 
[dnl
         2001:db8:200::/64             2001:db8:1::2 dst-ip (learned) ecmp
+        2001:db8:200::/64             2001:db8:1::2 dst-ip (learned) 
override-connected
         2001:db8:200::/64             2001:db8:2::2 dst-ip (learned) ecmp
+        2001:db8:200::/64             2001:db8:2::2 dst-ip (learned) 
override-connected
 ])
 
 OVN_CLEANUP_IC([az1], [az2])
@@ -4839,3 +4857,165 @@ OVN_CLEANUP_IC
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-ic -- east-west - 2az])
+
+ovn_init_ic_db
+ovn-ic-nbctl ts-add rtb-1
+ovn-ic-nbctl ts-add rtb-2
+
+ovn_start az1
+ovn_as az1
+
+check ovn_as az1 ovn-ic-nbctl --wait=sb sync
+check ovn_as az1 ovn-nbctl set nb_global . options:ic-route-learn=true
+check ovn_as az1 ovn-nbctl set nb_global . options:ic-route-adv=true
+
+check ovn_as az1 ovn-nbctl ls-add subnet-A
+check ovn_as az1 ovn-nbctl lsp-add subnet-A subnet-A-up -- lsp-set-type 
subnet-A-up router -- lsp-set-addresses subnet-A-up router -- lsp-set-options 
subnet-A-up router-port=subnet-A
+check ovn_as az1 ovn-nbctl lsp-add subnet-A client -- lsp-set-addresses client 
"0a:00:43:1e:92:20 172.31.0.4"
+
+check ovn_as az1 ovn-nbctl ls-add subnet-B
+check ovn_as az1 ovn-nbctl lsp-add subnet-B subnet-B-up -- lsp-set-type 
subnet-B-up router -- lsp-set-addresses subnet-B-up router -- lsp-set-options 
subnet-B-up router-port=subnet-B
+check ovn_as az1 ovn-nbctl lsp-add subnet-B server -- lsp-set-addresses server 
"0a:00:b9:86:a4:00 172.31.1.4"
+
+check ovn_as az1 ovn-nbctl lsp-add rtb-1 rtb-1-down1 -- lsp-set-type 
rtb-1-down1 router -- lsp-set-addresses rtb-1-down1 router -- lsp-set-options 
rtb-1-down1 router-port=rtb-1
+check ovn_as az1 ovn-nbctl lsp-add rtb-2 rtb-2-down1 -- lsp-set-type 
rtb-2-down1 router -- lsp-set-addresses rtb-2-down1 router -- lsp-set-options 
rtb-2-down1 router-port=rtb-2
+
+check ovn_as az1 ovn-nbctl lr-add rt1
+check ovn_as az1 ovn-nbctl lrp-add rt1 subnet-A "d0:fe:00:00:00:14" 
"172.31.0.1/24" -- lrp-set-options subnet-A route_table=table1
+check ovn_as az1 ovn-nbctl lrp-add rt1 subnet-B "d0:fe:00:00:00:15" 
"172.31.1.1/24" -- lrp-set-options subnet-B route_table=table1
+check ovn_as az1 ovn-nbctl lrp-add rt1 rtb-1 "00:00:a0:9e:9d:40" 
"169.254.100.1/27" -- lrp-set-options rtb-1 route_table=table1
+check ovn_as az1 ovn-nbctl lrp-add rt1 rtb-2 "00:00:60:15:b8:20" 
"169.254.100.33/27" -- lrp-set-options rtb-2 route_table=table2
+
+ovn_start az2
+ovn_as az2
+
+check ovn_as az2 ovn-ic-nbctl --wait=sb sync
+check ovn_as az2 ovn-nbctl set nb_global . options:ic-route-learn=true
+check ovn_as az2 ovn-nbctl set nb_global . options:ic-route-adv=true
+
+check ovn_as az2 ovn-nbctl ls-add subnet-C
+check ovn_as az2 ovn-nbctl lsp-add subnet-C subnet-C-up -- lsp-set-type 
subnet-C-up router -- lsp-set-addresses subnet-C-up router -- lsp-set-options 
subnet-C-up router-port=subnet-C
+check ovn_as az2 ovn-nbctl lsp-add subnet-C filter1 -- lsp-set-addresses 
filter1 "0a:01:4f:43:ce:e1 172.31.2.4"
+
+check ovn_as az2 ovn-nbctl ls-add subnet-D
+check ovn_as az2 ovn-nbctl lsp-add subnet-D subnet-D-up -- lsp-set-type 
subnet-D-up router -- lsp-set-addresses subnet-D-up router -- lsp-set-options 
subnet-D-up router-port=subnet-D
+check ovn_as az2 ovn-nbctl lsp-add subnet-D filter2 -- lsp-set-addresses 
filter2 "0a:01:39:eb:b1:41 172.31.3.4"
+
+check ovn_as az2 ovn-nbctl lsp-add rtb-1 rtb-1-down2 -- lsp-set-type 
rtb-1-down2 router -- lsp-set-addresses rtb-1-down2 router -- lsp-set-options 
rtb-1-down2 router-port=rtb-1
+check ovn_as az2 ovn-nbctl lsp-add rtb-2 rtb-2-down2 -- lsp-set-type 
rtb-2-down2 router -- lsp-set-addresses rtb-2-down2 router -- lsp-set-options 
rtb-2-down2 router-port=rtb-2
+
+check ovn_as az2 ovn-nbctl lr-add rt1
+check ovn_as az2 ovn-nbctl lrp-add rt1 subnet-C "d0:fe:00:00:00:16" 
"172.31.2.1/24" -- lrp-set-options subnet-C route_table=table2
+check ovn_as az2 ovn-nbctl lrp-add rt1 subnet-D "d0:fe:00:00:00:17" 
"172.31.3.1/24" -- lrp-set-options subnet-D route_table=table2
+check ovn_as az2 ovn-nbctl lrp-add rt1 rtb-1 "00:01:a0:9e:9d:40" 
"169.254.100.2/27" -- lrp-set-options rtb-1 route_table=table1
+check ovn_as az2 ovn-nbctl lrp-add rt1 rtb-2 "00:01:60:15:b8:20" 
"169.254.100.34/27" -- lrp-set-options rtb-2 route_table=table2
+
+check ovn_as az2 ovn-nbctl --route-table=table1 --override-connected 
lr-route-add rt1 "172.31.0.0/24" "172.31.2.4"
+check ovn_as az2 ovn-nbctl --route-table=table1 --override-connected 
lr-route-add rt1 "172.31.1.0/24" "172.31.3.4"
+
+check ovn-ic-nbctl --wait=sb sync
+
+AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list rt1], [0], [dnl
+IPv4 Routes
+Route Table <main>:
+            172.31.2.0/24             169.254.100.2 dst-ip (learned) ecmp
+            172.31.2.0/24            169.254.100.34 dst-ip (learned) ecmp
+            172.31.3.0/24             169.254.100.2 dst-ip (learned) ecmp
+            172.31.3.0/24            169.254.100.34 dst-ip (learned) ecmp
+
+Route Table table1:
+            172.31.0.0/24             169.254.100.2 dst-ip (learned) 
override-connected
+            172.31.1.0/24             169.254.100.2 dst-ip (learned) 
override-connected
+            172.31.2.0/24             169.254.100.2 dst-ip (learned) 
override-connected
+            172.31.3.0/24             169.254.100.2 dst-ip (learned) 
override-connected
+
+Route Table table2:
+            172.31.2.0/24            169.254.100.34 dst-ip (learned) 
override-connected
+            172.31.3.0/24            169.254.100.34 dst-ip (learned) 
override-connected
+])
+
+AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list rt1], [0], [dnl
+IPv4 Routes
+Route Table <main>:
+            172.31.0.0/24             169.254.100.1 dst-ip (learned) ecmp
+            172.31.0.0/24            169.254.100.33 dst-ip (learned) ecmp
+            172.31.1.0/24             169.254.100.1 dst-ip (learned) ecmp
+            172.31.1.0/24            169.254.100.33 dst-ip (learned) ecmp
+
+Route Table table1:
+            172.31.0.0/24                172.31.2.4 dst-ip override-connected
+            172.31.0.0/24             169.254.100.1 dst-ip (learned) 
override-connected
+            172.31.1.0/24                172.31.3.4 dst-ip override-connected
+            172.31.1.0/24             169.254.100.1 dst-ip (learned) 
override-connected
+
+Route Table table2:
+            172.31.0.0/24            169.254.100.33 dst-ip (learned) 
override-connected
+            172.31.1.0/24            169.254.100.33 dst-ip (learned) 
override-connected
+])
+
+AZF1="az1/az1_flow.txt"
+AZF2="az2/az2_flow.txt"
+ovn_as az1 ovn-sbctl lflow-list rt1 > $AZF1
+ovn_as az2 ovn-sbctl lflow-list rt1 > $AZF2
+
+VA1=$(grep "ip_routing_pre.*rtb-1" $AZF1 | sed -n 's/.*reg7 = 
\([[0-9]]*\).*/\1/p')
+VA2=$(grep "ip_routing_pre.*rtb-2" $AZF1 | sed -n 's/.*reg7 = 
\([[0-9]]*\).*/\1/p')
+
+#grep "ip_routing[[^_]]" $AZF1 | sed "s/reg7 == $VA1/reg7 == rtb-1/g" | sed 
"s/reg7 == $VA2/reg7 == rtb-2/g" |  ovn_strip_lflows > az1/az1_parsed.txt
+
+AT_CHECK([grep "ip_routing[[^_]]" $AZF1 | sed "s/reg7 == $VA1/reg7 == rtb-1/g" 
| sed "s/reg7 == $VA2/reg7 == rtb-2/g" |  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=1842 , match=(ip4.dst == 
172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
172.31.0.1; eth.src = d0:fe:00:00:00:14; outport = "subnet-A"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
172.31.1.1; eth.src = d0:fe:00:00:00:15; outport = "subnet-B"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.2; reg5 
= 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = "rtb-1"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.34; 
reg5 = 169.254.100.33; eth.src = 00:00:60:15:b8:20; outport = "rtb-2"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.3.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.2; reg5 
= 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = "rtb-1"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.3.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.34; 
reg5 = 169.254.100.33; eth.src = 00:00:60:15:b8:20; outport = "rtb-2"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.2; reg5 = 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.3.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.2; reg5 = 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-2 && 
ip4.dst == 172.31.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.34; reg5 = 169.254.100.33; eth.src = 00:00:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-2 && 
ip4.dst == 172.31.3.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.34; reg5 = 169.254.100.33; eth.src = 00:00:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1846 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.2; reg5 = 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1846 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.2; reg5 = 169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1878 , match=(ip4.dst == 
169.254.100.0/27), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
169.254.100.1; eth.src = 00:00:a0:9e:9d:40; outport = "rtb-1"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1878 , match=(ip4.dst == 
169.254.100.32/27), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
169.254.100.33; eth.src = 00:00:60:15:b8:20; outport = "rtb-2"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "rtb-1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:a0ff:fe9e:9d40; eth.src = 00:00:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "rtb-2" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:60ff:fe15:b820; eth.src = 00:00:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "subnet-A" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::d2fe:ff:fe00:14; eth.src = d0:fe:00:00:00:14; outport = 
"subnet-A"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "subnet-B" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::d2fe:ff:fe00:15; eth.src = d0:fe:00:00:00:15; outport = 
"subnet-B"; flags.loopback = 1; reg9[[9]] = 0; next;)
+])
+
+VA1=$(grep "ip_routing_pre.*rtb-1" $AZF2 | sed -n 's/.*reg7 = 
\([[0-9]]*\).*/\1/p')
+VA2=$(grep "ip_routing_pre.*rtb-2" $AZF2 | sed -n 's/.*reg7 = 
\([[0-9]]*\).*/\1/p')
+
+AT_CHECK([grep "ip_routing[[^_]]" $AZF2 | sed "s/reg7 == $VA1/reg7 == rtb-1/g" 
| sed "s/reg7 == $VA2/reg7 == rtb-2/g" |  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=1842 , match=(ip4.dst == 
172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.1; reg5 
= 169.254.100.2; eth.src = 00:01:a0:9e:9d:40; outport = "rtb-1"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.33; 
reg5 = 169.254.100.34; eth.src = 00:01:60:15:b8:20; outport = "rtb-2"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.1; reg5 
= 169.254.100.2; eth.src = 00:01:a0:9e:9d:40; outport = "rtb-1"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 169.254.100.33; 
reg5 = 169.254.100.34; eth.src = 00:01:60:15:b8:20; outport = "rtb-2"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
172.31.2.1; eth.src = d0:fe:00:00:00:16; outport = "subnet-C"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
172.31.3.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
172.31.3.1; eth.src = d0:fe:00:00:00:17; outport = "subnet-D"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.1; reg5 = 169.254.100.2; eth.src = 00:01:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.1; reg5 = 169.254.100.2; eth.src = 00:01:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-2 && 
ip4.dst == 172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.33; reg5 = 169.254.100.34; eth.src = 00:01:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1844 , match=(reg7 == rtb-2 && 
ip4.dst == 172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
169.254.100.33; reg5 = 169.254.100.34; eth.src = 00:01:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1846 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
172.31.2.4; reg5 = 172.31.2.1; eth.src = d0:fe:00:00:00:16; outport = 
"subnet-C"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1846 , match=(reg7 == rtb-1 && 
ip4.dst == 172.31.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 
172.31.3.4; reg5 = 172.31.3.1; eth.src = d0:fe:00:00:00:17; outport = 
"subnet-D"; flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1878 , match=(ip4.dst == 
169.254.100.0/27), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
169.254.100.2; eth.src = 00:01:a0:9e:9d:40; outport = "rtb-1"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1878 , match=(ip4.dst == 
169.254.100.32/27), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
169.254.100.34; eth.src = 00:01:60:15:b8:20; outport = "rtb-2"; flags.loopback 
= 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "rtb-1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::201:a0ff:fe9e:9d40; eth.src = 00:01:a0:9e:9d:40; outport = 
"rtb-1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "rtb-2" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::201:60ff:fe15:b820; eth.src = 00:01:60:15:b8:20; outport = 
"rtb-2"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "subnet-C" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::d2fe:ff:fe00:16; eth.src = d0:fe:00:00:00:16; outport = 
"subnet-C"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "subnet-D" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::d2fe:ff:fe00:17; eth.src = d0:fe:00:00:00:17; outport = 
"subnet-D"; flags.loopback = 1; reg9[[9]] = 0; next;)
+])
+
+OVN_CLEANUP_IC([az1], [az2])
+
+AT_CLEANUP
+])
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 1d7bd6c28..da023c260 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -7278,9 +7278,9 @@ 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=10300, 
match=(ct_mark.ecmp_reply_port == 1 && reg7 == 0 && ip4.dst == 1.0.0.1/32), 
action=(ip.ttl--; flags.loopback = 1; eth.src = 00:00:20:20:12:13; reg5 = 
192.168.0.1; outport = "lr0-public"; next;)
   table=??(lr_in_ip_routing   ), priority=10550, match=(nd_rs || nd_ra), 
action=(drop;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=260  , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1936 , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | ovn_strip_lflows], [0], 
[dnl
@@ -7304,9 +7304,9 @@ 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=10300, 
match=(ct_mark.ecmp_reply_port == 1 && reg7 == 0 && ip4.dst == 1.0.0.1/32), 
action=(ip.ttl--; flags.loopback = 1; eth.src = 00:00:20:20:12:13; reg5 = 
192.168.0.1; outport = "lr0-public"; next;)
   table=??(lr_in_ip_routing   ), priority=10550, match=(nd_rs || nd_ra), 
action=(drop;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=260  , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1936 , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 
's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_ip_routing_ecmp), priority=0    , match=(1), action=(drop;)
@@ -7346,9 +7346,9 @@ 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=10300, 
match=(ct_mark.ecmp_reply_port == 1 && reg7 == 0 && ip4.dst == 1.0.0.1/32), 
action=(ip.ttl--; flags.loopback = 1; eth.src = 00:00:20:20:12:13; reg5 = 
192.168.0.1; outport = "lr0-public"; next;)
   table=??(lr_in_ip_routing   ), priority=10550, match=(nd_rs || nd_ra), 
action=(drop;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=260  , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1936 , match=(reg7 == 0 && ip4.dst 
== 1.0.0.1/32), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 
's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl
   table=??(lr_in_ip_routing_ecmp), priority=0    , match=(1), action=(drop;)
@@ -7370,14 +7370,14 @@ check ovn-nbctl --wait=sb lr-route-add lr0 1.0.0.0/24 
192.168.0.10
 ovn-sbctl dump-flows lr0 > lr0flows
 
 AT_CHECK([grep -e "lr_in_ip_routing.*192.168.0.10" lr0flows | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 1.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 
= 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 1.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 
= 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
 ])
 
 check ovn-nbctl --wait=sb lr-route-add lr0 2.0.0.0/24 lr0-public
 
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep -e "lr_in_ip_routing.*2.0.0.0" lr0flows | ovn_strip_lflows], 
[0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 2.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 2.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
 ])
 
 check ovn-nbctl lr-route-add lr0 3.3.0.0/16 192.168.0.11
@@ -7392,7 +7392,7 @@ check ovn-nbctl set logical_router_static_route 
$route2_uuid selection_fields="i
 check ovn-nbctl --wait=sb sync
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep -e "(lr_in_ip_routing   ).*3.3.0.0" lr0flows | sed 
's/table=../table=??/' | sort], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=132  , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); hash_fields="ip_dst,ip_proto,ip_src");)
+  table=??(lr_in_ip_routing   ), priority=1744 , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); hash_fields="ip_dst,ip_proto,ip_src");)
 ])
 
 check ovn-nbctl set logical_router_static_route $route1_uuid 
selection_fields="ip_src,ip_dst,tp_src,tp_dst"
@@ -7401,10 +7401,10 @@ check ovn-nbctl set logical_router_static_route 
$route2_uuid selection_fields="i
 check ovn-nbctl --wait=sb sync
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep -e "(lr_in_ip_routing   ).*3.3.0.0" lr0flows | sed 
's/table=../table=??/' | sort], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=132  , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); hash_fields="ip_dst,ip_proto,ip_src");)
-  table=??(lr_in_ip_routing   ), priority=133  , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && sctp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 
1; reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,sctp_dst,sctp_src");)
-  table=??(lr_in_ip_routing   ), priority=133  , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && tcp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,tcp_dst,tcp_src");)
-  table=??(lr_in_ip_routing   ), priority=133  , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && udp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,udp_dst,udp_src");)
+  table=??(lr_in_ip_routing   ), priority=1744 , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); hash_fields="ip_dst,ip_proto,ip_src");)
+  table=??(lr_in_ip_routing   ), priority=1745 , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && sctp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 
1; reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,sctp_dst,sctp_src");)
+  table=??(lr_in_ip_routing   ), priority=1745 , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && tcp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,tcp_dst,tcp_src");)
+  table=??(lr_in_ip_routing   ), priority=1745 , match=(reg7 == 0 && ip4.dst 
== 3.3.0.0/16 && udp), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(values=(1, 2); 
hash_fields="ip_dst,ip_proto,ip_src,udp_dst,udp_src");)
 ])
 
 AT_CHECK([grep -e "lr_in_ecmp_stateful_egr" lr0flows | ovn_strip_lflows], [0], 
[dnl
@@ -7446,15 +7446,15 @@ ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep -e "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=196  , match=(reg7 == 0 && ip4.dst 
== 10.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 
= 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 11.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 2001:db8::10; 
xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; 
reg5 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::20; xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = 
"lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; 
reg5 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == 
"lr0-private" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; 
xxreg0 = ip6.dst; xxreg1 = fe80::200:20ff:fe20:1214; eth.src = 
00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; 
next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 10.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 
= 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 11.0.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 2001:db8::10; 
xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; 
reg5 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::20; xxreg1 = 2001:db8::1; eth.src = 00:00:20:20:12:14; outport = 
"lr0-private"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; 
reg5 = 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == 
"lr0-private" && ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; 
xxreg0 = ip6.dst; xxreg1 = fe80::200:20ff:fe20:1214; eth.src = 
00:00:20:20:12:14; outport = "lr0-private"; flags.loopback = 1; reg9[[9]] = 0; 
next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-public" 
&& ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
ip6.dst; xxreg1 = fe80::200:20ff:fe20:1213; eth.src = 00:00:20:20:12:13; 
outport = "lr0-public"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:20:20:12:14; outport = "lr0-private"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 AT_CHECK([grep -e "lr_in_arp_resolve" lr0flows | ovn_strip_lflows], [0], [dnl
@@ -7970,16 +7970,16 @@ AT_CHECK([grep "lr_in_ip_routing_pre" lr0flows | 
ovn_strip_lflows], [0], [dnl
 grep -e "(lr_in_ip_routing   ).*outport" lr0flows
 
 AT_CHECK([grep -e "(lr_in_ip_routing   ).*outport" lr0flows | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 1 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; 
reg5 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=198  , match=(ip4.dst == 
192.168.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.2.1; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=260  , match=(reg7 == 2 && ip4.dst 
== 1.1.1.1/32), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; reg5 
= 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 
1; reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=4    , match=(reg7 == 0 && ip4.dst 
== 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=4    , match=(reg7 == 2 && ip4.dst 
== 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lrp0" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lrp1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:101; eth.src = 00:00:00:00:01:01; outport = "lrp1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lrp2" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:201; eth.src = 00:00:00:00:02:01; outport = "lrp2"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1552 , match=(reg7 == 0 && ip4.dst 
== 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1552 , match=(reg7 == 2 && ip4.dst 
== 0.0.0.0/0), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.10; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 1 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.1.10; 
reg5 = 192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; 
flags.loopback = 1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.1.1; eth.src = 00:00:00:00:01:01; outport = "lrp1"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1842 , match=(ip4.dst == 
192.168.2.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = ip4.dst; reg5 = 
192.168.2.1; eth.src = 00:00:00:00:02:01; outport = "lrp2"; flags.loopback = 1; 
reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=1936 , match=(reg7 == 2 && ip4.dst 
== 1.1.1.1/32), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 192.168.0.20; reg5 
= 192.168.0.1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; flags.loopback = 
1; reg9[[9]] = 1; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lrp0" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:1; eth.src = 00:00:00:00:00:01; outport = "lrp0"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lrp1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:101; eth.src = 00:00:00:00:01:01; outport = "lrp1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lrp2" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:201; eth.src = 00:00:00:00:02:01; outport = "lrp2"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 OVN_CLEANUP_NORTHD
@@ -15879,12 +15879,12 @@ 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
 ])
 
 # Learn a route to 172.16.0.0/24 via 10.0.0.11 learned on lr0-sw0.
@@ -15900,13 +15900,13 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
 ])
 
 # Learn a route to 2001:db8:2::/64 via 2001:db8:ffff::20 learned on lr0-sw1.
@@ -15923,14 +15923,14 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
 ])
 
 # If we now add 2001:db8:ffff::1/64 as an additional network to lr0-sw1 we
@@ -15944,15 +15944,15 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 # Learn a route to 2001:db8:3::/64 via 10.0.0.20 learned on lr0-sw0.
@@ -15968,16 +15968,16 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 # Learn a route to 172.16.1.0/24 via 2001:db8:ffff::30 learned on lr0-sw1.
@@ -15993,17 +15993,17 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=194  , match=(reg7 == 0 && ip4.dst 
== 172.16.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::30; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=516  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::30; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:2::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8:ffff::20; xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; 
outport = "lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=2320 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:1::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = 
2001:db8::10; xxreg1 = 2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; xxreg1 = 
2001:db8::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; flags.loopback = 
1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(ip6.dst == 
2001:db8:ffff::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = 2001:db8:ffff::1; eth.src = 00:00:00:00:ff:02; outport = "lr0-sw1"; 
flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 # Deleting lr0-sw1 will remove the flows and also the learned route.
@@ -16015,11 +16015,11 @@ 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 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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.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=514  , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=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;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 172.16.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.11; 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=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.10; 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=1842 , 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=2318 , match=(reg7 == 0 && ip6.dst 
== 2001:db8:3::/64), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 
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=2322 , 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;)
 ])
 
 OVN_CLEANUP_NORTHD
@@ -16049,11 +16049,11 @@ 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=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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1840 , 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=1842 , 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=1842 , 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=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 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;)
@@ -16075,12 +16075,12 @@ 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--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 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=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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 192.168.1.0/24), action=(ip.ttl--; reg8[[0..15]] = 0; reg0 = 10.0.0.20; 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=1840 , 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=1842 , 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=1842 , 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=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 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;)
@@ -16103,12 +16103,12 @@ 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]] = 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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , 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=1840 , 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=1842 , 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=1842 , 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=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 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;)
@@ -16145,13 +16145,13 @@ ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep -w "lr_in_ip_routing" lr0flows | sed -e 's/reg8\[[0..15\]] = 
[[123]]/reg8\[[0..15\]] = ??/' | 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.0.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = ??; 
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]] = ??; 
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]] = ??; 
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;)
-  table=??(lr_in_ip_routing   ), priority=518  , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = ??; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1838 , match=(reg7 == 0 && ip4.dst 
== 192.168.1.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = ??; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.0.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = ??; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1842 , 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=1842 , 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=2322 , 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;)
+  table=??(lr_in_ip_routing   ), priority=2322 , match=(inport == "lr0-sw1" && 
ip6.dst == fe80::/64), action=(ip.ttl--; reg8[[0..15]] = 0; xxreg0 = ip6.dst; 
xxreg1 = fe80::200:ff:fe00:ff02; eth.src = 00:00:00:00:ff:02; outport = 
"lr0-sw1"; flags.loopback = 1; reg9[[9]] = 0; next;)
 ])
 
 OVN_CLEANUP_NORTHD
@@ -20473,7 +20473,7 @@ check ovn-nbctl --wait=sb sync
 
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep 'lr_in_ip_routing' lr0flows | grep 'select' | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
 ])
 
 AT_CHECK([grep 'lr_in_ip_routing_ecmp' lr0flows | sed -E 's/== [[1-9]]+\)/== 
\?)/' | ovn_strip_lflows], [0], [dnl
@@ -20491,7 +20491,7 @@ check ovn-nbctl --wait=sb set 
Logical_Router_Static_Route $ecmp1 nexthop="discar
 
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep 'lr_in_ip_routing' lr0flows | grep 'select' | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
 ])
 
 AT_CHECK([grep 'lr_in_ip_routing_ecmp' lr0flows | sed -E 's/== [[1-9]]+\)/== 
\?)/' | ovn_strip_lflows], [0], [dnl
@@ -20506,7 +20506,7 @@ check ovn-nbctl --wait=sb set 
Logical_Router_Static_Route $ecmp2 nexthop="discar
 
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep 'lr_in_ip_routing' lr0flows | grep 'select' | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
 ])
 
 AT_CHECK([grep 'lr_in_ip_routing_ecmp' lr0flows | sed -E 's/== [[1-9]]+\)/== 
\?)/' | ovn_strip_lflows], [0], [dnl
@@ -20522,7 +20522,7 @@ check ovn-nbctl --wait=sb set 
Logical_Router_Static_Route $ecmp2 nexthop="10.0.2
 
 ovn-sbctl dump-flows lr0 > lr0flows
 AT_CHECK([grep 'lr_in_ip_routing' lr0flows | grep 'select' | 
ovn_strip_lflows], [0], [dnl
-  table=??(lr_in_ip_routing   ), priority=196  , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
+  table=??(lr_in_ip_routing   ), priority=1840 , match=(reg7 == 0 && ip4.dst 
== 192.168.10.0/24), action=(ip.ttl--; flags.loopback = 1; reg8[[0..15]] = 1; 
reg8[[16..31]] = select(1, 2);)
 ])
 
 AT_CHECK([grep 'lr_in_ip_routing_ecmp' lr0flows | sed -E 's/== [[1-9]]+\)/== 
\?)/' | ovn_strip_lflows], [0], [dnl
diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
index 4fbd0bb0e..1c67bbd1f 100644
--- a/utilities/ovn-nbctl.8.xml
+++ b/utilities/ovn-nbctl.8.xml
@@ -1146,6 +1146,7 @@
       <dt>[<code>--may-exist</code>] [<code>--policy</code>=<var>POLICY</var>]
         [<code>--route-table</code>=<var>ROUTE_TABLE</var>]
         [<code>--ecmp</code>] [<code>--ecmp-symmetric-reply</code>]
+        [<code>--override-connected</code>]
         [<code>--bfd[=<var>UUID</var></code>]]
         <code>lr-route-add</code> <var>router</var>
         <var>prefix</var> <var>nexthop</var> [<var>port</var>]</dt>
@@ -1194,6 +1195,11 @@
           it is not necessary to set both.
         </p>
 
+        <p>
+          The <code>--override-connected</code> option makes it so that
+          route's priority to be highest among routes with same prefix.
+        </p>
+
         <p>
           <code>--bfd</code> option is used to link a BFD session to the
           OVN route. If the BFD session UUID is provided, it will be used
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 0ef207272..abc172b57 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -448,6 +448,7 @@ Route commands:\n\
   [--policy=POLICY]\n\
   [--ecmp]\n\
   [--ecmp-symmetric-reply]\n\
+  [--override-connected]\n\
   [--route-table=ROUTE_TABLE]\n\
   [--bfd]\n\
   lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
@@ -5236,6 +5237,8 @@ nbctl_lr_route_add(struct ctl_context *ctx)
                                            "--ecmp-symmetric-reply") != NULL;
     bool ecmp = shash_find(&ctx->options, "--ecmp") != NULL ||
                 ecmp_symmetric_reply;
+    bool override_connected = shash_find(&ctx->options,
+                                           "--override-connected") != NULL;
     struct nbrec_logical_router_static_route *route =
         nbctl_lr_get_route(lr, prefix, next_hop, is_src_route, ecmp,
                            route_table);
@@ -5323,11 +5326,20 @@ nbctl_lr_route_add(struct ctl_context *ctx)
         nbrec_logical_router_static_route_set_route_table(route, route_table);
     }
 
-    if (ecmp_symmetric_reply) {
-        const struct smap options = SMAP_CONST1(&options,
-                                                "ecmp_symmetric_reply",
-                                                "true");
+    if (ecmp_symmetric_reply || override_connected) {
+        struct smap options = SMAP_INITIALIZER(&options);
+
+        if (ecmp_symmetric_reply) {
+            smap_add(&options, "ecmp_symmetric_reply", "true");
+        }
+
+        if (override_connected) {
+            smap_add(&options, ROUTE_OVERRIDE_CONNECTED, "true");
+        }
+
         nbrec_logical_router_static_route_set_options(route, &options);
+
+        smap_destroy(&options);
     }
 
     nbrec_logical_router_update_static_routes_addvalue(lr, route);
@@ -7437,6 +7449,10 @@ print_route(const struct 
nbrec_logical_router_static_route *route,
         ds_put_cstr(s, " ecmp-symmetric-reply");
     }
 
+    if (smap_get_bool(&route->options, ROUTE_OVERRIDE_CONNECTED, false)) {
+        ds_put_cstr(s, " override-connected");
+    }
+
     if (route->bfd) {
         ds_put_cstr(s, " bfd");
     }
@@ -9420,8 +9436,8 @@ static const struct ctl_command_syntax nbctl_commands[] = 
{
     /* logical router route commands. */
     { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]",
       nbctl_pre_lr_route_add, nbctl_lr_route_add, NULL,
-      "--may-exist,--ecmp,--ecmp-symmetric-reply,--policy=,"
-      "--route-table=,--bfd?", RW },
+      "--may-exist,--ecmp,--ecmp-symmetric-reply,--override-connected,"
+      "--policy=,--route-table=,--bfd?", RW },
     { "lr-route-del", 1, 4, "ROUTER [PREFIX [NEXTHOP [PORT]]]",
       nbctl_pre_lr_route_del, nbctl_lr_route_del, NULL,
       "--if-exists,--policy=,--route-table=", RW },
-- 
2.48.1

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

Reply via email to