Skip to content

Commit

Permalink
ovn-ic: Add support for route tag.
Browse files Browse the repository at this point in the history
The OVN-IC feature can handle multiple points of redistribution when
we include more than one TS in the same Logical Router. So, it is a
good idea to use route tagging to prevent learing routes from logical
routers in the same user domain via Transit switch created for
peer-links with another user domain.

This means that there can be a logical separation by user domain
(e.g. VPCs), and a Transit Switch that peers between the different
VPCs, connecting the routers in the VPC1 with the routers in the VPC2,
for example. In this case, the route tag can ensure that the Logical
Routers of VPC1 does not learn routes from VPC1 itself via the peering
TS, avoiding installing additional openflow flows to handle
multipath/ecmp unnecessarily.

To use this route tag feature, new options were created to be configured
in the Logical Router Port connected to the TS. This configuration must
be performed in the LRP insted of the LR because the LRP is the path used
to advertise and learn routes connected to a specific TS (nexthop).

Signed-off-by: Roberto Bartzen Acosta <roberto.acosta@luizalabs.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
  • Loading branch information
r-acosta authored and numansiddique committed Oct 25, 2024
1 parent 264c831 commit b2b2b5a
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 19 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Post v24.09.0
- Added support to choose selection methods - dp_hash or
hash (with specified hash fields) for ECMP routes
while choosing nexthop.
- ovn-ic: Add support for route tag to prevent route learning.

OVN v24.09.0 - 13 Sep 2024
--------------------------
Expand Down
79 changes: 60 additions & 19 deletions ic/ovn-ic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 = "";
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -1199,15 +1203,16 @@ 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
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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -1384,6 +1395,16 @@ 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 && !strcmp(isb_route_tag, route_filter_tag)) {
VLOG_DBG("Skip learning route %s -> %s as its route tag "
"[%s] is filtered by the filter tag [%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()) {
Expand Down Expand Up @@ -1471,6 +1492,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
Expand All @@ -1488,6 +1510,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. */
Expand Down Expand Up @@ -1580,7 +1612,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;

Expand All @@ -1603,7 +1636,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);
}
}

Expand All @@ -1615,7 +1648,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. */
Expand All @@ -1635,9 +1668,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;
Expand Down Expand Up @@ -1669,9 +1703,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);
}
}
Expand Down
27 changes: 27 additions & 0 deletions ovn-nb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3678,6 +3678,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">
Expand Down
Loading

0 comments on commit b2b2b5a

Please sign in to comment.