Skip to content

Commit

Permalink
controller: Support learning routes per iface.
Browse files Browse the repository at this point in the history
Previously we just assumed that if a LR had multiple LRPs bound to the
local chassis that all routes where valid for all of these LRPs.
This commit handles a previous option in ovn-nb that allowes the user to
specify the interface name that a route needs to use to be acceptable
for a given LRP.
The users can then have a 1:1 relationship between LRPs and interfaces
to allow ovn-controller to determine which route belongs to which LRP.

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 Dec 19, 2024
1 parent 5ba9ebc commit 5adb451
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 13 deletions.
1 change: 1 addition & 0 deletions controller/route-exchange-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data)
rr->addr = rd->rta_dst;
rr->plen = rd->rtm_dst_len;
rr->nexthop = nexthop->addr;
memcpy(rr->ifname, nexthop->ifname, IFNAMSIZ);
}
return;
}
Expand Down
2 changes: 2 additions & 0 deletions controller/route-exchange-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <stdint.h>
#include "openvswitch/hmap.h"
#include <netinet/in.h>
#include <net/if.h>

/* This value is arbitrary but currently unused.
* See https://github.com/iproute2/iproute2/blob/main/etc/iproute2/rt_protos */
Expand All @@ -31,6 +32,7 @@ struct re_nl_received_route_node {
struct in6_addr addr;
unsigned int plen;
struct in6_addr nexthop;
char ifname[IFNAMSIZ];
};

int re_nl_create_vrf(const char *ifname, uint32_t table_id);
Expand Down
21 changes: 15 additions & 6 deletions controller/route-exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ route_erase_entry(struct route_entry *route_e)
static void
sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath,
const struct hmap *learned_routes,
const struct sset *bound_ports,
const struct smap *bound_ports,
struct ovsdb_idl_txn *ovnsb_idl_txn,
struct ovsdb_idl_index *sbrec_learned_route_by_datapath,
struct ovsdb_idl_index *sbrec_port_binding_by_name)
Expand All @@ -116,8 +116,9 @@ sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath,
SBREC_LEARNED_ROUTE_FOR_EACH_EQUAL (sb_route, filter,
sbrec_learned_route_by_datapath) {
/* If the port is not local we don't care about it.
* Some other ovn-controller will handle it. */
if (!sset_contains(bound_ports,
* Some other ovn-controller will handle it.
* We may not use smap_get since the value might be validly NULL. */
if (!smap_get_node(bound_ports,
sb_route->logical_port->logical_port)) {
continue;
}
Expand All @@ -137,14 +138,22 @@ sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath,
learned_route->plen);
char *nexthop = normalize_v46(&learned_route->nexthop);

const char *logical_port_name;
SSET_FOR_EACH (logical_port_name, bound_ports) {
struct smap_node *port_node;
SMAP_FOR_EACH (port_node, bound_ports) {
/* The user specified an ifname, but we learned it on a different
* port. */
if (port_node->value && strcmp(port_node->value,
learned_route->ifname)) {
continue;
}

const struct sbrec_port_binding *logical_port =
lport_lookup_by_name(sbrec_port_binding_by_name,
logical_port_name);
port_node->key);
if (!logical_port) {
continue;
}

route_e = route_lookup_or_add(&sync_routes,
datapath,
logical_port, ip_prefix, nexthop);
Expand Down
12 changes: 9 additions & 3 deletions controller/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,16 @@ advertise_datapath_cleanup(struct advertise_datapath_entry *ad)
free(ar);
}
hmap_destroy(&ad->routes);
sset_destroy(&ad->bound_ports);
smap_destroy(&ad->bound_ports);
free(ad);
}

void
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);

const struct local_datapath *ld;
HMAP_FOR_EACH (ld, hmap_node, r_ctx_in->local_datapaths) {
if (!ld->n_peer_ports || ld->is_switch) {
Expand All @@ -102,7 +104,7 @@ route_run(struct route_ctx_in *r_ctx_in,
ad->key = ld->datapath->tunnel_key;
ad->db = ld->datapath;
hmap_init(&ad->routes);
sset_init(&ad->bound_ports);
smap_init(&ad->bound_ports);

/* This is a LR datapath, find LRPs with route exchange options
* that are bound locally. */
Expand All @@ -122,8 +124,12 @@ route_run(struct route_ctx_in *r_ctx_in,
"maintain-vrf", false);
ad->use_netns |= smap_get_bool(&repb->options,
"use-netns", false);
char *ifname = nullable_xstrdup(
smap_get(&repb->options,
"dynamic-routing-ifname"));
relevant_datapath = true;
sset_add(&ad->bound_ports, local_peer->logical_port);
smap_add_nocopy(&ad->bound_ports,
xstrdup(local_peer->logical_port), ifname);
}

if (!relevant_datapath) {
Expand Down
6 changes: 4 additions & 2 deletions controller/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <netinet/in.h>
#include "openvswitch/hmap.h"
#include "sset.h"
#include "smap.h"

struct hmap;
struct ovsdb_idl_index;
Expand Down Expand Up @@ -51,8 +52,9 @@ struct advertise_datapath_entry {
bool use_netns;
struct hmap routes;
/* the name of the port bindings locally bound for this datapath and
* running route exchange logic. */
struct sset bound_ports;
* running route exchange logic.
* The key is the port name and the value is the ifname if set. */
struct smap bound_ports;
};

struct advertise_route_entry {
Expand Down
25 changes: 23 additions & 2 deletions tests/system-ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -14920,6 +14920,17 @@ AT_CHECK_UNQUOTED([ovn-sbctl --columns ip_prefix,nexthop,logical_port --bare fin
$lp
])

# by setting a learning interface filter we will now forget about this route
check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \
options:dynamic-routing-ifname=thisdoesnotexist
check_row_count Learned_Route 0

# chaning it to "lo" will allow us to learn the route again
check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \
options:dynamic-routing-ifname=lo
check_row_count Learned_Route 1


OVS_APP_EXIT_AND_WAIT([ovn-controller])

as ovn-sb
Expand Down Expand Up @@ -15130,14 +15141,24 @@ check ip route add 233.252.0.0/24 via 192.168.10.10 dev lo onlink vrf ovnvrf1337
# for now we trigger a recompute as route watching is not yet implemented
check ovn-appctl -t ovn-controller inc-engine/recompute
check ovn-nbctl --wait=hv sync
check_row_count Learned_Route 2
check_row_count Learned_Route 1
lp=$(ovn-sbctl --bare --columns _uuid list port_binding internet-phys)
AT_CHECK_UNQUOTED([ovn-sbctl --columns ip_prefix,nexthop,logical_port --bare find Learned_Route logical_port=$lp], [0], [dnl
AT_CHECK_UNQUOTED([ovn-sbctl --columns ip_prefix,nexthop,logical_port --bare find Learned_Route], [0], [dnl
233.252.0.0/24
192.168.10.10
$lp
])

# by setting a learning interface filter we will now forget about this route
check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \
options:dynamic-routing-ifname=thisdoesnotexist
check_row_count Learned_Route 0

# chaning it to "lo" will allow us to learn the route again
check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \
options:dynamic-routing-ifname=lo
check_row_count Learned_Route 1

as ovn-sb
OVS_APP_EXIT_AND_WAIT([ovsdb-server])

Expand Down

0 comments on commit 5adb451

Please sign in to comment.