diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 8aee30e726..64c84f4262 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -380,14 +380,18 @@ static int dhcp4_request_route(Route *in, Link *link) { route->priority = link->network->dhcp_route_metric; if (!route->table_set) route->table = link_get_dhcp4_route_table(link); - if (route->mtu == 0) - route->mtu = link->network->dhcp_route_mtu; - if (route->quickack < 0) - route->quickack = link->network->dhcp_quickack; - if (route->initcwnd == 0) - route->initcwnd = link->network->dhcp_initial_congestion_window; - if (route->initrwnd == 0) - route->initrwnd = link->network->dhcp_advertised_receive_window; + r = route_metric_set(&route->metric, RTAX_MTU, link->network->dhcp_route_mtu); + if (r < 0) + return r; + r = route_metric_set(&route->metric, RTAX_INITCWND, link->network->dhcp_initial_congestion_window); + if (r < 0) + return r; + r = route_metric_set(&route->metric, RTAX_INITRWND, link->network->dhcp_advertised_receive_window); + if (r < 0) + return r; + r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->dhcp_quickack); + if (r < 0) + return r; if (route_get(NULL, link, route, &existing) < 0) /* This is a new route. */ link->dhcp4_configured = false; diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index d972588b3e..e62e57b765 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -251,7 +251,7 @@ static int route_append_json(Route *route, JsonVariant **array) { JSON_BUILD_PAIR_UNSIGNED("Priority", route->priority), JSON_BUILD_PAIR_UNSIGNED("Table", route->table), JSON_BUILD_PAIR_STRING("TableString", table), - JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("MTU", route->mtu), + JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("MTU", route_metric_get(&route->metric, RTAX_MTU)), JSON_BUILD_PAIR_UNSIGNED("Preference", route->pref), JSON_BUILD_PAIR_UNSIGNED("Flags", route->flags), JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)), diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 369e205a99..43c0cd3ad4 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -208,12 +208,15 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) { ndisc_set_route_priority(link, route); if (!route->protocol_set) route->protocol = RTPROT_RA; - if (route->quickack < 0) - route->quickack = link->network->ipv6_accept_ra_quickack; - if (route->mtu == 0) - route->mtu = mtu; - if (route->hop_limit == 0) - route->hop_limit = hop_limit; + r = route_metric_set(&route->metric, RTAX_MTU, mtu); + if (r < 0) + return r; + r = route_metric_set(&route->metric, RTAX_HOPLIMIT, hop_limit); + if (r < 0) + return r; + r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->ipv6_accept_ra_quickack); + if (r < 0) + return r; is_new = route_get(NULL, link, route, NULL) < 0; diff --git a/src/network/networkd-route-metric.c b/src/network/networkd-route-metric.c index a0fb40fd26..67841cb67e 100644 --- a/src/network/networkd-route-metric.c +++ b/src/network/networkd-route-metric.c @@ -1,50 +1,201 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "alloc-util.h" +#include "netlink-util.h" #include "networkd-route.h" #include "networkd-route-metric.h" #include "parse-util.h" #include "string-util.h" -int config_parse_route_metric_mtu( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +void route_metric_done(RouteMetric *metric) { + assert(metric); - Network *network = userdata; - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; + free(metric->metrics); + free(metric->metrics_set); + free(metric->tcp_congestion_control_algo); +} + +int route_metric_copy(const RouteMetric *src, RouteMetric *dest) { + assert(src); + assert(dest); + + dest->n_metrics = src->n_metrics; + if (src->n_metrics > 0) { + assert(src->n_metrics != 1); + + dest->metrics = newdup(uint32_t, src->metrics, src->n_metrics); + if (!dest->metrics) + return -ENOMEM; + } else + dest->metrics = NULL; + + dest->n_metrics_set = src->n_metrics_set; + if (src->n_metrics_set > 0) { + assert(src->n_metrics_set != 1); + + dest->metrics_set = newdup(bool, src->metrics_set, src->n_metrics_set); + if (!dest->metrics_set) + return -ENOMEM; + } else + dest->metrics_set = NULL; + + return free_and_strdup(&dest->tcp_congestion_control_algo, src->tcp_congestion_control_algo); +} + +void route_metric_hash_func(const RouteMetric *metric, struct siphash *state) { + assert(metric); + + siphash24_compress_typesafe(metric->n_metrics, state); + siphash24_compress_safe(metric->metrics, sizeof(uint32_t) * metric->n_metrics, state); + siphash24_compress_string(metric->tcp_congestion_control_algo, state); +} + +int route_metric_compare_func(const RouteMetric *a, const RouteMetric *b) { int r; - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); + assert(a); + assert(b); - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); + r = memcmp_nn(a->metrics, a->n_metrics * sizeof(uint32_t), b->metrics, b->n_metrics * sizeof(uint32_t)); + if (r != 0) + return r; + + return strcmp_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); + + if (force) { + if (!GREEDY_REALLOC0(metric->metrics_set, attr + 1)) + return -ENOMEM; + + metric->metrics_set[attr] = true; + metric->n_metrics_set = MAX(metric->n_metrics_set, (size_t) (attr + 1)); + } else { + /* Do not override the values specified in conf parsers. */ + if (metric->n_metrics_set > attr && metric->metrics_set[attr]) + return 0; + } + + if (value != 0) { + if (!GREEDY_REALLOC0(metric->metrics, attr + 1)) + return -ENOMEM; + + metric->metrics[attr] = value; + metric->n_metrics = MAX(metric->n_metrics, (size_t) (attr + 1)); return 0; } - r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, AF_UNSPEC, rvalue, &route->mtu, userdata); - if (r <= 0) - return r; + if (metric->n_metrics <= attr) + return 0; - TAKE_PTR(route); + metric->metrics[attr] = 0; + + for (size_t i = metric->n_metrics; i > 0; i--) + if (metric->metrics[i-1] != 0) { + metric->n_metrics = i; + return 0; + } + + metric->n_metrics = 0; return 0; } -int config_parse_route_metric_advmss( +static void route_metric_unset(RouteMetric *metric, uint16_t attr) { + assert(metric); + + if (metric->n_metrics_set > attr) + metric->metrics_set[attr] = false; + + assert_se(route_metric_set_full(metric, attr, 0, /* force = */ false) >= 0); +} + +uint32_t route_metric_get(const RouteMetric *metric, uint16_t attr) { + assert(metric); + + if (metric->n_metrics <= attr) + return 0; + + return metric->metrics[attr]; +} + +int route_metric_set_netlink_message(const RouteMetric *metric, sd_netlink_message *m) { + int r; + + assert(metric); + assert(m); + + if (metric->n_metrics <= 0 && isempty(metric->tcp_congestion_control_algo)) + return 0; + + r = sd_netlink_message_open_container(m, RTA_METRICS); + if (r < 0) + return r; + + for (size_t i = 0; i < metric->n_metrics; i++) { + if (i == RTAX_CC_ALGO) + continue; + + if (metric->metrics[i] == 0) + continue; + + r = sd_netlink_message_append_u32(m, i, metric->metrics[i]); + if (r < 0) + return r; + } + + if (!isempty(metric->tcp_congestion_control_algo)) { + r = sd_netlink_message_append_string(m, RTAX_CC_ALGO, metric->tcp_congestion_control_algo); + if (r < 0) + return r; + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return r; + + return 0; +} + +int route_metric_read_netlink_message(RouteMetric *metric, sd_netlink_message *m) { + _cleanup_free_ void *data = NULL; + size_t len; + int r; + + assert(metric); + assert(m); + + r = sd_netlink_message_read_data(m, RTA_METRICS, &len, &data); + if (r == -ENODATA) + return 0; + if (r < 0) + return log_warning_errno(r, "rtnl: Could not read RTA_METRICS attribute, ignoring: %m"); + + for (struct rtattr *rta = data; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { + size_t rta_type = RTA_TYPE(rta); + + if (rta_type == RTAX_CC_ALGO) { + char *p = memdup_suffix0(RTA_DATA(rta), RTA_PAYLOAD(rta)); + if (!p) + return log_oom(); + + free_and_replace(metric->tcp_congestion_control_algo, p); + + } else { + if (RTA_PAYLOAD(rta) != sizeof(uint32_t)) + continue; + + r = route_metric_set(metric, rta_type, *(uint32_t*) RTA_DATA(rta)); + if (r < 0) + return log_oom(); + } + } + + return 0; +} + +static int config_parse_route_metric_advmss_impl( const char *unit, const char *filename, unsigned line, @@ -56,31 +207,11 @@ int config_parse_route_metric_advmss( void *data, void *userdata) { - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; - Network *network = userdata; + uint32_t *val = ASSERT_PTR(data); uint64_t u; int r; - assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); - - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); - return 0; - } - - if (isempty(rvalue)) { - route->advmss = 0; - TAKE_PTR(route); - return 0; - } r = parse_size(rvalue, 1024, &u); if (r < 0) { @@ -95,13 +226,11 @@ int config_parse_route_metric_advmss( return 0; } - route->advmss = u; - - TAKE_PTR(route); - return 0; + *val = (uint32_t) u; + return 1; } -int config_parse_route_metric_hop_limit( +static int config_parse_route_metric_hop_limit_impl( const char *unit, const char *filename, unsigned line, @@ -113,31 +242,10 @@ int config_parse_route_metric_hop_limit( void *data, void *userdata) { - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; - Network *network = userdata; - uint32_t k; + uint32_t k, *val = ASSERT_PTR(data); int r; - assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); - - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); - return 0; - } - - if (isempty(rvalue)) { - route->hop_limit = 0; - TAKE_PTR(route); - return 0; - } r = safe_atou32(rvalue, &k); if (r < 0) { @@ -151,10 +259,8 @@ int config_parse_route_metric_hop_limit( return 0; } - route->hop_limit = k; - - TAKE_PTR(route); - return 0; + *val = k; + return 1; } int config_parse_tcp_window( @@ -169,15 +275,10 @@ int config_parse_tcp_window( void *data, void *userdata) { - uint32_t *window = ASSERT_PTR(data); - uint32_t k; + uint32_t k, *val = ASSERT_PTR(data); int r; - assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); r = safe_atou32(rvalue, &k); if (r < 0) { @@ -191,11 +292,11 @@ int config_parse_tcp_window( return 0; } - *window = k; - return 0; + *val = k; + return 1; } -int config_parse_route_metric_tcp_window( +static int config_parse_route_metric_tcp_rto_impl( const char *unit, const char *filename, unsigned line, @@ -207,72 +308,11 @@ int config_parse_route_metric_tcp_window( void *data, void *userdata) { - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; - Network *network = userdata; - uint32_t *d; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); - return 0; - } - - if (streq(lvalue, "InitialCongestionWindow")) - d = &route->initcwnd; - else if (streq(lvalue, "InitialAdvertisedReceiveWindow")) - d = &route->initrwnd; - else - assert_not_reached(); - - r = config_parse_tcp_window(unit, filename, line, section, section_line, lvalue, ltype, rvalue, d, userdata); - if (r < 0) - return r; - - TAKE_PTR(route); - return 0; -} - -int config_parse_route_metric_tcp_rto( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = userdata; - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; + uint32_t *val = ASSERT_PTR(data); usec_t usec; int r; - assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); - - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); - return 0; - } r = parse_sec(rvalue, &usec); if (r < 0) { @@ -288,13 +328,11 @@ int config_parse_route_metric_tcp_rto( return 0; } - route->tcp_rto_usec = usec; - - TAKE_PTR(route); - return 0; + *val = (uint32_t) DIV_ROUND_UP(usec, USEC_PER_MSEC); + return 1; } -int config_parse_route_metric_boolean( +static int config_parse_route_metric_boolean_impl( const char *unit, const char *filename, unsigned line, @@ -306,24 +344,10 @@ int config_parse_route_metric_boolean( void *data, void *userdata) { - Network *network = userdata; - _cleanup_(route_free_or_set_invalidp) Route *route = NULL; + uint32_t *val = ASSERT_PTR(data); int r; - assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); - - r = route_new_static(network, filename, section_line, &route); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to allocate route, ignoring assignment: %m"); - return 0; - } r = parse_boolean(rvalue); if (r < 0) { @@ -332,17 +356,73 @@ int config_parse_route_metric_boolean( return 0; } - if (streq(lvalue, "QuickAck")) - route->quickack = r; - else if (streq(lvalue, "FastOpenNoCookie")) - route->fast_open_no_cookie = r; - else - assert_not_reached(); - - TAKE_PTR(route); - return 0; + *val = r; + return 1; } +#define DEFINE_CONFIG_PARSE_ROUTE_METRIC(name, parser) \ + int config_parse_route_metric_##name( \ + const char *unit, \ + const char *filename, \ + unsigned line, \ + const char *section, \ + unsigned section_line, \ + const char *lvalue, \ + int ltype, \ + const char *rvalue, \ + void *data, \ + void *userdata) { \ + \ + Network *network = ASSERT_PTR(userdata); \ + _cleanup_(route_free_or_set_invalidp) Route *route = NULL; \ + uint16_t attr_type = ltype; \ + int r; \ + \ + assert(filename); \ + assert(section); \ + assert(lvalue); \ + assert(rvalue); \ + \ + r = route_new_static(network, filename, section_line, &route); \ + if (r == -ENOMEM) \ + return log_oom(); \ + if (r < 0) { \ + log_syntax(unit, LOG_WARNING, filename, line, r, \ + "Failed to allocate route, ignoring assignment: %m"); \ + return 0; \ + } \ + \ + if (isempty(rvalue)) { \ + route_metric_unset(&route->metric, attr_type); \ + TAKE_PTR(route); \ + return 0; \ + } \ + \ + uint32_t k; \ + r = parser(unit, filename, line, section, section_line, \ + lvalue, /* ltype = */ 0, rvalue, \ + &k, userdata); \ + if (r <= 0) \ + return r; \ + \ + if (route_metric_set_full( \ + &route->metric, \ + attr_type, \ + k, \ + /* force = */ true) < 0) \ + return log_oom(); \ + \ + TAKE_PTR(route); \ + return 0; \ + } + +DEFINE_CONFIG_PARSE_ROUTE_METRIC(mtu, config_parse_mtu); +DEFINE_CONFIG_PARSE_ROUTE_METRIC(advmss, config_parse_route_metric_advmss_impl); +DEFINE_CONFIG_PARSE_ROUTE_METRIC(hop_limit, config_parse_route_metric_hop_limit_impl); +DEFINE_CONFIG_PARSE_ROUTE_METRIC(tcp_window, config_parse_tcp_window); +DEFINE_CONFIG_PARSE_ROUTE_METRIC(tcp_rto, config_parse_route_metric_tcp_rto_impl); +DEFINE_CONFIG_PARSE_ROUTE_METRIC(boolean, config_parse_route_metric_boolean_impl); + int config_parse_route_metric_tcp_congestion( const char *unit, const char *filename, @@ -355,15 +435,12 @@ int config_parse_route_metric_tcp_congestion( void *data, void *userdata) { - Network *network = userdata; + Network *network = ASSERT_PTR(userdata); _cleanup_(route_free_or_set_invalidp) Route *route = NULL; int r; assert(filename); - assert(section); - assert(lvalue); assert(rvalue); - assert(data); r = route_new_static(network, filename, section_line, &route); if (r == -ENOMEM) @@ -375,8 +452,8 @@ int config_parse_route_metric_tcp_congestion( } r = config_parse_string(unit, filename, line, section, section_line, lvalue, 0, - rvalue, &route->tcp_congestion_control_algo, userdata); - if (r < 0) + rvalue, &route->metric.tcp_congestion_control_algo, userdata); + if (r <= 0) return r; TAKE_PTR(route); diff --git a/src/network/networkd-route-metric.h b/src/network/networkd-route-metric.h index ba8b7bb6c8..1a3aaf2ae5 100644 --- a/src/network/networkd-route-metric.h +++ b/src/network/networkd-route-metric.h @@ -1,7 +1,40 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include +#include + +#include "sd-netlink.h" + #include "conf-parser.h" +#include "hash-funcs.h" + +typedef struct RouteMetric { + size_t n_metrics; /* maximum metric attr type with non-zero value */ + uint32_t *metrics; /* RTAX_*, except for RTAX_CC_ALGO */ + + size_t n_metrics_set; + bool *metrics_set; /* used by conf parsers */ + + char *tcp_congestion_control_algo; /* RTAX_CC_ALGO */ +} RouteMetric; + +#define ROUTE_METRIC_NULL ((const RouteMetric) {}) + +void route_metric_done(RouteMetric *metric); +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); + +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) { + return route_metric_set_full(metric, attr, value, false); +} +uint32_t route_metric_get(const RouteMetric *metric, uint16_t attr); + +int route_metric_set_netlink_message(const RouteMetric *metric, sd_netlink_message *m); +int route_metric_read_netlink_message(RouteMetric *metric, sd_netlink_message *message); CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_mtu); CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_advmss); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index b8f1041dbd..0553a66343 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -35,8 +35,6 @@ int route_new(Route **ret) { .type = RTN_UNICAST, .table = RT_TABLE_MAIN, .lifetime_usec = USEC_INFINITY, - .quickack = -1, - .fast_open_no_cookie = -1, .gateway_onlink = -1, }; @@ -103,11 +101,9 @@ Route *route_free(Route *route) { set_remove(route->manager->routes, route); ordered_set_free_with_destructor(route->multipath_routes, multipath_route_free); - + route_metric_done(&route->metric); sd_event_source_disable_unref(route->expire); - free(route->tcp_congestion_control_algo); - return mfree(route); } @@ -139,11 +135,7 @@ static void route_hash_func(const Route *route, struct siphash *state) { siphash24_compress_typesafe(route->protocol, state); siphash24_compress_typesafe(route->scope, state); siphash24_compress_typesafe(route->type, state); - - siphash24_compress_typesafe(route->initcwnd, state); - siphash24_compress_typesafe(route->initrwnd, state); - - siphash24_compress_typesafe(route->advmss, state); + route_metric_hash_func(&route->metric, state); siphash24_compress_typesafe(route->nexthop_id, state); break; @@ -221,15 +213,7 @@ static int route_compare_func(const Route *a, const Route *b) { if (r != 0) return r; - r = CMP(a->initcwnd, b->initcwnd); - if (r != 0) - return r; - - r = CMP(a->initrwnd, b->initrwnd); - if (r != 0) - return r; - - r = CMP(a->advmss, b->advmss); + r = route_metric_compare_func(&a->metric, &b->metric); if (r != 0) return r; @@ -337,10 +321,10 @@ int route_dup(const Route *src, Route **ret) { dest->link = NULL; dest->manager = NULL; dest->multipath_routes = NULL; + dest->metric = ROUTE_METRIC_NULL; dest->expire = NULL; - dest->tcp_congestion_control_algo = NULL; - r = free_and_strdup(&dest->tcp_congestion_control_algo, src->tcp_congestion_control_algo); + r = route_metric_copy(&src->metric, &dest->metric); if (r < 0) return r; @@ -1187,65 +1171,8 @@ static int route_configure(const Route *route, uint32_t lifetime_sec, Link *link return r; } - r = sd_netlink_message_open_container(m, RTA_METRICS); - if (r < 0) - return r; - - if (route->mtu > 0) { - r = sd_netlink_message_append_u32(m, RTAX_MTU, route->mtu); - if (r < 0) - return r; - } - - if (route->initcwnd > 0) { - r = sd_netlink_message_append_u32(m, RTAX_INITCWND, route->initcwnd); - if (r < 0) - return r; - } - - if (route->initrwnd > 0) { - r = sd_netlink_message_append_u32(m, RTAX_INITRWND, route->initrwnd); - if (r < 0) - return r; - } - - if (route->quickack >= 0) { - r = sd_netlink_message_append_u32(m, RTAX_QUICKACK, route->quickack); - if (r < 0) - return r; - } - - if (route->fast_open_no_cookie >= 0) { - r = sd_netlink_message_append_u32(m, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie); - if (r < 0) - return r; - } - - if (route->advmss > 0) { - r = sd_netlink_message_append_u32(m, RTAX_ADVMSS, route->advmss); - if (r < 0) - return r; - } - - if (!isempty(route->tcp_congestion_control_algo)) { - r = sd_netlink_message_append_string(m, RTAX_CC_ALGO, route->tcp_congestion_control_algo); - if (r < 0) - return r; - } - - if (route->hop_limit > 0) { - r = sd_netlink_message_append_u32(m, RTAX_HOPLIMIT, route->hop_limit); - if (r < 0) - return r; - } - - if (route->tcp_rto_usec > 0) { - r = sd_netlink_message_append_u32(m, RTAX_RTO_MIN, DIV_ROUND_UP(route->tcp_rto_usec, USEC_PER_MSEC)); - if (r < 0) - return r; - } - - r = sd_netlink_message_close_container(m); + /* metrics */ + r = route_metric_set_netlink_message(&route->metric, m); if (r < 0) return r; @@ -1851,36 +1778,9 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma return 0; } - r = sd_netlink_message_enter_container(message, RTA_METRICS); - if (r < 0 && r != -ENODATA) { - log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container, ignoring: %m"); + /* metrics */ + if (route_metric_read_netlink_message(&tmp->metric, message) < 0) return 0; - } - if (r >= 0) { - r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTAX_ADVMSS, &tmp->advmss); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route message with invalid advmss, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_exit_container(message); - if (r < 0) { - log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container, ignoring: %m"); - return 0; - } - } r = sd_netlink_message_read_data(message, RTA_MULTIPATH, &rta_len, &rta_multipath); if (r < 0 && r != -ENODATA) { diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 5075398967..33d1e643cc 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -36,8 +36,6 @@ struct Route { int family; int gw_family; uint32_t gw_weight; - int quickack; - int fast_open_no_cookie; unsigned char dst_prefixlen; unsigned char src_prefixlen; @@ -47,17 +45,13 @@ struct Route { unsigned char tos; uint32_t priority; /* note that ip(8) calls this 'metric' */ uint32_t table; - uint32_t mtu; - uint32_t initcwnd; - uint32_t initrwnd; - uint32_t advmss; - uint32_t hop_limit; - char *tcp_congestion_control_algo; unsigned char pref; unsigned flags; int gateway_onlink; /* Only used in conf parser and route_section_verify(). */ uint32_t nexthop_id; - usec_t tcp_rto_usec; + + /* metrics (RTA_METRICS) */ + RouteMetric metric; bool scope_set:1; bool table_set:1; diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 1d201528ac..d8a2c47209 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -1088,6 +1088,7 @@ int config_parse_string( void *userdata) { char **s = ASSERT_PTR(data); + int r; assert(filename); assert(lvalue); @@ -1095,7 +1096,7 @@ int config_parse_string( if (isempty(rvalue)) { *s = mfree(*s); - return 0; + return 1; } if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_SAFE) && !string_is_safe(rvalue)) { @@ -1116,7 +1117,11 @@ int config_parse_string( return 0; } - return free_and_strdup_warn(s, empty_to_null(rvalue)); + r = free_and_strdup_warn(s, empty_to_null(rvalue)); + if (r < 0) + return r; + + return 1; } int config_parse_dns_name(