diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index 69bac4ab2..452416e8b 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -874,6 +874,7 @@ struct ic_route_info {
     struct in6_addr nexthop;
     const char *origin;
     const char *route_table;
+    const char *route_tag;
 
     const struct nbrec_logical_router *nb_lr;
 
@@ -1124,7 +1125,8 @@ add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix,
                  const char *origin, const char *route_table,
                  const struct nbrec_logical_router_port *nb_lrp,
                  const struct nbrec_logical_router_static_route *nb_route,
-                 const struct nbrec_logical_router *nb_lr)
+                 const struct nbrec_logical_router *nb_lr,
+                 const char *route_tag)
 {
     if (route_table == NULL) {
         route_table = "";
@@ -1143,6 +1145,7 @@ add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix,
         ic_route->route_table = route_table;
         ic_route->nb_lrp = nb_lrp;
         ic_route->nb_lr = nb_lr;
+        ic_route->route_tag = route_tag;
         hmap_insert(routes_ad, &ic_route->node, hash);
     } else {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
@@ -1158,7 +1161,8 @@ add_static_to_routes_ad(
     const struct nbrec_logical_router_static_route *nb_route,
     const struct nbrec_logical_router *nb_lr,
     const struct lport_addresses *nexthop_addresses,
-    const struct smap *nb_options)
+    const struct smap *nb_options,
+    const char *route_tag)
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
@@ -1199,7 +1203,7 @@ add_static_to_routes_ad(
     }
 
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_STATIC,
-                     nb_route->route_table, NULL, nb_route, nb_lr);
+                     nb_route->route_table, NULL, nb_route, nb_lr, route_tag);
 }
 
 static void
@@ -1207,7 +1211,8 @@ add_network_to_routes_ad(struct hmap *routes_ad, const char *network,
                          const struct nbrec_logical_router_port *nb_lrp,
                          const struct lport_addresses *nexthop_addresses,
                          const struct smap *nb_options,
-                         const struct nbrec_logical_router *nb_lr)
+                         const struct nbrec_logical_router *nb_lr,
+                         const char *route_tag)
 {
     struct in6_addr prefix, nexthop;
     unsigned int plen;
@@ -1246,7 +1251,7 @@ add_network_to_routes_ad(struct hmap *routes_ad, const char *network,
 
     /* directly-connected routes go to <main> route table */
     add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_CONNECTED,
-                     NULL, nb_lrp, NULL, nb_lr);
+                     NULL, nb_lrp, NULL, nb_lr, route_tag);
 }
 
 static bool
@@ -1315,8 +1320,8 @@ get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name)
     return smap_get(&nb_lsp->options, "router-port");
 }
 
-static const char *
-get_route_table_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
+static const struct nbrec_logical_router_port *
+get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
 {
     const struct nbrec_logical_router_port *lrp;
     const struct nbrec_logical_router_port *lrp_key =
@@ -1326,10 +1331,7 @@ get_route_table_by_lrp_name(struct ic_context *ctx, const char *lrp_name)
                                                lrp_key);
     nbrec_logical_router_port_index_destroy_row(lrp_key);
 
-    if (lrp) {
-        return smap_get_def(&lrp->options, "route_table", "");
-    }
-    return "";  /* <main> route table */
+    return lrp;
 }
 
 static bool
@@ -1359,12 +1361,21 @@ sync_learned_routes(struct ic_context *ctx,
         nbrec_nb_global_first(ctx->ovnnb_idl);
     ovs_assert(nb_global);
 
-    const char *lrp_name, *ts_route_table;
+    const char *lrp_name, *ts_route_table, *route_filter_tag;
     const struct icsbrec_port_binding *isb_pb;
+    const struct nbrec_logical_router_port *lrp;
     for (int i = 0; i < ic_lr->n_isb_pbs; i++) {
         isb_pb = ic_lr->isb_pbs[i];
         lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
-        ts_route_table = get_route_table_by_lrp_name(ctx, lrp_name);
+        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
+        if (lrp) {
+            ts_route_table = smap_get_def(&lrp->options, "route_table", "");
+            route_filter_tag = smap_get_def(&lrp->options,
+                                            "ic-route-filter-tag", "");
+        } else {
+            ts_route_table = "";
+            route_filter_tag = "";
+        }
 
         isb_route_key = icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts);
         icsbrec_route_index_set_transit_switch(isb_route_key,
@@ -1384,6 +1395,17 @@ sync_learned_routes(struct ic_context *ctx,
                 continue;
             }
 
+            const char *isb_route_tag = smap_get(&isb_route->external_ids,
+                                                 "ic-route-tag");
+            if ((isb_route_tag != NULL) &&
+                (!strcmp(isb_route_tag, route_filter_tag))) {
+                VLOG_DBG("Skip learning route %s -> %s as either "
+                         "its route tag %s is filtered by %s of TS LRP ",
+                         isb_route->ip_prefix, isb_route->nexthop,
+                         isb_route_tag, route_filter_tag);
+                continue;
+            }
+
             if (isb_route->route_table[0] &&
                 strcmp(isb_route->route_table, ts_route_table)) {
                 if (VLOG_IS_DBG_ENABLED()) {
@@ -1471,6 +1493,7 @@ ad_route_sync_external_ids(const struct ic_route_info *route_adv,
                            const struct icsbrec_route *isb_route)
 {
     struct uuid isb_ext_id, nb_id, isb_ext_lr_id, lr_id;
+    const char *route_tag;
     smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id);
     smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id);
     nb_id = route_adv->nb_route ? route_adv->nb_route->header_.uuid
@@ -1488,6 +1511,16 @@ ad_route_sync_external_ids(const struct ic_route_info *route_adv,
                                                  uuid_s);
         free(uuid_s);
     }
+    if (strcmp(route_adv->route_tag, "")) {
+        icsbrec_route_update_external_ids_setkey(isb_route, "ic-route-tag",
+                                                 route_adv->route_tag);
+    } else {
+        route_tag = smap_get(&isb_route->external_ids, "ic-route-tag");
+        if (route_tag) {
+            icsbrec_route_update_external_ids_delkey(isb_route,
+                                                     "ic-route-tag");
+        }
+    }
 }
 
 /* Sync routes from routes_ad to IC-SB. */
@@ -1580,7 +1613,8 @@ build_ts_routes_to_adv(struct ic_context *ctx,
                        struct hmap *routes_ad,
                        struct lport_addresses *ts_port_addrs,
                        const struct nbrec_nb_global *nb_global,
-                       const char *ts_route_table)
+                       const char *ts_route_table,
+                       const char *route_tag)
 {
     const struct nbrec_logical_router *lr = ic_lr->lr;
 
@@ -1603,7 +1637,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,
         } else if (!strcmp(ts_route_table, nb_route->route_table)) {
             /* It may be a route to be advertised */
             add_static_to_routes_ad(routes_ad, nb_route, lr, ts_port_addrs,
-                                    &nb_global->options);
+                                    &nb_global->options, route_tag);
         }
     }
 
@@ -1615,7 +1649,7 @@ build_ts_routes_to_adv(struct ic_context *ctx,
                 add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp,
                                          ts_port_addrs,
                                          &nb_global->options,
-                                         lr);
+                                         lr, route_tag);
             }
         } else {
             /* The router port of the TS port is ignored. */
@@ -1635,9 +1669,10 @@ collect_lr_routes(struct ic_context *ctx,
     ovs_assert(nb_global);
 
     const struct icsbrec_port_binding *isb_pb;
-    const char *lrp_name, *ts_name, *route_table;
+    const char *lrp_name, *ts_name, *route_table, *route_tag;
     struct lport_addresses ts_port_addrs;
     const struct icnbrec_transit_switch *key;
+    const struct nbrec_logical_router_port *lrp;
 
     struct hmap *routes_ad;
     const struct icnbrec_transit_switch *t_sw;
@@ -1669,9 +1704,16 @@ collect_lr_routes(struct ic_context *ctx,
             continue;
         }
         lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port);
-        route_table = get_route_table_by_lrp_name(ctx, lrp_name);
+        lrp = get_lrp_by_lrp_name(ctx, lrp_name);
+        if (lrp) {
+            route_table = smap_get_def(&lrp->options, "route_table", "");
+            route_tag = smap_get_def(&lrp->options, "ic-route-tag", "");
+        } else {
+            route_table = "";
+            route_tag = "";
+        }
         build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs,
-                               nb_global, route_table);
+                               nb_global, route_table, route_tag);
         destroy_lport_addresses(&ts_port_addrs);
     }
 }
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 2836f58f5..adb9144ae 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -3662,6 +3662,33 @@ or
 
         </ul>
       </column>
+
+      <column name="options" key="ic-route-tag" type='{"type": "string"}'>
+        <p>
+          This option expects a name of a route-tag that's present in the
+          Logical Router Port. If set, it causes any route advertised by
+          the Logical Router Port to include the <code>route-tag</code> in
+          the <code> external_ids </code> register of the advertised route
+          entry in the <ref table="Route" db="OVN_IC_Southbound"/> table of
+          the <ref db="OVN_IC_Southbound"/> database.
+
+          This allows to tag and filter route tags in the process of
+          advertising and learning routes in <code>ovn-ic</code> daemon.
+        </p>
+      </column>
+
+      <column name="options" key="ic-route-filter-tag"
+              type='{"type": "string"}'>
+        <p>
+          This option expects a name of a filtered route-tag that's present
+          in the Logical Router Port. If set, it causes any route learned by
+          the Logical Router Port with the <code>route-tag</code> present in
+          the external_ids register of the advertised route entry in the
+          <ref table="Route" db="OVN_IC_Southbound"/> table of the
+          <ref db="OVN_IC_Southbound"/> database, will be filtered and not
+          learned by the <code>ovn-ic</code> daemon.
+        </p>
+      </column>
     </group>
 
     <group title="Attachment">
diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
index 9fa41200e..33ad37f2e 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -2357,3 +2357,203 @@ OVN_CLEANUP_SBOX([hv2], ["/IGMP Querier enabled without a valid IPv4/d
 OVN_CLEANUP_IC([az1],[az2])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn-ic -- route tag -- tagging and filtering routes])
+
+ovn_init_ic_db
+ovn-ic-nbctl ts-add ts1
+
+for i in 1 2; do
+    ovn_start az$i
+    ovn_as az$i
+
+    # Enable route learning at AZ level
+    ovn-nbctl set nb_global . options:ic-route-learn=true
+    # Enable route advertising at AZ level
+    ovn-nbctl set nb_global . options:ic-route-adv=true
+done
+
+# Create new transit switches and LRs. Test topology is next:
+# VPC1:
+#                       / transit switch (ts11) \
+# logical router (lr11) - transit switch (ts12) - logical router (lr12)
+#                       \                       /
+#                        transit switch (tspeer)
+# VPC2:                 /                       \
+# logical router (lr21) - transit switch (ts21) - logical router (lr22)
+#                       \ transit switch (ts22) /
+#
+
+# VPC1
+# create lr11, lr12, ts11, ts12 and connect them
+for i in 1 2; do
+    ovn_as az$i
+
+    lr=lr1$i
+    ovn-nbctl lr-add $lr
+
+    for j in 1 2; do
+        ts=ts1$j
+        ovn-ic-nbctl --wait=sb --may-exist ts-add $ts
+
+        lrp=lrp-$lr-$ts
+        lsp=lsp-$ts-$lr
+        # Create LRP and connect to TS
+        ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24
+        ovn-nbctl lsp-add $ts $lsp \
+                -- lsp-set-addresses $lsp router \
+                -- lsp-set-type $lsp router \
+                -- lsp-set-options $lsp router-port=$lrp
+    done
+done
+
+# VPC2
+# create lr21, lr22, ts21, ts22 and connect them
+for i in 1 2; do
+    ovn_as az$i
+
+    lr=lr2$i
+    ovn-nbctl lr-add $lr
+
+    for j in 1 2; do
+        ts=ts2$j
+        ovn-ic-nbctl --wait=sb --may-exist ts-add $ts
+
+        lrp=lrp-$lr-$ts
+        lsp=lsp-$ts-$lr
+        # Create LRP and connect to TS
+        ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24
+        ovn-nbctl lsp-add $ts $lsp \
+                -- lsp-set-addresses $lsp router \
+                -- lsp-set-type $lsp router \
+                -- lsp-set-options $lsp router-port=$lrp
+    done
+done
+
+# Create directly-connected route in VPC1
+ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12 aa:aa:aa:aa:bb:01 "192.168.0.1/24"
+
+# Create directly-connected route in VPC2
+ovn_as az2 ovn-nbctl --wait=sb lrp-add lr22 lrp-lr22 aa:aa:aa:aa:cc:01 "192.168.1.1/24"
+
+check ovn-ic-nbctl --wait=sb sync
+
+# Test direct routes from lr12 were learned to lr11
+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.102.2 ecmp
+])
+
+# Test direct routes from lr22 were learned to lr21
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 192.168 |
+             grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl
+192.168.1.0/24 169.254.101.2 ecmp
+192.168.1.0/24 169.254.102.2 ecmp
+])
+
+# Create peering TS
+ovn-ic-nbctl --wait=sb --may-exist ts-add tspeer
+
+# Create LRPs and connect to the peering TS
+ovn_as az1
+ovn-nbctl lrp-add lr11 lrp-lr11-tspeer aa:aa:aa:aa:11:01 169.254.103.11/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr11 \
+        -- lsp-set-addresses lsp-tspeer-lr11 router \
+        -- lsp-set-type lsp-tspeer-lr11 router \
+        -- lsp-set-options lsp-tspeer-lr11 router-port=lrp-lr11-tspeer
+
+ovn_as az2
+ovn-nbctl lrp-add lr12 lrp-lr12-tspeer aa:aa:aa:aa:12:01 169.254.103.12/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr12 \
+        -- lsp-set-addresses lsp-tspeer-lr12 router \
+        -- lsp-set-type lsp-tspeer-lr12 router \
+        -- lsp-set-options lsp-tspeer-lr12 router-port=lrp-lr12-tspeer
+
+ovn_as az1
+ovn-nbctl lrp-add lr21 lrp-lr21-tspeer aa:aa:aa:aa:21:01 169.254.103.21/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr21 \
+        -- lsp-set-addresses lsp-tspeer-lr21 router \
+        -- lsp-set-type lsp-tspeer-lr21 router \
+        -- lsp-set-options lsp-tspeer-lr21 router-port=lrp-lr21-tspeer
+
+ovn_as az2
+ovn-nbctl lrp-add lr22 lrp-lr22-tspeer aa:aa:aa:aa:22:01 169.254.103.22/24
+ovn-nbctl lsp-add tspeer lsp-tspeer-lr22 \
+        -- lsp-set-addresses lsp-tspeer-lr22 router \
+        -- lsp-set-type lsp-tspeer-lr22 router \
+        -- lsp-set-options lsp-tspeer-lr22 router-port=lrp-lr22-tspeer
+
+check ovn-ic-nbctl --wait=sb sync
+
+# Test direct routes from lr12/lr22 were learned to lr11
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+# Test direct routes from lr22/lr12 were learned to lr21
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.101.2
+192.168.1.0/24 169.254.102.2
+192.168.1.0/24 169.254.103.22
+])
+
+# VPC1: Create a route tag for VPC1 mark its own routes via lrp-lr12
+ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer options:ic-route-tag=vpc1
+
+# Test advertised routes with the vpc1 route tag present
+ovn-ic-sbctl list route
+wait_row_count ic-sb:Route 1 ip_prefix=192.168.0.1/24 nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1
+
+# Filter routes on VPC1 lrp-lr11-tspeer with the route tag vpc1 present
+ovn_as az1 ovn-nbctl set logical_router_port lrp-lr11-tspeer options:ic-route-filter-tag=vpc1
+
+# Test remaining direct routes from lr12 were learned to lr11
+# Routes from the 169.254.101.2 nexthop have been filtered
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.1.0/24 169.254.103.22
+])
+
+# Remove the route tag used for advertisement
+ovn_as az2 ovn-nbctl remove logical_router_port lrp-lr12-tspeer options ic-route-tag=vpc1
+
+# Test advertised routes with the vpc1 route tag present
+ovn-ic-sbctl list route
+wait_row_count ic-sb:Route 0 ip_prefix=192.168.0.1/24 nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1
+
+# Test the original direct routes from lr12/lr22 were learned to lr11
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+# Remove route tag filter and add route tag on lrp-lr12-tspeer advertised routes
+ovn_as az1 ovn-nbctl remove logical_router_port lrp-lr11-tspeer options ic-route-filter-tag=vpc1
+ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer options:ic-route-tag=vpc1
+
+# Test if all the routes are learned because we no longer have the filter tag option enabled
+OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep 192.168 |
+             grep learned | awk '{print $1, $2}' | sort ], [0], [dnl
+192.168.0.0/24 169.254.101.2
+192.168.0.0/24 169.254.102.2
+192.168.0.0/24 169.254.103.12
+192.168.1.0/24 169.254.103.22
+])
+
+OVN_CLEANUP_IC([az1], [az2])
+
+AT_CLEANUP
+])
