network/route: move several conf parsers to networkd-route-metric.c and networkd-route-nexthop.c

This also split config_parse_route_boolean() into two:
for GatewayOnline= and boolean route metrics.

No functional change, just refactoring and preparation for later commits.
This commit is contained in:
Yu Watanabe
2024-01-06 05:08:40 +09:00
parent f48e52bda8
commit df8767fc8d
8 changed files with 608 additions and 533 deletions

View File

@@ -67,8 +67,10 @@ sources = files(
'networkd-nexthop.c',
'networkd-queue.c',
'networkd-radv.c',
'networkd-route-util.c',
'networkd-route.c',
'networkd-route-metric.c',
'networkd-route-nexthop.c',
'networkd-route-util.c',
'networkd-routing-policy-rule.c',
'networkd-setlink.c',
'networkd-speed-meter.c',

View File

@@ -193,8 +193,8 @@ Route.Scope, config_parse_route_scope,
Route.PreferredSource, config_parse_preferred_src, 0, 0
Route.Table, config_parse_route_table, 0, 0
Route.MTUBytes, config_parse_route_mtu, AF_UNSPEC, 0
Route.GatewayOnLink, config_parse_route_boolean, 0, 0
Route.GatewayOnlink, config_parse_route_boolean, 0, 0
Route.GatewayOnLink, config_parse_route_gateway_onlink, 0, 0
Route.GatewayOnlink, config_parse_route_gateway_onlink, 0, 0
Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0
Route.Protocol, config_parse_route_protocol, 0, 0
Route.Type, config_parse_route_type, 0, 0

View File

@@ -0,0 +1,394 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "networkd-route.h"
#include "networkd-route-metric.h"
#include "parse-util.h"
#include "string-util.h"
int config_parse_route_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) {
Network *network = 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)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &route->mtu, userdata);
if (r <= 0)
return r;
TAKE_PTR(route);
return 0;
}
int config_parse_tcp_advmss(
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) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
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) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
if (u == 0 || u > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
route->advmss = u;
TAKE_PTR(route);
return 0;
}
int config_parse_route_hop_limit(
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) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
uint32_t k;
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) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse per route hop limit, ignoring assignment: %s", rvalue);
return 0;
}
if (k > 255) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified per route hop limit \"%s\" is too large, ignoring assignment: %m", rvalue);
return 0;
}
if (k == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid per route hop limit \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
route->hop_limit = k;
TAKE_PTR(route);
return 0;
}
int config_parse_tcp_window(
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) {
uint32_t *window = ASSERT_PTR(data);
uint32_t k;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (k >= 1024) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (k == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
*window = k;
return 0;
}
int config_parse_route_tcp_window(
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) {
_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_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;
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) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse route TCP retransmission timeout (RTO), ignoring assignment: %s", rvalue);
return 0;
}
if (!timestamp_is_set(usec) ||
DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Route TCP retransmission timeout (RTO) must be in the range 0…%"PRIu32"ms, ignoring assignment: %s", UINT32_MAX, rvalue);
return 0;
}
route->tcp_rto_usec = usec;
TAKE_PTR(route);
return 0;
}
int config_parse_route_boolean(
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;
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) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=\"%s\", ignoring assignment: %m", lvalue, rvalue);
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;
}
int config_parse_tcp_congestion(
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;
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 = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
rvalue, &route->tcp_congestion_control_algo, userdata);
if (r < 0)
return r;
TAKE_PTR(route);
return 0;
}

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
CONFIG_PARSER_PROTOTYPE(config_parse_route_hop_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_rto);
CONFIG_PARSER_PROTOTYPE(config_parse_route_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_congestion);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);

View File

@@ -0,0 +1,182 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/nexthop.h>
#include "alloc-util.h"
#include "extract-word.h"
#include "netlink-util.h"
#include "networkd-route.h"
#include "networkd-route-nexthop.h"
#include "parse-util.h"
#include "string-util.h"
int config_parse_route_nexthop(
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 id;
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->nexthop_id = 0;
TAKE_PTR(route);
return 0;
}
r = safe_atou32(rvalue, &id);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
if (id == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
route->nexthop_id = id;
TAKE_PTR(route);
return 0;
}
int config_parse_multipath_route(
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) {
_cleanup_(multipath_route_freep) MultipathRoute *m = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_free_ char *word = NULL;
Network *network = userdata;
union in_addr_union a;
int family, r;
const char *p;
char *dev;
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->multipath_routes = ordered_set_free_with_destructor(route->multipath_routes, multipath_route_free);
TAKE_PTR(route);
return 0;
}
m = new0(MultipathRoute, 1);
if (!m)
return log_oom();
p = rvalue;
r = extract_first_word(&p, &word, NULL, 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route option, ignoring assignment: %s", rvalue);
return 0;
}
dev = strchr(word, '@');
if (dev) {
*dev++ = '\0';
r = parse_ifindex(dev);
if (r > 0)
m->ifindex = r;
else {
if (!ifname_valid_full(dev, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid interface name '%s' in %s=, ignoring: %s", dev, lvalue, rvalue);
return 0;
}
m->ifname = strdup(dev);
if (!m->ifname)
return log_oom();
}
}
r = in_addr_from_string_auto(word, &family, &a);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
return 0;
}
m->gateway.address = a;
m->gateway.family = family;
if (!isempty(p)) {
r = safe_atou32(p, &m->weight);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
/* ip command takes weight in the range 1…255, while kernel takes the value in the
* range 0…254. MultiPathRoute= setting also takes weight in the same range which ip
* command uses, then networkd decreases by one and stores it to match the range which
* kernel uses. */
if (m->weight == 0 || m->weight > 256) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
m->weight--;
}
r = ordered_set_ensure_put(&route->multipath_routes, NULL, m);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to store multipath route, ignoring assignment: %m");
return 0;
}
TAKE_PTR(m);
TAKE_PTR(route);
return 0;
}

View File

@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,8 @@
#include "conf-parser.h"
#include "in-addr-util.h"
#include "networkd-link.h"
#include "networkd-route-metric.h"
#include "networkd-route-nexthop.h"
#include "networkd-util.h"
typedef struct Manager Manager;
@@ -80,6 +82,7 @@ struct Route {
extern const struct hash_ops route_hash_ops;
int route_new(Route **ret);
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret);
Route *route_free(Route *route);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_free);
int route_dup(const Route *src, Route **ret);
@@ -119,16 +122,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_destination);
CONFIG_PARSER_PROTOTYPE(config_parse_route_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_route_scope);
CONFIG_PARSER_PROTOTYPE(config_parse_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_route_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_route_gateway_onlink);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_hop_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_rto);
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_congestion);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);