Enable east-west traffic rerouting for locally
connected networks. Enable east-west traffic between AZ.

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.
Also, route_table column in ic database now used for
connected routes too.

ic route priorities are changed to raise priority
of learned connected routes that have route table set.

Finally, route priorities for same prefix network will be:
 1. Static (both local and ic-learned), override-connected is set.
 2. Ic-learned connected with route table set.
 3. All other connected.
 3. All other static.

With using route tables, this approach will create possibility
to enforce local traffic reroute to remote az for processing and
deliver it back to original destination.

Signed-off-by: Aleksandr Smirnov <alekssmirnov@k2.cloud>
---
 ic/ovn-ic.c                    |  85 ++++++++++---
 northd/en-learned-route-sync.c |   2 +-
 northd/northd.c                | 146 ++++++++++++---------
 northd/northd.h                |   2 +
 ovn-ic-sb.ovsschema            |   5 +-
 ovn-ic-sb.xml                  |   4 +
 ovn-nb.xml                     |   8 ++
 tests/ovn-ic.at                | 181 +++++++++++++++++++++++++-
 tests/ovn-northd.at            | 226 ++++++++++++++++-----------------
 utilities/ovn-nbctl.c          |  28 +++-
 10 files changed, 486 insertions(+), 201 deletions(-)

diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index caffa6fe0..467810dd5 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -935,6 +935,7 @@ struct ic_route_info {
     const char *origin;
     const char *route_table;
     const char *route_tag;
+    bool override_connected;
 
     const struct nbrec_logical_router *nb_lr;
 
@@ -951,29 +952,40 @@ struct ic_route_info {
     const struct nbrec_load_balancer *nb_lb;
 };
 
+static bool
+get_override_connected(const struct smap *options)
+{
+    return smap_get_bool(options, "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 char *route_table,
+              bool override_connected)
 {
     uint32_t basis = hash_bytes(prefix, sizeof *prefix, (uint32_t)plen);
     basis = hash_string(origin, basis);
     basis = hash_string(route_table, basis);
+    basis = hash_boolean(override_connected, basis);
     return hash_bytes(nexthop, sizeof *nexthop, basis);
 }
 
 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, uint32_t hash)
+              const char *origin, const char *route_table,
+              bool override_connected, uint32_t hash)
 {
     struct ic_route_info *r;
     if (!hash) {
-        hash = ic_route_hash(prefix, plen, nexthop, origin, route_table);
+        hash = ic_route_hash(prefix, plen, nexthop, origin, route_table,
+                             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)) {
@@ -1027,8 +1039,10 @@ 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);
+
     if (ic_route_find(routes_learned, &prefix, plen, &nexthop, origin,
-                      nb_route->route_table, 0)) {
+                      nb_route->route_table, override_connected, 0)) {
         /* Route was added to learned on previous iteration. */
         return true;
     }
@@ -1041,9 +1055,11 @@ add_to_routes_learned(struct hmap *routes_learned,
     ic_route->origin = origin;
     ic_route->route_table = nb_route->route_table;
     ic_route->nb_lr = nb_lr;
+    ic_route->override_connected = override_connected;
+
     hmap_insert(routes_learned, &ic_route->node,
                 ic_route_hash(&prefix, plen, &nexthop, origin,
-                              nb_route->route_table));
+                              nb_route->route_table, override_connected));
     return true;
 }
 
@@ -1177,18 +1193,16 @@ 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);
 
-    if (route_table == NULL) {
-        route_table = "";
-    }
-
-    uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table);
+    uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table,
+                              override_connected);
 
     if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, route_table,
-                       hash)) {
+                       override_connected, hash)) {
         struct ic_route_info *ic_route = xzalloc(sizeof *ic_route);
         ic_route->prefix = prefix;
         ic_route->plen = plen;
@@ -1200,6 +1214,8 @@ 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);
@@ -1269,7 +1285,8 @@ 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,
+                     get_override_connected(&nb_route->options));
 }
 
 static void
@@ -1279,7 +1296,8 @@ add_network_to_routes_ad(struct hmap *routes_ad, const 
char *network,
                          const struct smap *nb_options,
                          const struct nbrec_logical_router *nb_lr,
                          const char *route_tag,
-                         const struct nbrec_logical_router_port *ts_lrp)
+                         const struct nbrec_logical_router_port *ts_lrp,
+                         const char *ts_route_table)
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
@@ -1317,9 +1335,23 @@ add_network_to_routes_ad(struct hmap *routes_ad, const 
char *network,
         ds_destroy(&msg);
     }
 
+    /* directly-connected networks that come thru gateway port with assigned
+     * route_table also duplicated as priority static routes for
+     * given route table.
+     * As result, traffic that processed thru such route table and routed to
+     * cross az gateway port will select transit port specially allocated
+     * to process traffic with 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);
+    }
+
     /* directly-connected routes go to <main> route table */
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_CONNECTED,
-                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag);
+                     "", nb_lrp, NULL, nb_lr, NULL, route_tag, false);
 }
 
 static void
@@ -1377,7 +1409,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, nb_lr, nb_lb, route_tag, false);
 out:
     free(vip_str);
 }
@@ -1741,7 +1773,9 @@ sync_learned_routes(struct ic_context *ctx,
             struct ic_route_info *route_learned
                 = ic_route_find(&ic_lr->routes_learned, &prefix, plen,
                                 &nexthop, isb_route->origin,
-                                isb_route->route_table, 0);
+                                isb_route->route_table,
+                                get_override_connected(&isb_route->options),
+                                0);
             if (route_learned) {
                 /* Sync external-ids */
                 struct uuid ext_id;
@@ -1773,6 +1807,12 @@ sync_learned_routes(struct ic_context *ctx,
                     nb_route, "ic-learned-route", uuid_s);
                 nbrec_logical_router_static_route_update_options_setkey(
                     nb_route, "origin", isb_route->origin);
+
+                if (get_override_connected(&isb_route->options)) {
+                    nbrec_logical_router_static_route_update_options_setkey(
+                        nb_route, "override-connected", "true");
+                }
+
                 free(uuid_s);
                 nbrec_logical_router_update_static_routes_addvalue(ic_lr->lr,
                     nb_route);
@@ -1861,7 +1901,9 @@ advertise_routes(struct ic_context *ctx,
         }
         struct ic_route_info *route_adv =
             ic_route_find(routes_ad, &prefix, plen, &nexthop,
-                          isb_route->origin, isb_route->route_table, 0);
+                          isb_route->origin, isb_route->route_table,
+                          get_override_connected(&isb_route->options),
+                          0);
         if (!route_adv) {
             /* Delete the extra route from IC-SB. */
             VLOG_DBG("Delete route %s -> %s from IC-SB, which is not found"
@@ -1905,6 +1947,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,
+                "override-connected", "true");
+        }
         free(prefix_s);
         free(nexthop_s);
 
@@ -1958,7 +2004,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);
+                                         lr, route_tag, ts_lrp,
+                                         ts_route_table);
             }
         } else {
             /* The router port of the TS port is ignored. */
diff --git a/northd/en-learned-route-sync.c b/northd/en-learned-route-sync.c
index f14f610ac..8abb6010e 100644
--- a/northd/en-learned-route-sync.c
+++ b/northd/en-learned-route-sync.c
@@ -205,7 +205,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 70045c0a0..04634d2da 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -336,15 +336,20 @@ 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)
+ *  1. (highest priority) Priority static routes,
+ *     (override-connected option is set), including ic-learned.
+ *  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)
  * (src-ip routes have lower priority than all other routes regardless of
  * prefix length, so not included here.) */
-#define ROUTE_PRIO_OFFSET_MULTIPLIER 6
+#define ROUTE_PRIO_OFFSET_MULTIPLIER 10
 #define ROUTE_PRIO_OFFSET_LEARNED 0
 #define ROUTE_PRIO_OFFSET_STATIC 2
 #define ROUTE_PRIO_OFFSET_CONNECTED 4
+#define ROUTE_PRIO_OFFSET_PRIORITY_CONNECTED 6
+#define ROUTE_PRIO_OFFSET_PRIORITY_STATIC 8
 
 /* Returns the type of the datapath to which a flow with the given 'stage' may
  * be added. */
@@ -11441,6 +11446,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;
         }
@@ -11471,6 +11480,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,
@@ -11486,6 +11496,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;
@@ -11514,7 +11525,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;
@@ -11575,6 +11587,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,
@@ -11584,7 +11597,7 @@ parsed_route_add(const struct ovn_datapath *od,
 
     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,
+        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);
@@ -11712,6 +11725,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,
+                                            "override-connected", false);
 
     enum route_source source;
     if (!strcmp(smap_get_def(&route->options, "origin", ""),
@@ -11723,7 +11738,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);
 }
@@ -11741,7 +11757,7 @@ parsed_routes_add_connected(const struct ovn_datapath 
*od,
         parsed_route_add(od, NULL, &prefix, addr->plen,
                          false, addr->addr_s, op,
                          0, false,
-                         false, NULL, ROUTE_SOURCE_CONNECTED,
+                         false, false, NULL, ROUTE_SOURCE_CONNECTED,
                          &op->nbrp->header_, NULL, routes);
     }
 
@@ -11753,7 +11769,7 @@ parsed_routes_add_connected(const struct ovn_datapath 
*od,
         parsed_route_add(od, NULL, &prefix, addr->plen,
                          false, addr->addr_s, op,
                          0, false,
-                         false, NULL, ROUTE_SOURCE_CONNECTED,
+                         false, false, NULL, ROUTE_SOURCE_CONNECTED,
                          &op->nbrp->header_, NULL, routes);
     }
 }
@@ -11808,62 +11824,47 @@ 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)
+calc_priority(int plen,
+              enum route_source source,
+              bool override_connected,
+              bool is_src_route,
+              bool has_protocol_match)
 {
+    uint16_t pri = (plen * ROUTE_PRIO_OFFSET_MULTIPLIER) + has_protocol_match;
+
+    if (is_src_route) {
+        return pri;
+    }
+
     switch (source) {
     case ROUTE_SOURCE_CONNECTED:
-        return ROUTE_PRIO_OFFSET_CONNECTED;
+        pri += (override_connected)
+               ? ROUTE_PRIO_OFFSET_PRIORITY_CONNECTED
+               : ROUTE_PRIO_OFFSET_CONNECTED;
+        break;
+
     case ROUTE_SOURCE_STATIC:
-        return ROUTE_PRIO_OFFSET_STATIC;
+        pri += (override_connected)
+               ? ROUTE_PRIO_OFFSET_PRIORITY_STATIC
+               : ROUTE_PRIO_OFFSET_STATIC;
+        break;
+
     case ROUTE_SOURCE_LEARNED:
-        return ROUTE_PRIO_OFFSET_LEARNED;
+        pri += ROUTE_PRIO_OFFSET_LEARNED;
+        break;
+
     case ROUTE_SOURCE_NAT:
     case ROUTE_SOURCE_LB:
     default:
         OVS_NOT_REACHED();
     }
-}
 
-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)
-{
-    const char *dir;
-    int ofs = route_source_to_offset(source);
-    int base = 0;
-
-    /* The priority here is calculated to implement longest-prefix-match
-     * routing. */
-    if (is_src_route) {
-        dir = "src";
-        ofs = 0;
-    } else {
-        dir = "dst";
-        /* dst routes have higher priority than all src routes regardless of
-         * prefix length. */
-        base = (128 + 1) * ROUTE_PRIO_OFFSET_MULTIPLIER;
-    }
-
-    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);
-    }
-
-    if (has_protocol_match) {
-        ofs += 1;
-    }
-    *priority = base + (plen * ROUTE_PRIO_OFFSET_MULTIPLIER) + ofs;
-
-    ds_put_format(match, "ip%s.%s == %s/%d", is_ipv4 ? "4" : "6", dir,
-                  network_s, plen);
+    return pri + (128 + 1) * ROUTE_PRIO_OFFSET_MULTIPLIER;
 }
 
+
 bool
 find_route_outport(const struct hmap *lr_ports, const char *output_port,
                    const char *ip_prefix, const char *nexthop, bool is_ipv4,
@@ -12058,10 +12059,20 @@ 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;
@@ -12172,7 +12183,8 @@ 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;
@@ -12186,8 +12198,22 @@ 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);
+
+    priority = calc_priority(plen, source, override_connected, is_src_route,
+                             false);
 
     struct ds common_actions = DS_EMPTY_INITIALIZER;
     struct ds actions = DS_EMPTY_INITIALIZER;
@@ -12255,7 +12281,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);
 }
@@ -17718,7 +17744,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 eacff73eb..59d785c7f 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -780,6 +780,7 @@ struct parsed_route {
     uint32_t route_table_id;
     uint32_t hash;
     bool ecmp_symmetric_reply;
+    bool override_connected;
     bool is_discard_route;
     const struct ovn_datapath *od;
     bool stale;
@@ -809,6 +810,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/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema
index 22f75b06c..a9f6cbadc 100644
--- a/ovn-ic-sb.ovsschema
+++ b/ovn-ic-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_IC_Southbound",
     "version": "2.1.0",
-    "cksum": "1466425967 7126",
+    "cksum": "1280659896 7281",
     "tables": {
         "IC_SB_Global": {
             "columns": {
@@ -101,6 +101,9 @@
                     "type": "string",
                     "enum": ["set",
                              ["connected", "static", "loadbalancer"]]}}},
+                "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 8f98c7ebb..bd540517f 100644
--- a/ovn-ic-sb.xml
+++ b/ovn-ic-sb.xml
@@ -355,6 +355,10 @@
         Nexthop IP address for this route.
       </column>
 
+      <column name="options">
+        Options of the route. Currently, only override-connected is supported.
+      </column>
+
       <column name="origin">
         Can be one of <code>connected</code>, <code>static</code> or
         <code>loadbalancer</code>.  Routes to directly-connected subnets -
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 4a7581807..6d835cdf5 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -4510,6 +4510,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.
+        The key's value is only "true".
+
+        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 37d7bc1b6..11cd9c164 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -912,9 +912,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 4242 -A 2], [0], [dnl
+AT_CHECK([ovn-ic-sbctl list route | grep 4242 -A 3], [0], [dnl
 ip_prefix           : "4242::1/128"
 nexthop             : "2001:db8:1::1"
+options             : {}
 origin              : loadbalancer
 ])
 
@@ -1247,6 +1248,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)
 ])
@@ -1279,6 +1281,167 @@ OVN_CLEANUP_IC([az1], [az2])
 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
+
+ovn_as az1 check ovn-ic-nbctl --wait=sb sync
+ovn_as az1 check ovn-nbctl set nb_global . options:ic-route-learn=true
+ovn_as az1 check ovn-nbctl set nb_global . options:ic-route-adv=true
+
+ovn_as az1 check ovn-nbctl ls-add subnet-A
+ovn_as az1 check 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
+ovn_as az1 check ovn-nbctl lsp-add subnet-A client -- lsp-set-addresses client 
"0a:00:43:1e:92:20 172.31.0.4"
+
+ovn_as az1 check ovn-nbctl ls-add subnet-B
+ovn_as az1 check 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
+ovn_as az1 check ovn-nbctl lsp-add subnet-B server -- lsp-set-addresses server 
"0a:00:b9:86:a4:00 172.31.1.4"
+
+ovn_as az1 check 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
+ovn_as az1 check 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
+
+ovn_as az1 check ovn-nbctl lr-add rt1
+ovn_as az1 check 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
+ovn_as az1 check 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
+ovn_as az1 check 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
+ovn_as az1 check 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
+
+ovn_as az2 check ovn-ic-nbctl --wait=sb sync
+ovn_as az2 check ovn-nbctl set nb_global . options:ic-route-learn=true
+ovn_as az2 check ovn-nbctl set nb_global . options:ic-route-adv=true
+
+ovn_as az2 check ovn-nbctl ls-add subnet-C
+ovn_as az2 check 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
+ovn_as az2 check ovn-nbctl lsp-add subnet-C filter1 -- lsp-set-addresses 
filter1 "0a:01:4f:43:ce:e1 172.31.2.4"
+
+ovn_as az2 check ovn-nbctl ls-add subnet-D
+ovn_as az2 check 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
+ovn_as az2 check ovn-nbctl lsp-add subnet-D filter2 -- lsp-set-addresses 
filter2 "0a:01:39:eb:b1:41 172.31.3.4"
+
+ovn_as az2 check 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
+ovn_as az2 check 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
+
+ovn_as az2 check ovn-nbctl lr-add rt1
+ovn_as az2 check 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
+ovn_as az2 check 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
+ovn_as az2 check 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
+ovn_as az2 check 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
+
+ovn_as az2 check ovn-nbctl --route-table=table1 --override-connected 
lr-route-add rt1 "172.31.0.0/24" "172.31.2.4"
+ovn_as az2 check 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1536 , 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=1536 , 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=1536 , 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=1536 , 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=1538 , 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=1538 , 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=1564 , 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=1564 , 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=1934 , 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=1934 , 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=1934 , 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=1934 , 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1534 , 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=1536 , 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=1536 , 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=1536 , 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=1536 , 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=1538 , 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=1538 , 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=1564 , 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=1564 , 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=1934 , 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=1934 , 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=1934 , 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=1934 , 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
+])
 
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([ovn-ic -- route sync -- multiple route tables])
@@ -1374,8 +1537,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
@@ -1383,22 +1549,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])
@@ -1505,8 +1676,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
@@ -1514,18 +1688,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)
 ])
 
@@ -1533,7 +1710,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])
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index d40ebbe62..d81f47e48 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -7019,9 +7019,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=1162 , 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=922  , 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=968  , 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=1534 , 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=1612 , 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=1934 , 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
@@ -7040,9 +7040,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=1162 , 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=922  , 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=968  , 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=1534 , 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=1612 , 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=1934 , 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;)
@@ -7072,9 +7072,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=1162 , 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=922  , 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=968  , 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=1534 , 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=1612 , 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=1934 , 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;)
@@ -7091,14 +7091,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=920  , 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=1532 , 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=920  , 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=1532 , 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
@@ -7113,7 +7113,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=872  , 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=1452 , 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"
@@ -7122,10 +7122,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=872  , 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=873  , 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=873  , 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=873  , 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=1452 , 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=1453 , 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=1453 , 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=1453 , 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_CLEANUP
@@ -7163,14 +7163,14 @@ 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=1160 , 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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=920  , 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=920  , 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=922  , 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=1532 , 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=1532 , 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=1534 , 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=1932 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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
@@ -7682,16 +7682,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=1162 , 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=1162 , 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=1162 , 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=776  , 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=776  , 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=920  , 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=922  , 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=922  , 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=922  , 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=968  , 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=1292 , 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=1292 , 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=1532 , 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=1534 , 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=1534 , 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=1534 , 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=1612 , 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=1934 , 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=1934 , 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=1934 , 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;)
 ])
 
 AT_CLEANUP
@@ -15229,12 +15229,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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=920  , 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=922  , 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=1532 , 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=1534 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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.
@@ -15250,13 +15250,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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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.
@@ -15273,13 +15273,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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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
@@ -15293,15 +15293,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=1158 , 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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1930 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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=1934 , 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.
@@ -15317,16 +15317,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=1158 , 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=1158 , 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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1930 , 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=1930 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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=1934 , 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.
@@ -15342,17 +15342,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=1158 , 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=1158 , 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=1160 , 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=1162 , 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=1162 , 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=1162 , 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=1162 , 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=918  , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1530 , 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=1532 , 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=1534 , 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=1930 , 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=1930 , 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=1932 , 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=1934 , 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=1934 , 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=1934 , 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=1934 , 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.
@@ -15364,11 +15364,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=1158 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1930 , 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=1934 , 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;)
 ])
 
 AT_CLEANUP
@@ -15397,11 +15397,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=1162 , 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=1162 , 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=920  , 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=922  , 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=922  , 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=1532 , 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=1534 , 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=1534 , 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=1934 , 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=1934 , 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;)
@@ -15423,12 +15423,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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1534 , 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=1934 , 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=1934 , 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;)
@@ -15451,12 +15451,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=1162 , 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=1162 , 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=918  , 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=920  , 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=922  , 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=922  , 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=1530 , 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=1532 , 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=1534 , 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=1534 , 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=1934 , 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=1934 , 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;)
@@ -15493,13 +15493,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=1162 , 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=1162 , 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=918  , 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=918  , 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=920  , 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=922  , 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=922  , 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=1530 , 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=1530 , 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=1532 , 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=1534 , 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=1534 , 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=1934 , 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=1934 , 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_CLEANUP
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 56a513217..bac9c041e 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -410,6 +410,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\
@@ -4766,6 +4767,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);
@@ -4853,11 +4856,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, "override-connected", "true");
+        }
+
         nbrec_logical_router_static_route_set_options(route, &options);
+
+        smap_destroy(&options);
     }
 
     nbrec_logical_router_update_static_routes_addvalue(lr, route);
@@ -6982,6 +6994,10 @@ print_route(const struct 
nbrec_logical_router_static_route *route,
         ds_put_cstr(s, " ecmp-symmetric-reply");
     }
 
+    if (smap_get_bool(&route->options, "override-connected", false)) {
+        ds_put_cstr(s, " override-connected");
+    }
+
     if (route->bfd) {
         ds_put_cstr(s, " bfd");
     }
@@ -8404,8 +8420,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.49.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to