Skip to content

Commit

Permalink
controller: Support learning routes.
Browse files Browse the repository at this point in the history
we now learn all routes inside the vrfs we also advertise routes on.
The routes are then placed in the southbound database for processing by
northd.

Routes are only selected if matching the following rules:
1. must not be a route advertised by us
2. must not be a local connected route (as we want to not learn transfer
   networks)
3. the prefix must not be a link local address

However we can not reliably determine over which link we learned the
route in case we have two LRPs of the same LR on the same chassis.
For now we just assume the routes on both links are identical.
Future commits will refine this.

Signed-off-by: Felix Huettner <felix.huettner@stackit.cloud>
Signed-off-by: 0-day Robot <robot@bytheb.org>
  • Loading branch information
felixhuettner authored and ovsrobot committed Jan 2, 2025
1 parent a21916f commit 8414712
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 10 deletions.
50 changes: 45 additions & 5 deletions controller/ovn-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
*
* Monitor Template_Var for local chassis.
*
* Monitor Advertised_Route for local datapaths.
* Monitor Advertised/Learned_Route for local datapaths.
*
* We always monitor patch ports because they allow us to see the linkages
* between related logical datapaths. That way, when we know that we have
Expand All @@ -252,6 +252,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
struct ovsdb_idl_condition chprv = OVSDB_IDL_CONDITION_INIT(&chprv);
struct ovsdb_idl_condition tv = OVSDB_IDL_CONDITION_INIT(&tv);
struct ovsdb_idl_condition ar = OVSDB_IDL_CONDITION_INIT(&ar);
struct ovsdb_idl_condition lr = OVSDB_IDL_CONDITION_INIT(&lr);

/* Always monitor all logical datapath groups. Otherwise, DPG updates may
* be received *after* the lflows using it are seen by ovn-controller.
Expand All @@ -272,6 +273,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
ovsdb_idl_condition_add_clause_true(&chprv);
ovsdb_idl_condition_add_clause_true(&tv);
ovsdb_idl_condition_add_clause_true(&ar);
ovsdb_idl_condition_add_clause_true(&lr);
goto out;
}

Expand Down Expand Up @@ -361,6 +363,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl,
sbrec_ip_multicast_add_clause_datapath(&ip_mcast, OVSDB_F_EQ,
uuid);
sbrec_advertised_route_add_clause_datapath(&ar, OVSDB_F_EQ, uuid);
sbrec_learned_route_add_clause_datapath(&lr, OVSDB_F_EQ, uuid);
}

/* Datapath groups are immutable, which means a new group record is
Expand Down Expand Up @@ -389,6 +392,7 @@ out:;
sb_table_set_req_mon_condition(ovnsb_idl, chassis_private, &chprv),
sb_table_set_opt_mon_condition(ovnsb_idl, chassis_template_var, &tv),
sb_table_set_opt_mon_condition(ovnsb_idl, advertised_route, &ar),
sb_table_set_opt_mon_condition(ovnsb_idl, learned_route, &lr),
};

unsigned int expected_cond_seqno = 0;
Expand All @@ -409,6 +413,7 @@ out:;
ovsdb_idl_condition_destroy(&chprv);
ovsdb_idl_condition_destroy(&tv);
ovsdb_idl_condition_destroy(&ar);
ovsdb_idl_condition_destroy(&lr);
return expected_cond_seqno;
}

Expand Down Expand Up @@ -874,7 +879,8 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
SB_NODE(meter, "meter") \
SB_NODE(static_mac_binding, "static_mac_binding") \
SB_NODE(chassis_template_var, "chassis_template_var") \
SB_NODE(advertised_route, "advertised_route")
SB_NODE(advertised_route, "advertised_route") \
SB_NODE(learned_route, "learned_route")

enum sb_engine_node {
#define SB_NODE(NAME, NAME_STR) SB_##NAME,
Expand Down Expand Up @@ -4993,13 +4999,34 @@ route_sb_advertised_route_data_handler(struct engine_node *node, void *data)
return true;
}

struct ed_type_route_exchange {
/* We need the idl to check if a table exists. */
struct ovsdb_idl *sb_idl;
};

static void
en_route_exchange_run(struct engine_node *node, void *data OVS_UNUSED)
en_route_exchange_run(struct engine_node *node, void *data)
{
struct ed_type_route_exchange *re = data;

struct ovsdb_idl_index *sbrec_learned_route_by_datapath =
engine_ovsdb_node_get_index(
engine_get_input("SB_learned_route", node),
"datapath");

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_route *route_data =
engine_get_input_data("route", node);

struct route_exchange_ctx_in r_ctx_in = {
.ovnsb_idl_txn = engine_get_context()->ovnsb_idl_txn,
.ovnsb_idl = re->sb_idl,
.sbrec_learned_route_by_datapath = sbrec_learned_route_by_datapath,
.sbrec_port_binding_by_name = sbrec_port_binding_by_name,
.announce_routes = &route_data->announce_routes,
};

Expand All @@ -5014,9 +5041,11 @@ en_route_exchange_run(struct engine_node *node, void *data OVS_UNUSED)

static void *
en_route_exchange_init(struct engine_node *node OVS_UNUSED,
struct engine_arg *arg OVS_UNUSED)
struct engine_arg *arg)
{
return NULL;
struct ed_type_route_exchange *re = xzalloc(sizeof(*re));
re->sb_idl = arg->sb_idl;
return re;
}

static void
Expand Down Expand Up @@ -5234,6 +5263,9 @@ main(int argc, char *argv[])
struct ovsdb_idl_index *sbrec_advertised_route_index_by_datapath
= ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
&sbrec_advertised_route_col_datapath);
struct ovsdb_idl_index *sbrec_learned_route_index_by_datapath
= ovsdb_idl_index_create1(ovnsb_idl_loop.idl,
&sbrec_learned_route_col_datapath);

ovsdb_idl_track_add_all(ovnsb_idl_loop.idl);
ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
Expand All @@ -5260,6 +5292,8 @@ main(int argc, char *argv[])
&sbrec_ha_chassis_group_col_external_ids);
ovsdb_idl_omit(ovnsb_idl_loop.idl,
&sbrec_advertised_route_col_external_ids);
ovsdb_idl_omit(ovnsb_idl_loop.idl,
&sbrec_learned_route_col_external_ids);

/* We don't want to monitor Connection table at all. So omit all the
* columns. */
Expand Down Expand Up @@ -5353,6 +5387,10 @@ main(int argc, char *argv[])
route_sb_advertised_route_data_handler);

engine_add_input(&en_route_exchange, &en_route, NULL);
engine_add_input(&en_route_exchange, &en_sb_learned_route,
engine_noop_handler);
engine_add_input(&en_route_exchange, &en_sb_port_binding,
engine_noop_handler);

engine_add_input(&en_addr_sets, &en_sb_address_set,
addr_sets_sb_address_set_handler);
Expand Down Expand Up @@ -5573,6 +5611,8 @@ main(int argc, char *argv[])
sbrec_chassis_template_var_index_by_chassis);
engine_ovsdb_node_add_index(&en_sb_advertised_route, "datapath",
sbrec_advertised_route_index_by_datapath);
engine_ovsdb_node_add_index(&en_sb_learned_route, "datapath",
sbrec_learned_route_index_by_datapath);
engine_ovsdb_node_add_index(&en_ovs_flow_sample_collector_set, "id",
ovsrec_flow_sample_collector_set_by_id);
engine_ovsdb_node_add_index(&en_ovs_port, "qos", ovsrec_port_by_qos);
Expand Down
42 changes: 40 additions & 2 deletions controller/route-exchange-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"
#include "packets.h"
#include "ovn-util.h"
#include "route-table.h"
#include "route.h"

Expand Down Expand Up @@ -171,8 +172,27 @@ re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
return modify_route(RTM_DELROUTE, 0, table_id, dst, plen);
}

static uint32_t
route_hash(const struct in6_addr *dst, unsigned int plen)
{
uint32_t hash = hash_bytes(dst->s6_addr, 16, 0);
return hash_int(plen, hash);
}

void
re_nl_received_routes_destroy(struct hmap *host_routes)
{
struct re_nl_received_route_node *rr;
HMAP_FOR_EACH_SAFE (rr, hmap_node, host_routes) {
hmap_remove(host_routes, &rr->hmap_node);
free(rr);
}
hmap_destroy(host_routes);
}

struct route_msg_handle_data {
const struct hmap *routes;
struct hmap *learned_routes;
};

static void
Expand All @@ -184,8 +204,25 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data)
struct advertise_route_entry *ar;
int err;

/* This route is not from us, we should not touch it. */
/* This route is not from us, so we learn it. */
if (rd->rtm_protocol != RTPROT_OVN) {
if (prefix_is_link_local(&rd->rta_dst, rd->rtm_dst_len)) {
return;
}
struct route_data_nexthop *nexthop;
LIST_FOR_EACH (nexthop, nexthop_node, &rd->nexthops) {
if (ipv6_is_zero(&nexthop->addr)) {
/* This is most likely an address on the local link.
* As we just want to learn remote routes we do not need it.*/
continue;
}
struct re_nl_received_route_node *rr = xzalloc(sizeof *rr);
hmap_insert(handle_data->learned_routes, &rr->hmap_node,
route_hash(&rd->rta_dst, rd->rtm_dst_len));
rr->addr = rd->rta_dst;
rr->plen = rd->rtm_dst_len;
rr->nexthop = nexthop->addr;
}
return;
}

Expand All @@ -212,7 +249,7 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data)

void
re_nl_sync_routes(uint32_t table_id,
const struct hmap *routes)
const struct hmap *routes, struct hmap *learned_routes)
{
struct advertise_route_entry *ar;
HMAP_FOR_EACH (ar, node, routes) {
Expand All @@ -224,6 +261,7 @@ re_nl_sync_routes(uint32_t table_id,
* in the system. */
struct route_msg_handle_data data = {
.routes = routes,
.learned_routes = learned_routes,
};
route_table_dump_one_table(table_id, handle_route_msg_delete_routes,
&data);
Expand Down
13 changes: 12 additions & 1 deletion controller/route-exchange-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#define ROUTE_EXCHANGE_NETLINK_H 1

#include <stdint.h>
#include "openvswitch/hmap.h"
#include <netinet/in.h>

/* This value is arbitrary but currently unused.
* See https://github.com/iproute2/iproute2/blob/main/etc/iproute2/rt_protos */
Expand All @@ -24,6 +26,13 @@
struct in6_addr;
struct hmap;

struct re_nl_received_route_node {
struct hmap_node hmap_node;
struct in6_addr addr;
unsigned int plen;
struct in6_addr nexthop;
};

int re_nl_create_vrf(const char *ifname, uint32_t table_id);
int re_nl_delete_vrf(const char *ifname);

Expand All @@ -34,7 +43,9 @@ int re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,

void re_nl_dump(uint32_t table_id);

void re_nl_received_routes_destroy(struct hmap *);
void re_nl_sync_routes(uint32_t table_id,
const struct hmap *host_routes);
const struct hmap *host_routes,
struct hmap *learned_routes);

#endif /* route-exchange-netlink.h */
Loading

0 comments on commit 8414712

Please sign in to comment.