diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-04-21 13:51:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-21 13:51:31 +0200 |
commit | b67bbfef14293cb4a1c46573df7a68e53100832d (patch) | |
tree | d6319cd195e71472251ca327efb4d1e776b9f648 | |
parent | units: fix repart conditions to run if definitions exist in /sysroot + /sysusr (diff) | |
parent | test-network: update test for RouteMetric= (diff) | |
download | systemd-b67bbfef14293cb4a1c46573df7a68e53100832d.tar.xz systemd-b67bbfef14293cb4a1c46573df7a68e53100832d.zip |
Merge pull request #19344 from yuwata/network-route-metric-19028
network: add RouteMetric= setting in [Address] and more
-rw-r--r-- | man/systemd.network.xml | 47 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.c | 10 | ||||
-rw-r--r-- | src/network/networkd-address.c | 47 | ||||
-rw-r--r-- | src/network/networkd-address.h | 2 | ||||
-rw-r--r-- | src/network/networkd-dhcp-common.c | 10 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 1 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 2 | ||||
-rw-r--r-- | src/network/networkd-ipv4ll.c | 1 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 8 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 6 | ||||
-rw-r--r-- | src/network/networkd-network.c | 2 | ||||
-rw-r--r-- | src/network/networkd-network.h | 7 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 39 | ||||
-rw-r--r-- | src/network/networkd-radv.h | 2 | ||||
-rw-r--r-- | src/network/networkd-route.c | 4 | ||||
-rw-r--r-- | test/fuzz/fuzz-network-parser/directives.network | 4 | ||||
-rwxr-xr-x | test/test-network/systemd-networkd-tests.py | 48 |
17 files changed, 187 insertions, 53 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 554d1f663c..4024252b39 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1100,6 +1100,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> </listitem> </varlistentry> <varlistentry> + <term><varname>RouteMetric=</varname></term> + <listitem> + <para>The metric of the prefix route, which is pointing to the subnet of the configured IP + address, taking the configured prefix length into account. Takes an unsigned integer in the + range 0…4294967295. When unset or set to 0, the kernel's default value is used. This + setting will be ignored when <varname>AddPrefixRoute=</varname> is false.</para> + </listitem> + </varlistentry> + <varlistentry> <term><varname>HomeAddress=</varname></term> <listitem> <para>Takes a boolean. Designates this address the "home address" as defined in @@ -1421,7 +1430,8 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <varlistentry> <term><varname>Metric=</varname></term> <listitem> - <para>The metric of the route (an unsigned integer).</para> + <para>The metric of the route. Takes an unsigned integer in the range 0…4294967295. + Defaluts to unset, and the kernel's default will be used.</para> </listitem> </varlistentry> <varlistentry> @@ -1837,7 +1847,8 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <varlistentry> <term><varname>RouteMetric=</varname></term> <listitem> - <para>Set the routing metric for routes specified by the DHCP server. Defaults to 1024.</para> + <para>Set the routing metric for routes specified by the DHCP server. Takes an unsigned + integer in the range 0…4294967295. Defaults to 1024.</para> </listitem> </varlistentry> @@ -1978,13 +1989,6 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> </varlistentry> <varlistentry> - <term><varname>RouteMetric=</varname></term> - <listitem> - <para>Set the routing metric for routes specified by the DHCP server. Defaults to 1024.</para> - </listitem> - </varlistentry> - - <varlistentry> <term><varname>RapidCommit=</varname></term> <listitem> <para>Takes a boolean. The DHCPv6 client can obtain configuration parameters from a DHCPv6 server through @@ -2158,6 +2162,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <para>As in the [Address] section, but defaults to true.</para> </listitem> </varlistentry> + + <varlistentry> + <term><varname>RouteMetric=</varname></term> + <listitem> + <para>The metric of the route to the delegated prefix subnet. Takes an unsigned integer in + the range 0…4294967295. When unset or set to 0, the kernel's default value is used.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> @@ -2208,6 +2220,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> </varlistentry> <varlistentry> + <term><varname>RouteMetric=</varname></term> + <listitem> + <para>Set the routing metric for the routes received in the Router Advertisement. Takes an + unsigned integer in the range 0…4294967295. Defaults to 1024.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><varname>UseAutonomousPrefix=</varname></term> <listitem> <para>When true (the default), the autonomous prefix received in the Router Advertisement will be used and take @@ -2564,6 +2584,15 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para> <listitem><para>Takes a boolean. When true, adds an address from the prefix. Default to false. </para></listitem> </varlistentry> + + <varlistentry> + <term><varname>RouteMetric=</varname></term> + <listitem> + <para>The metric of the prefix route. Takes an unsigned integer in the range 0…4294967295. + When unset or set to 0, the kernel's default value is used. This setting is ignored when + <varname>Assign=</varname> is false.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index ed7b9a8cd1..5ae15d67bc 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -683,13 +683,13 @@ static const NLType rtnl_address_types[] = { [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, - [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFA_ANYCAST] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, -/* - [IFA_ANYCAST], - [IFA_MULTICAST], -*/ + [IFA_MULTICAST] = { .type = NETLINK_TYPE_IN_ADDR }, [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [IFA_RT_PRIORITY] = { .type = NETLINK_TYPE_U32 }, + [IFA_TARGET_NETNSID] = { .type = NETLINK_TYPE_S32 }, }; static const NLTypeSystem rtnl_address_type_system = { diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 58b089901b..e589fff150 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -918,6 +918,10 @@ int address_configure( if (r < 0) return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); + r = sd_netlink_message_append_u32(req, IFA_RT_PRIORITY, address->route_metric); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_RT_PRIORITY attribute: %m"); + k = address_add(link, address, &a); if (k < 0) return log_link_error_errno(link, k, "Could not add address: %m"); @@ -1091,6 +1095,7 @@ int link_set_addresses(Link *link) { return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); address->family = AF_INET6; + address->route_metric = p->route_metric; r = static_address_configure(address, link); if (r < 0) return r; @@ -1801,6 +1806,48 @@ int config_parse_address_scope( return 0; } +int config_parse_address_route_metric( + 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_(address_free_or_set_invalidp) Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to allocate new address, ignoring assignment: %m"); + return 0; + } + + r = safe_atou32(rvalue, &n->route_metric); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Could not parse %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + int config_parse_duplicate_address_detection( const char *unit, const char *filename, diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index e3ca868c2e..58f44cd4cd 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -28,6 +28,7 @@ typedef struct Address { unsigned char prefixlen; unsigned char scope; uint32_t flags; + uint32_t route_metric; /* route metric for prefix route */ char *label; int set_broadcast; @@ -83,6 +84,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_label); CONFIG_PARSER_PROTOTYPE(config_parse_lifetime); CONFIG_PARSER_PROTOTYPE(config_parse_address_flags); CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); +CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric); CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection); #define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u" diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index f09f0ee50e..bb0b204467 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -332,14 +332,14 @@ int config_parse_dhcp_route_metric( if (streq_ptr(section, "DHCPv4")) { network->dhcp_route_metric = metric; network->dhcp_route_metric_set = true; - } else if (streq_ptr(section, "DHCPv6")) { - network->dhcp6_route_metric = metric; - network->dhcp6_route_metric_set = true; + } else if (STRPTR_IN_SET(section, "DHCPv6", "IPv6AcceptRA")) { + network->ipv6_accept_ra_route_metric = metric; + network->ipv6_accept_ra_route_metric_set = true; } else { /* [DHCP] section */ if (!network->dhcp_route_metric_set) network->dhcp_route_metric = metric; - if (!network->dhcp6_route_metric_set) - network->dhcp6_route_metric = metric; + if (!network->ipv6_accept_ra_route_metric_set) + network->ipv6_accept_ra_route_metric = metric; } return 0; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 2157057121..85b909e576 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -893,6 +893,7 @@ static int dhcp4_update_address(Link *link, bool announce) { if (prefixlen <= 30) addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link)); + addr->route_metric = link->network->dhcp_route_metric; /* allow reusing an existing address and simply update its lifetime * in case it already exists */ diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index f5e66b9457..6f3c02d44d 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -284,6 +284,7 @@ static int dhcp6_set_pd_route(Link *link, const union in_addr_union *prefix, con route->dst = *prefix; route->dst_prefixlen = 64; route->protocol = RTPROT_DHCP; + route->priority = link->network->dhcp6_pd_route_metric; r = route_configure(route, link, dhcp6_pd_route_handler, &ret); if (r < 0) @@ -399,6 +400,7 @@ static int dhcp6_set_pd_address( address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_valid = lifetime_valid; SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address); + address->route_metric = link->network->dhcp6_pd_route_metric; r = address_configure(address, link, dhcp6_pd_address_handler, &ret); if (r < 0) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 7aad2131fd..5390c53799 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -91,6 +91,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { ll_addr->prefixlen = 16; ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen); ll_addr->scope = RT_SCOPE_LINK; + ll_addr->route_metric = IPV4LL_ROUTE_METRIC; r = address_configure(ll_addr, link, ipv4ll_address_handler, NULL); if (r < 0) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 7a975f3a91..b02f67c770 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -530,7 +530,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route->family = AF_INET6; route->table = table; - route->priority = link->network->dhcp6_route_metric; + route->priority = link->network->ipv6_accept_ra_route_metric; route->protocol = RTPROT_RA; route->pref = preference; route->gw_family = AF_INET6; @@ -554,7 +554,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { if (!route_gw->table_set) route_gw->table = table; if (!route_gw->priority_set) - route_gw->priority = link->network->dhcp6_route_metric; + route_gw->priority = link->network->ipv6_accept_ra_route_metric; if (!route_gw->protocol_set) route_gw->protocol = RTPROT_RA; if (!route_gw->pref_set) @@ -814,7 +814,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { route->family = AF_INET6; route->table = link_get_ipv6_accept_ra_route_table(link); - route->priority = link->network->dhcp6_route_metric; + route->priority = link->network->ipv6_accept_ra_route_metric; route->protocol = RTPROT_RA; route->flags = RTM_F_PREFIX; route->dst_prefixlen = prefixlen; @@ -899,7 +899,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { route->family = AF_INET6; route->table = link_get_ipv6_accept_ra_route_table(link); - route->priority = link->network->dhcp6_route_metric; + route->priority = link->network->ipv6_accept_ra_route_metric; route->protocol = RTPROT_RA; route->pref = preference; route->gw = gateway; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 4fc368547c..568c34f51b 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -146,6 +146,7 @@ Address.AddPrefixRoute, config_parse_address_flags, Address.AutoJoin, config_parse_address_flags, IFA_F_MCAUTOJOIN, 0 Address.DuplicateAddressDetection, config_parse_duplicate_address_detection, 0, 0 Address.Scope, config_parse_address_scope, 0, 0 +Address.RouteMetric, config_parse_address_route_metric, 0, 0 IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 IPv6AddressLabel.Label, config_parse_address_label, 0, 0 Neighbor.Address, config_parse_neighbor_address, 0, 0 @@ -243,13 +244,13 @@ DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0 DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_without_ra) DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options) -DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0 IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) IPv6AcceptRA.UseDomains, config_parse_ipv6_accept_ra_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0 +IPv6AcceptRA.RouteMetric, config_parse_dhcp_route_metric, 0, 0 IPv6AcceptRA.RouterAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_router) IPv6AcceptRA.RouterDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_router) IPv6AcceptRA.PrefixAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_prefix) @@ -308,6 +309,7 @@ DHCPv6PrefixDelegation.Announce, config_parse_bool, DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign) DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_manage_temporary_address) DHCPv6PrefixDelegation.Token, config_parse_dhcp6_pd_token, 0, offsetof(Network, dhcp6_pd_token) +DHCPv6PrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp6_pd_route_metric) IPv6SendRA.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed) IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) @@ -323,6 +325,7 @@ IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0 +IPv6Prefix.RouteMetric, config_parse_prefix_metric, 0, 0 IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 LLDP.MUDURL, config_parse_lldp_mud, 0, 0 @@ -491,6 +494,7 @@ DHCP.RapidCommit, config_parse_bool, DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, 0 DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) +DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0 IPv6AcceptRA.DenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix) IPv6AcceptRA.BlackList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix) TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 320d33645e..6c81f2cca7 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -321,7 +321,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp6_use_hostname = true, .dhcp6_use_ntp = true, .dhcp6_rapid_commit = true, - .dhcp6_route_metric = DHCP_ROUTE_METRIC, .dhcp6_pd = -1, .dhcp6_pd_announce = true, @@ -379,6 +378,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv6_accept_ra_use_autonomous_prefix = true, .ipv6_accept_ra_use_onlink_prefix = true, .ipv6_accept_ra_route_table = RT_TABLE_MAIN, + .ipv6_accept_ra_route_metric = DHCP_ROUTE_METRIC, .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES, .can_triple_sampling = -1, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 16a445982c..db0fbbdf1a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -170,8 +170,6 @@ struct Network { DHCPUseDomains dhcp6_use_domains; bool dhcp6_use_domains_set; uint8_t dhcp6_pd_length; - uint32_t dhcp6_route_metric; - bool dhcp6_route_metric_set; char *dhcp6_mudurl; char **dhcp6_user_class; char **dhcp6_vendor_class; @@ -221,6 +219,7 @@ struct Network { bool dhcp6_pd_assign; bool dhcp6_pd_manage_temporary_address; int64_t dhcp6_pd_subnet_id; + uint32_t dhcp6_pd_route_metric; union in_addr_union dhcp6_pd_token; /* Bridge Support */ @@ -277,10 +276,12 @@ struct Network { bool ipv6_accept_ra_use_onlink_prefix; bool active_slave; bool primary_slave; - bool ipv6_accept_ra_route_table_set; DHCPUseDomains ipv6_accept_ra_use_domains; IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client; uint32_t ipv6_accept_ra_route_table; + bool ipv6_accept_ra_route_table_set; + uint32_t ipv6_accept_ra_route_metric; + bool ipv6_accept_ra_route_metric_set; Set *ndisc_deny_listed_router; Set *ndisc_allow_listed_router; Set *ndisc_deny_listed_prefix; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 19f75e01da..52c9afcc5e 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -382,6 +382,45 @@ int config_parse_prefix_assign( return 0; } +int config_parse_prefix_metric( + 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_(prefix_free_or_set_invalidp) Prefix *p = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return log_oom(); + + r = safe_atou32(rvalue, &p->route_metric); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + TAKE_PTR(p); + + return 0; +} + int config_parse_route_prefix( const char *unit, const char *filename, diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 73d2f24545..f6efd32697 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -33,6 +33,7 @@ typedef struct Prefix { sd_radv_prefix *radv_prefix; bool assign; + uint32_t route_metric; } Prefix; typedef struct RoutePrefix { @@ -64,6 +65,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix_metric); CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index a74541a6c9..9ed30d69ed 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -628,11 +628,11 @@ static void log_route_debug(const Route *route, const char *str, const Link *lin (void) route_protocol_full_to_string_alloc(route->protocol, &proto); log_link_debug(link, - "%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s, nexthop: %"PRIu32, + "%s route: dst: %s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s, nexthop: %"PRIu32", priority: %"PRIu32, str, strna(dst), strna(src), strna(gw), strna(prefsrc), strna(scope), strna(table), strna(proto), strna(route_type_to_string(route->type)), - route->nexthop_id); + route->nexthop_id, route->priority); } } diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 158f0ffad1..e5acc5d67d 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -147,6 +147,7 @@ Announce= Assign= ManageTemporaryAddress= Token= +RouteMetric= [Route] Destination= Protocol= @@ -236,6 +237,7 @@ PreferredLifetimeSec= AddressAutoconfiguration= ValidLifetimeSec= Assign= +RouteMetric= [IPv6RoutePrefix] Route= LifetimeSec= @@ -270,6 +272,7 @@ ManageTemporaryAddress= Broadcast= Peer= Label= +RouteMetric= [RoutingPolicyRule] Table= IncomingInterface= @@ -317,6 +320,7 @@ Prefix= [IPv6AcceptRA] UseDomains= RouteTable= +RouteMetric= UseDNS= DHCPv6Client= UseAutonomousPrefix= diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 9d86818610..148ff6e8c0 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3911,7 +3911,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) @@ -4014,7 +4014,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip address show dev veth99 scope global') print(output) self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99') - self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99') + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic veth99') output = check_output('ip route show dev veth99') print(output) @@ -4044,7 +4044,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip route show dev veth99') print(output) - self.assertRegex(output, 'metric 24') + self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output) + self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output) + self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output) def test_dhcp_client_reassign_static_routes_ipv4(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', @@ -4056,7 +4058,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip address show dev veth99 scope global') print(output) - self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') output = check_output('ip route show dev veth99') print(output) @@ -4201,7 +4203,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') output = check_output('ip address show dev veth99 scope global') @@ -4244,7 +4246,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') print('## ip -d link show dev vrf99') @@ -4255,14 +4257,14 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print('## ip address show vrf vrf99') output = check_output('ip address show vrf vrf99') print(output) - self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 .* scope link') print('## ip address show dev veth99') output = check_output('ip address show dev veth99') print(output) - self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 .* scope link') @@ -4338,9 +4340,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') print('Wait for the dynamic address to be expired') time.sleep(130) @@ -4353,9 +4355,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') search_words_in_dnsmasq_log('DHCPOFFER', show_all=True) @@ -4375,13 +4377,13 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -6 address show dev veth99 scope link') self.assertRegex(output, r'inet6 .* scope link') output = check_output('ip -4 address show dev veth99 scope global dynamic') - self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99') + self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99') output = check_output('ip -4 address show dev veth99 scope link') - self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link') + self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link') start_dnsmasq(lease_time='2m') - self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic', ipv='-4') - self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4') + self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4') + self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4') def test_dhcp_client_route_remove_on_renew(self): copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', @@ -4395,7 +4397,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -4 address show dev veth99 scope global dynamic') print(output) - self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') address1=None for line in output.splitlines(): if 'brd 192.168.5.255 scope global dynamic veth99' in line: @@ -4415,10 +4417,10 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): output = check_output('ip -4 address show dev veth99 scope global dynamic') print(output) - self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') address2=None for line in output.splitlines(): - if 'brd 192.168.5.255 scope global dynamic veth99' in line: + if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line: address2 = line.split()[1].split('/')[0] break @@ -4440,7 +4442,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4458,7 +4460,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4476,7 +4478,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) @@ -4494,7 +4496,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.wait_online(['veth99:routable', 'veth-peer:routable']) # link become 'routable' when at least one protocol provide an valid address. - self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') time.sleep(3) |