Skip to content

Commit

Permalink
controller: Prioritize host routes.
Browse files Browse the repository at this point in the history
northd allows us to announce host routes instead of connected routes of
LRs.

For the host routes we also know the LSP that host the address.
We can then check if this LSP is pointing to a LRP that is also local to
the current chassis, so if a LR is chained behind an LR and both use
chassisredirect ports.
In this case we can announce the route with a more preferable priority
than otherwise.

This helps in the following case:
* the backend router is bound on only a single chassis
* the frontend router is bound to multiple chassis (with multiple LRPs)
* one of the chassis of the frontend router matches the backend router

In this case it would be preferable if the network fabric sends the
traffic to the chassis that hosts both the frontend and backend router.
Other chassis would work as well, but then OVN would redirect the
traffic from one chassis to the other.
So this allows us to skip tunneling traffic in one case.

Signed-off-by: Felix Huettner <[email protected]>
Signed-off-by: 0-day Robot <[email protected]>
  • Loading branch information
felixhuettner authored and ovsrobot committed Dec 19, 2024
1 parent 5adb451 commit 9412f50
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 25 deletions.
51 changes: 51 additions & 0 deletions controller/ovn-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -4820,6 +4820,13 @@ struct ed_type_route {
/* Contains struct tracked_datapath entries for local datapaths subject to
* route exchange. */
struct hmap tracked_route_datapaths;

/* Contains the tracked_ports that in the last run where bound locally */
struct sset tracked_ports_local;

/* Contains the tracked_ports that in the last run where bound not local */
struct sset tracked_ports_remote;

/* Contains struct advertise_datapath_entry */
struct hmap announce_routes;
};
Expand Down Expand Up @@ -4868,6 +4875,8 @@ en_route_run(struct engine_node *node, void *data)

struct route_ctx_out r_ctx_out = {
.tracked_re_datapaths = &re_data->tracked_route_datapaths,
.tracked_ports_local = &re_data->tracked_ports_local,
.tracked_ports_remote = &re_data->tracked_ports_remote,
.announce_routes = &re_data->announce_routes,
};

Expand All @@ -4884,6 +4893,8 @@ en_route_init(struct engine_node *node OVS_UNUSED,
struct ed_type_route *data = xzalloc(sizeof *data);

hmap_init(&data->tracked_route_datapaths);
sset_init(&data->tracked_ports_local);
sset_init(&data->tracked_ports_remote);
hmap_init(&data->announce_routes);

return data;
Expand All @@ -4895,6 +4906,8 @@ en_route_cleanup(void *data)
struct ed_type_route *re_data = data;

tracked_datapaths_destroy(&re_data->tracked_route_datapaths);
sset_destroy(&re_data->tracked_ports_local);
sset_destroy(&re_data->tracked_ports_remote);
route_cleanup(&re_data->announce_routes);
hmap_destroy(&re_data->announce_routes);
}
Expand Down Expand Up @@ -4942,6 +4955,26 @@ route_sb_port_binding_data_handler(struct engine_node *node, void *data)
const struct sbrec_port_binding_table *pb_table =
EN_OVSDB_GET(engine_get_input("SB_port_binding", node));

const struct ovsrec_open_vswitch_table *ovs_table =
EN_OVSDB_GET(engine_get_input("OVS_open_vswitch", node));
const char *chassis_id = get_ovs_chassis_id(ovs_table);
ovs_assert(chassis_id);

struct ovsdb_idl_index *sbrec_chassis_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_chassis", node),
"name");
const struct sbrec_chassis *chassis
= chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
ovs_assert(chassis);

struct ovsdb_idl_index *sbrec_port_binding_by_name =
engine_ovsdb_node_get_index(
engine_get_input("SB_port_binding", node),
"name");
struct ed_type_runtime_data *rt_data =
engine_get_input_data("runtime_data", node);

const struct sbrec_port_binding *sbrec_pb;
SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (sbrec_pb, pb_table) {
struct tracked_datapath *re_t_dp =
Expand All @@ -4959,6 +4992,24 @@ route_sb_port_binding_data_handler(struct engine_node *node, void *data)
return false;
}

if (sset_contains(&re_data->tracked_ports_local,
sbrec_pb->logical_port)) {
if (!find_route_exchange_pb(sbrec_port_binding_by_name, chassis,
&rt_data->active_tunnels, sbrec_pb)) {
/* The port was previously local but now it no longer is. */
return false;
}
}

if (sset_contains(&re_data->tracked_ports_remote,
sbrec_pb->logical_port)) {
if (find_route_exchange_pb(sbrec_port_binding_by_name, chassis,
&rt_data->active_tunnels, sbrec_pb)) {
/* The port was previously remote but now we bound it. */
return false;
}
}

}
return true;
}
Expand Down
21 changes: 13 additions & 8 deletions controller/route-exchange-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ re_nl_delete_vrf(const char *ifname)

static int
modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
const struct in6_addr *dst, unsigned int plen)
const struct in6_addr *dst, unsigned int plen,
unsigned int priority)
{
uint32_t flags = NLM_F_REQUEST | NLM_F_ACK;
bool is_ipv4 = IN6_IS_ADDR_V4MAPPED(dst);
Expand All @@ -128,6 +129,7 @@ modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
rt->rtm_dst_len = plen;

nl_msg_put_u32(&request, RTA_TABLE, table_id);
nl_msg_put_u32(&request, RTA_PRIORITY, priority);

if (is_ipv4) {
nl_msg_put_be32(&request, RTA_DST, in6_addr_get_mapped_ipv4(dst));
Expand All @@ -143,7 +145,7 @@ modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,

int
re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
unsigned int plen)
unsigned int plen, unsigned int priority)
{
uint32_t flags = NLM_F_CREATE | NLM_F_EXCL;
uint32_t type = RTM_NEWROUTE;
Expand All @@ -155,12 +157,12 @@ re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
return EINVAL;
}

return modify_route(type, flags, table_id, dst, plen);
return modify_route(type, flags, table_id, dst, plen, priority);
}

int
re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
unsigned int plen)
unsigned int plen, unsigned int priority)
{
if (!TABLE_ID_VALID(table_id)) {
VLOG_WARN_RL(&rl,
Expand All @@ -169,7 +171,7 @@ re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
return EINVAL;
}

return modify_route(RTM_DELROUTE, 0, table_id, dst, plen);
return modify_route(RTM_DELROUTE, 0, table_id, dst, plen, priority);
}

static uint32_t
Expand Down Expand Up @@ -230,13 +232,15 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data)
uint32_t arhash = advertise_route_hash(&rd->rta_dst, rd->rtm_dst_len);
HMAP_FOR_EACH_WITH_HASH (ar, node, arhash, routes) {
if (ipv6_addr_equals(&ar->addr, &rd->rta_dst)
&& ar->plen == rd->rtm_dst_len) {
&& ar->plen == rd->rtm_dst_len
&& ar->priority == rd->rta_priority) {
ar->installed = true;
return;
}
}

err = re_nl_delete_route(rd->rta_table_id, &rd->rta_dst,
rd->rtm_dst_len);
rd->rtm_dst_len, rd->rta_priority);
if (err) {
char addr_s[INET6_ADDRSTRLEN + 1];
VLOG_WARN_RL(&rl, "Delete route table_id=%"PRIu32" dst=%s plen=%d: %s",
Expand Down Expand Up @@ -273,7 +277,8 @@ re_nl_sync_routes(uint32_t table_id,
if (ar->installed) {
continue;
}
int err = re_nl_add_route(table_id, &ar->addr, ar->plen);
int err = re_nl_add_route(table_id, &ar->addr, ar->plen,
ar->priority);
if (err) {
char addr_s[INET6_ADDRSTRLEN + 1];
VLOG_WARN_RL(&rl, "Add route table_id=%"PRIu32" dst=%s "
Expand Down
4 changes: 2 additions & 2 deletions controller/route-exchange-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ int re_nl_create_vrf(const char *ifname, uint32_t table_id);
int re_nl_delete_vrf(const char *ifname);

int re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
unsigned int plen);
unsigned int plen, unsigned int priority);
int re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
unsigned int plen);
unsigned int plen, unsigned int priority);

void re_nl_dump(uint32_t table_id);

Expand Down
48 changes: 47 additions & 1 deletion controller/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
* in the corresponding VRF interface name. */
#define MAX_TABLE_ID 1000000000

#define PRIORITY_DEFAULT 1000
#define PRIORITY_LOCAL_BOUND 100

bool
route_exchange_relevant_port(const struct sbrec_port_binding *pb)
{
Expand All @@ -46,7 +49,7 @@ advertise_route_hash(const struct in6_addr *dst, unsigned int plen)
return hash_int(plen, hash);
}

static const struct sbrec_port_binding*
const struct sbrec_port_binding*
find_route_exchange_pb(struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct sbrec_chassis *chassis,
const struct sset *active_tunnels,
Expand Down Expand Up @@ -74,6 +77,29 @@ find_route_exchange_pb(struct ovsdb_idl_index *sbrec_port_binding_by_name,
return NULL;
}

static bool
pb_is_local(struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct sbrec_chassis *chassis,
const struct sset *active_tunnels,
const char *port_name)
{
if (lport_is_chassis_resident(sbrec_port_binding_by_name, chassis,
active_tunnels, port_name)) {
return true;
}

const struct sbrec_port_binding *pb = lport_lookup_by_name(
sbrec_port_binding_by_name, port_name);

const char *crp = smap_get(&pb->options, "chassis-redirect-port");
if (!crp) {
return NULL;
}

return lport_is_chassis_resident(sbrec_port_binding_by_name, chassis,
active_tunnels, crp);
}

static void
advertise_datapath_cleanup(struct advertise_datapath_entry *ad)
{
Expand All @@ -92,6 +118,8 @@ route_run(struct route_ctx_in *r_ctx_in,
struct route_ctx_out *r_ctx_out)
{
tracked_datapaths_destroy(r_ctx_out->tracked_re_datapaths);
sset_clear(r_ctx_out->tracked_ports_local);
sset_clear(r_ctx_out->tracked_ports_remote);

const struct local_datapath *ld;
HMAP_FOR_EACH (ld, hmap_node, r_ctx_in->local_datapaths) {
Expand Down Expand Up @@ -176,11 +204,29 @@ route_run(struct route_ctx_in *r_ctx_in,
continue;
}

unsigned int priority = PRIORITY_DEFAULT;

if (route->tracked_port) {
if (pb_is_local(
r_ctx_in->sbrec_port_binding_by_name,
r_ctx_in->chassis,
r_ctx_in->active_tunnels,
route->tracked_port->logical_port)) {
priority = PRIORITY_LOCAL_BOUND;
sset_add(r_ctx_out->tracked_ports_local,
route->tracked_port->logical_port);
} else {
sset_add(r_ctx_out->tracked_ports_remote,
route->tracked_port->logical_port);
}
}

struct advertise_route_entry *ar = xzalloc(sizeof(*ar));
hmap_insert(&ad->routes, &ar->node,
advertise_route_hash(&prefix, plen));
ar->addr = prefix;
ar->plen = plen;
ar->priority = priority;
}
sbrec_advertised_route_index_destroy_row(route_filter);

Expand Down
13 changes: 13 additions & 0 deletions controller/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ struct route_ctx_in {

struct route_ctx_out {
struct hmap *tracked_re_datapaths;

/* Contains the tracked_ports that in the last run where bound locally */
struct sset *tracked_ports_local;

/* Contains the tracked_ports that in the last run where bound not local */
struct sset *tracked_ports_remote;

/* Contains struct advertise_datapath_entry */
struct hmap *announce_routes;
};
Expand All @@ -61,11 +68,17 @@ struct advertise_route_entry {
struct hmap_node node;
struct in6_addr addr;
unsigned int plen;
unsigned int priority;
/* used by the route-exchange module to determine if the route is
* already installed */
bool installed;
};

const struct sbrec_port_binding *find_route_exchange_pb(
struct ovsdb_idl_index *sbrec_port_binding_by_name,
const struct sbrec_chassis *chassis,
const struct sset *active_tunnels,
const struct sbrec_port_binding *pb);
bool route_exchange_relevant_port(const struct sbrec_port_binding *pb);
uint32_t advertise_route_hash(const struct in6_addr *dst, unsigned int plen);
void route_run(struct route_ctx_in *,
Expand Down
Loading

0 comments on commit 9412f50

Please sign in to comment.