]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/route: move several conf parsers to networkd-route-metric.c and networkd...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Jan 2024 20:08:40 +0000 (05:08 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 6 Jan 2024 16:39:58 +0000 (01:39 +0900)
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.

src/network/meson.build
src/network/networkd-network-gperf.gperf
src/network/networkd-route-metric.c [new file with mode: 0644]
src/network/networkd-route-metric.h [new file with mode: 0644]
src/network/networkd-route-nexthop.c [new file with mode: 0644]
src/network/networkd-route-nexthop.h [new file with mode: 0644]
src/network/networkd-route.c
src/network/networkd-route.h

index 5f06948752beb292f70a7f7bb2eddb695dc98b6d..2708b3a5bf4aa39974fe0e72fea3970aa399d515 100644 (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',
index ab11047f7e807266233aad2a6adeb5179bcd00d0..455ca8ee226fc51420d8e288d978988338b09dbb 100644 (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
diff --git a/src/network/networkd-route-metric.c b/src/network/networkd-route-metric.c
new file mode 100644 (file)
index 0000000..194e53b
--- /dev/null
@@ -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;
+}
diff --git a/src/network/networkd-route-metric.h b/src/network/networkd-route-metric.h
new file mode 100644 (file)
index 0000000..a6ae425
--- /dev/null
@@ -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);
diff --git a/src/network/networkd-route-nexthop.c b/src/network/networkd-route-nexthop.c
new file mode 100644 (file)
index 0000000..fbb8ee2
--- /dev/null
@@ -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;
+}
diff --git a/src/network/networkd-route-nexthop.h b/src/network/networkd-route-nexthop.h
new file mode 100644 (file)
index 0000000..ae07696
--- /dev/null
@@ -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);
index 7c8461abb73cc24fba975a93a8562018e5cac6fb..b8f1041dbdd409a635232cec09f5a2f77058b655 100644 (file)
@@ -45,7 +45,7 @@ int route_new(Route **ret) {
         return 0;
 }
 
-static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
+int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
         _cleanup_(config_section_freep) ConfigSection *n = NULL;
         _cleanup_(route_freep) Route *route = NULL;
         int r;
@@ -2264,59 +2264,6 @@ int config_parse_route_scope(
         return 0;
 }
 
-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_route_table(
                 const char *unit,
                 const char *filename,
@@ -2360,7 +2307,7 @@ int config_parse_route_table(
         return 0;
 }
 
-int config_parse_route_boolean(
+int config_parse_route_gateway_onlink(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2398,14 +2345,7 @@ int config_parse_route_boolean(
                 return 0;
         }
 
-        if (STR_IN_SET(lvalue, "GatewayOnLink", "GatewayOnlink"))
-                route->gateway_onlink = r;
-        else if (streq(lvalue, "QuickAck"))
-                route->quickack = r;
-        else if (streq(lvalue, "FastOpenNoCookie"))
-                route->fast_open_no_cookie = r;
-        else
-                assert_not_reached();
+        route->gateway_onlink = r;
 
         TAKE_PTR(route);
         return 0;
@@ -2528,463 +2468,6 @@ int config_parse_route_type(
         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_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;
-}
-
-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_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_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_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_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;
-}
-
 static int route_section_verify(Route *route, Network *network) {
         if (section_is_invalid(route->section))
                 return -EINVAL;
index 2e7f6290630dcb6fe51a6ec3ebf3e3e40ddbefe3..5075398967954e60c57f2f523be1cadd18b0c28e 100644 (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);