Skip to content

Commit

Permalink
nl_l3: ignore duplicated link routes from FRR
Browse files Browse the repository at this point in the history
Signed-off-by: Jonas Gorski <[email protected]>
  • Loading branch information
KanjiMonster committed Oct 6, 2023
1 parent 43c3a02 commit b0a2ae6
Showing 1 changed file with 59 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/netlink/nl_l3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,37 @@ int nl_l3::add_l3_unicast_route(rtnl_route *r, bool update_route) {
return -ENOTSUP;
}

// FRR may occationally install link-local routes again with a different
// priority. Since we cannot handle multiple routes with different
// priorities/metrics yet, ignore the duplicated route.
if (rtnl_route_get_priority(r) > 0 &&
rtnl_route_get_protocol(r) != RTPROT_KERNEL) {
nl_route_query rq;

auto route = rq.query_route(rtnl_route_get_dst(r));

if (route) {
bool duplicate = false;
VLOG(2) << __FUNCTION__ << ": got route " << OBJ_CAST(route)
<< " for dst " << OBJ_CAST(rtnl_route_get_dst(r));
if (rtnl_route_get_protocol(route) == RTPROT_KERNEL &&
nl_addr_cmp_prefix(rtnl_route_get_dst(r),
rtnl_route_get_dst(route)) == 0) {
// we already have a kernel route for the same dst
duplicate = true;
}
nl_object_put(OBJ_CAST(route));

// there already is a kernel route, so ignore this one
if (duplicate)
return 0;
} else {
// huh?
VLOG(2) << __FUNCTION__ << ": no route for dst "
<< OBJ_CAST(rtnl_route_get_dst(r));
}
}

std::deque<struct rtnl_neigh *> neighs;
std::deque<nh_stub> unresolved_nh;
int rv = get_neighbours_of_route(r, &neighs, &unresolved_nh);
Expand Down Expand Up @@ -1906,6 +1937,34 @@ int nl_l3::del_l3_unicast_route(rtnl_route *r, bool keep_route) {
if (vrf_id == MAIN_ROUTING_TABLE)
vrf_id = 0;

if (rtnl_route_get_priority(r) > 0 &&
rtnl_route_get_protocol(r) != RTPROT_KERNEL) {
nl_route_query rq;

auto route = rq.query_route(rtnl_route_get_dst(r));

if (route) {
bool duplicate = false;
VLOG(2) << __FUNCTION__ << ": got route " << OBJ_CAST(route)
<< " for dst " << OBJ_CAST(rtnl_route_get_dst(r));
if (rtnl_route_get_protocol(route) == RTPROT_KERNEL &&
nl_addr_cmp_prefix(rtnl_route_get_dst(r),
rtnl_route_get_dst(route)) == 0) {
// we have a kernel route for the same dst
duplicate = true;
}
nl_object_put(OBJ_CAST(route));

// there is still a kernel route, so ignore this one
if (duplicate)
return 0;
} else {
// no route anymore, this is fine
VLOG(2) << __FUNCTION__ << ": no route for dst "
<< OBJ_CAST(rtnl_route_get_dst(r));
}
}

if (!keep_route) {
rv = del_l3_unicast_route(dst, vrf_id);
if (rv < 0) {
Expand Down

0 comments on commit b0a2ae6

Please sign in to comment.