network/route-nexthop: introduce route_adjust_nexthops() and route_nexthops_needs_adjust()

These are not used in this commit, but will be used later.
Preparation for later commits.
This commit is contained in:
Yu Watanabe
2024-01-19 10:23:14 +09:00
parent 413ea20ab3
commit acc3fc9e5f
2 changed files with 113 additions and 0 deletions
+111
View File
@@ -200,6 +200,117 @@ int route_nexthops_copy(const Route *src, const RouteNextHop *nh, Route *dest) {
return 0;
}
static bool multipath_routes_needs_adjust(const Route *route) {
assert(route);
RouteNextHop *nh;
ORDERED_SET_FOREACH(nh, route->nexthops)
if (route->nexthop.ifindex == 0)
return true;
return false;
}
bool route_nexthops_needs_adjust(const Route *route) {
assert(route);
if (route->nexthop_id != 0)
/* At this stage, the nexthop may not be configured, or may be under reconfiguring.
* Hence, we cannot know if the nexthop is blackhole or not. */
return route->type != RTN_BLACKHOLE;
if (route_type_is_reject(route))
return false;
if (ordered_set_isempty(route->nexthops))
return route->nexthop.ifindex == 0;
return multipath_routes_needs_adjust(route);
}
static bool route_nexthop_set_ifindex(RouteNextHop *nh, Link *link) {
assert(nh);
assert(link);
assert(link->manager);
if (nh->ifindex > 0) {
nh->ifname = mfree(nh->ifname);
return false;
}
/* If an interface name is specified, use it. Otherwise, use the interface that requests this route. */
if (nh->ifname && link_get_by_name(link->manager, nh->ifname, &link) < 0)
return false;
nh->ifindex = link->ifindex;
nh->ifname = mfree(nh->ifname);
return true; /* updated */
}
int route_adjust_nexthops(Route *route, Link *link) {
int r;
assert(route);
assert(link);
assert(link->manager);
/* When an IPv4 route has nexthop id and the nexthop type is blackhole, even though kernel sends
* RTM_NEWROUTE netlink message with blackhole type, kernel's internal route type fib_rt_info::type
* may not be blackhole. Thus, we cannot know the internal value. Moreover, on route removal, the
* matching is done with the hidden value if we set non-zero type in RTM_DELROUTE message. So,
* here let's set route type to BLACKHOLE when the nexthop is blackhole. */
if (route->nexthop_id != 0) {
NextHop *nexthop;
r = nexthop_is_ready(link->manager, route->nexthop_id, &nexthop);
if (r <= 0)
return r; /* r == 0 means the nexthop is under (re-)configuring.
* We cannot use the currently remembered information. */
if (!nexthop->blackhole)
return false;
if (route->type == RTN_BLACKHOLE)
return false;
route->type = RTN_BLACKHOLE;
return true; /* updated */
}
if (route_type_is_reject(route))
return false;
if (ordered_set_isempty(route->nexthops))
return route_nexthop_set_ifindex(&route->nexthop, link);
if (!multipath_routes_needs_adjust(route))
return false;
_cleanup_ordered_set_free_ OrderedSet *nexthops = NULL;
for (;;) {
_cleanup_(route_nexthop_freep) RouteNextHop *nh = NULL;
nh = ordered_set_steal_first(route->nexthops);
if (!nh)
break;
(void) route_nexthop_set_ifindex(nh, link);
r = ordered_set_ensure_put(&nexthops, &route_nexthop_hash_ops, nh);
if (r == -EEXIST)
continue; /* Duplicated? Let's drop the nexthop. */
if (r < 0)
return r;
assert(r > 0);
TAKE_PTR(nh);
}
ordered_set_free(route->nexthops);
route->nexthops = TAKE_PTR(nexthops);
return true; /* updated */
}
int route_nexthop_get_link(Manager *manager, Link *link, const RouteNextHop *nh, Link **ret) {
assert(manager);
assert(nh);
+2
View File
@@ -35,6 +35,8 @@ void route_nexthops_hash_func(const Route *route, struct siphash *state);
int route_nexthops_compare_func(const Route *a, const Route *b);
int route_nexthops_copy(const Route *src, const RouteNextHop *nh, Route *dest);
bool route_nexthops_needs_adjust(const Route *route);
int route_adjust_nexthops(Route *route, Link *link);
int route_nexthop_get_link(Manager *manager, Link *link, const RouteNextHop *nh, Link **ret);
int route_nexthops_is_ready_to_configure(const Route *route, Link *link);