From: Yu Watanabe Date: Sun, 7 Jan 2024 01:35:07 +0000 (+0900) Subject: network/route-metric: introduce RouteMetric X-Git-Tag: v256-rc1~1204^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d32a520b095f7b795b37f32c059085c6d929bbc4;p=thirdparty%2Fsystemd.git network/route-metric: introduce RouteMetric Then, split out route metric handling from networkd-route.c to networkd-route-metric.c. No functional change, just refactoring and preparation for later commits. --- diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 8aee30e7266..4fada25a9c2 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -380,14 +380,14 @@ 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; + if (route->metric.mtu == 0) + route->metric.mtu = link->network->dhcp_route_mtu; + if (route->metric.quickack < 0) + route->metric.quickack = link->network->dhcp_quickack; + if (route->metric.initcwnd == 0) + route->metric.initcwnd = link->network->dhcp_initial_congestion_window; + if (route->metric.initrwnd == 0) + route->metric.initrwnd = link->network->dhcp_advertised_receive_window; 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 d972588b3ea..7b703bdfef3 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.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 369e205a99a..ee9e2448f35 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -208,12 +208,12 @@ 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; + if (route->metric.quickack < 0) + route->metric.quickack = link->network->ipv6_accept_ra_quickack; + if (route->metric.mtu == 0) + route->metric.mtu = mtu; + if (route->metric.hop_limit == 0) + route->metric.hop_limit = hop_limit; 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 a0fb40fd26d..4c74a5d792b 100644 --- a/src/network/networkd-route-metric.c +++ b/src/network/networkd-route-metric.c @@ -1,10 +1,161 @@ /* 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" +void route_metric_done(RouteMetric *metric) { + assert(metric); + + free(metric->tcp_congestion_control_algo); +} + +int route_metric_copy(const RouteMetric *src, RouteMetric *dest) { + assert(src); + assert(dest); + + dest->quickack = src->quickack; + dest->fast_open_no_cookie = src->fast_open_no_cookie; + dest->mtu = src->mtu; + dest->initcwnd = src->initcwnd; + dest->initrwnd = src->initrwnd; + dest->advmss = src->advmss; + dest->hop_limit = src->hop_limit; + dest->tcp_rto_usec = src->tcp_rto_usec; + + 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->initcwnd, state); + siphash24_compress_typesafe(metric->initrwnd, state); + siphash24_compress_typesafe(metric->advmss, state); +} + +int route_metric_compare_func(const RouteMetric *a, const RouteMetric *b) { + int r; + + assert(a); + assert(b); + + r = CMP(a->initcwnd, b->initcwnd); + if (r != 0) + return r; + + r = CMP(a->initrwnd, b->initrwnd); + if (r != 0) + return r; + + return CMP(a->advmss, b->advmss); +} + +int route_metric_set_netlink_message(const RouteMetric *metric, sd_netlink_message *m) { + int r; + + assert(metric); + assert(m); + + r = sd_netlink_message_open_container(m, RTA_METRICS); + if (r < 0) + return r; + + if (metric->mtu > 0) { + r = sd_netlink_message_append_u32(m, RTAX_MTU, metric->mtu); + if (r < 0) + return r; + } + + if (metric->initcwnd > 0) { + r = sd_netlink_message_append_u32(m, RTAX_INITCWND, metric->initcwnd); + if (r < 0) + return r; + } + + if (metric->initrwnd > 0) { + r = sd_netlink_message_append_u32(m, RTAX_INITRWND, metric->initrwnd); + if (r < 0) + return r; + } + + if (metric->quickack >= 0) { + r = sd_netlink_message_append_u32(m, RTAX_QUICKACK, metric->quickack); + if (r < 0) + return r; + } + + if (metric->fast_open_no_cookie >= 0) { + r = sd_netlink_message_append_u32(m, RTAX_FASTOPEN_NO_COOKIE, metric->fast_open_no_cookie); + if (r < 0) + return r; + } + + if (metric->advmss > 0) { + r = sd_netlink_message_append_u32(m, RTAX_ADVMSS, metric->advmss); + 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; + } + + if (metric->hop_limit > 0) { + r = sd_netlink_message_append_u32(m, RTAX_HOPLIMIT, metric->hop_limit); + if (r < 0) + return r; + } + + if (metric->tcp_rto_usec > 0) { + r = sd_netlink_message_append_u32(m, RTAX_RTO_MIN, DIV_ROUND_UP(metric->tcp_rto_usec, USEC_PER_MSEC)); + 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) { + int r; + + assert(metric); + assert(m); + + r = sd_netlink_message_enter_container(m, RTA_METRICS); + if (r == -ENODATA) + return 0; + if (r < 0) + return log_warning_errno(r, "rtnl: Could not enter RTA_METRICS container, ignoring: %m"); + + r = sd_netlink_message_read_u32(m, RTAX_INITCWND, &metric->initcwnd); + if (r < 0 && r != -ENODATA) + return log_warning_errno(r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); + + r = sd_netlink_message_read_u32(m, RTAX_INITRWND, &metric->initrwnd); + if (r < 0 && r != -ENODATA) + return log_warning_errno(r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); + + r = sd_netlink_message_read_u32(m, RTAX_ADVMSS, &metric->advmss); + if (r < 0 && r != -ENODATA) + return log_warning_errno(r, "rtnl: received route message with invalid advmss, ignoring: %m"); + + r = sd_netlink_message_exit_container(m); + if (r < 0) + return log_warning_errno(r, "rtnl: Could not exit from RTA_METRICS container, ignoring: %m"); + + return 0; +} + int config_parse_route_metric_mtu( const char *unit, const char *filename, @@ -36,7 +187,7 @@ int config_parse_route_metric_mtu( return 0; } - r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, AF_UNSPEC, rvalue, &route->mtu, userdata); + r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, AF_UNSPEC, rvalue, &route->metric.mtu, userdata); if (r <= 0) return r; @@ -77,7 +228,7 @@ int config_parse_route_metric_advmss( } if (isempty(rvalue)) { - route->advmss = 0; + route->metric.advmss = 0; TAKE_PTR(route); return 0; } @@ -95,7 +246,7 @@ int config_parse_route_metric_advmss( return 0; } - route->advmss = u; + route->metric.advmss = u; TAKE_PTR(route); return 0; @@ -134,7 +285,7 @@ int config_parse_route_metric_hop_limit( } if (isempty(rvalue)) { - route->hop_limit = 0; + route->metric.hop_limit = 0; TAKE_PTR(route); return 0; } @@ -151,7 +302,7 @@ int config_parse_route_metric_hop_limit( return 0; } - route->hop_limit = k; + route->metric.hop_limit = k; TAKE_PTR(route); return 0; @@ -228,9 +379,9 @@ int config_parse_route_metric_tcp_window( } if (streq(lvalue, "InitialCongestionWindow")) - d = &route->initcwnd; + d = &route->metric.initcwnd; else if (streq(lvalue, "InitialAdvertisedReceiveWindow")) - d = &route->initrwnd; + d = &route->metric.initrwnd; else assert_not_reached(); @@ -288,7 +439,7 @@ int config_parse_route_metric_tcp_rto( return 0; } - route->tcp_rto_usec = usec; + route->metric.tcp_rto_usec = usec; TAKE_PTR(route); return 0; @@ -333,9 +484,9 @@ int config_parse_route_metric_boolean( } if (streq(lvalue, "QuickAck")) - route->quickack = r; + route->metric.quickack = r; else if (streq(lvalue, "FastOpenNoCookie")) - route->fast_open_no_cookie = r; + route->metric.fast_open_no_cookie = r; else assert_not_reached(); @@ -375,7 +526,7 @@ 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); + rvalue, &route->metric.tcp_congestion_control_algo, userdata); if (r < 0) return r; diff --git a/src/network/networkd-route-metric.h b/src/network/networkd-route-metric.h index ba8b7bb6c8d..8f447f6e811 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 { + int quickack; + int fast_open_no_cookie; + uint32_t mtu; + uint32_t initcwnd; + uint32_t initrwnd; + uint32_t advmss; + uint32_t hop_limit; + char *tcp_congestion_control_algo; + usec_t tcp_rto_usec; +} RouteMetric; + +#define ROUTE_METRIC_NULL \ + ((const RouteMetric) { \ + .quickack = -1, \ + .fast_open_no_cookie = -1, \ + }) + +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_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 b8f1041dbdd..4fe2bd49bd7 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -35,8 +35,7 @@ int route_new(Route **ret) { .type = RTN_UNICAST, .table = RT_TABLE_MAIN, .lifetime_usec = USEC_INFINITY, - .quickack = -1, - .fast_open_no_cookie = -1, + .metric = ROUTE_METRIC_NULL, .gateway_onlink = -1, }; @@ -103,11 +102,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 +136,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 +214,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 +322,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 +1172,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 +1779,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 50753989679..33d1e643cc4 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;