mirror of
https://github.com/systemd/systemd.git
synced 2025-03-21 02:50:18 +03:00
network/route: remove existing route if some property conflict with requested ones
Fixes #28853.
This commit is contained in:
parent
e09b758876
commit
7027cdbd79
@ -63,6 +63,28 @@ int route_metric_compare_func(const RouteMetric *a, const RouteMetric *b) {
|
||||
return strcmp_ptr(a->tcp_congestion_control_algo, b->tcp_congestion_control_algo);
|
||||
}
|
||||
|
||||
bool route_metric_can_update(const RouteMetric *a, const RouteMetric *b, bool expiration_by_kernel) {
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
/* If the kernel has expiration timer for the route, then only MTU can be updated. */
|
||||
|
||||
if (!expiration_by_kernel)
|
||||
return route_metric_compare_func(a, b) == 0;
|
||||
|
||||
if (a->n_metrics != b->n_metrics)
|
||||
return false;
|
||||
|
||||
for (size_t i = 1; i < a->n_metrics; i++) {
|
||||
if (i != RTAX_MTU)
|
||||
continue;
|
||||
if (a->metrics[i] != b->metrics[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return streq_ptr(a->tcp_congestion_control_algo, b->tcp_congestion_control_algo);
|
||||
}
|
||||
|
||||
int route_metric_set_full(RouteMetric *metric, uint16_t attr, uint32_t value, bool force) {
|
||||
assert(metric);
|
||||
|
||||
|
@ -26,6 +26,7 @@ int route_metric_copy(const RouteMetric *src, RouteMetric *dest);
|
||||
|
||||
void route_metric_hash_func(const RouteMetric *metric, struct siphash *state);
|
||||
int route_metric_compare_func(const RouteMetric *a, const RouteMetric *b);
|
||||
bool route_metric_can_update(const RouteMetric *a, const RouteMetric *b, bool expiration_by_kernel);
|
||||
|
||||
int route_metric_set_full(RouteMetric *metric, uint16_t attr, uint32_t value, bool force);
|
||||
static inline int route_metric_set(RouteMetric *metric, uint16_t attr, uint32_t value) {
|
||||
|
@ -1305,6 +1305,43 @@ static bool route_by_kernel(const Route *route) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool route_can_update(const Route *existing, const Route *requesting) {
|
||||
assert(existing);
|
||||
assert(requesting);
|
||||
|
||||
if (route_compare_func(existing, requesting) != 0)
|
||||
return false;
|
||||
|
||||
switch (existing->family) {
|
||||
case AF_INET:
|
||||
if (existing->nexthop.weight != requesting->nexthop.weight)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case AF_INET6:
|
||||
if (existing->protocol != requesting->protocol)
|
||||
return false;
|
||||
if (existing->type != requesting->type)
|
||||
return false;
|
||||
if (existing->flags != requesting->flags)
|
||||
return false;
|
||||
if (!in6_addr_equal(&existing->prefsrc.in6, &requesting->prefsrc.in6))
|
||||
return false;
|
||||
if (existing->pref != requesting->pref)
|
||||
return false;
|
||||
if (existing->expiration_managed_by_kernel && requesting->lifetime_usec != USEC_INFINITY)
|
||||
return false; /* We cannot disable expiration timer in the kernel. */
|
||||
if (!route_metric_can_update(&existing->metric, &requesting->metric, existing->expiration_managed_by_kernel))
|
||||
return false;
|
||||
if (existing->nexthop.weight != requesting->nexthop.weight)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static int link_unmark_route(Link *link, const Route *route, const RouteNextHop *nh) {
|
||||
_cleanup_(route_unrefp) Route *tmp = NULL;
|
||||
Route *existing;
|
||||
@ -1324,6 +1361,9 @@ static int link_unmark_route(Link *link, const Route *route, const RouteNextHop
|
||||
if (route_get(link->manager, tmp, &existing) < 0)
|
||||
return 0;
|
||||
|
||||
if (!route_can_update(existing, tmp))
|
||||
return 0;
|
||||
|
||||
route_unmark(existing);
|
||||
return 1;
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ int route_remove_and_cancel(Route *route, Manager *manager);
|
||||
|
||||
int route_get(Manager *manager, const Route *route, Route **ret);
|
||||
|
||||
bool route_can_update(const Route *existing, const Route *requesting);
|
||||
|
||||
int link_drop_routes(Link *link, bool foreign);
|
||||
static inline int link_drop_static_routes(Link *link) {
|
||||
return link_drop_routes(link, false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user