diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 1c26609917..126accaca9 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -4420,6 +4420,15 @@ ServerAddress=192.168.0.1/24
+
+ Preference=
+
+ Specifies the preference of the route option. Takes one of high,
+ medium, or low. Defaults to medium.
+
+
+
+
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 9a25be666b..bf91f2c4c1 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -408,7 +408,7 @@ IPv6SendRA.ReachableTimeSec, config_parse_router_uint32_msec_use
IPv6SendRA.RetransmitSec, config_parse_router_uint32_msec_usec, 0, offsetof(Network, router_retransmit_usec)
IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
-IPv6SendRA.RouterPreference, config_parse_router_preference, 0, 0
+IPv6SendRA.RouterPreference, config_parse_router_preference, 0, offsetof(Network, router_preference)
IPv6SendRA.HopLimit, config_parse_uint8, 0, offsetof(Network, router_hop_limit)
IPv6SendRA.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns)
IPv6SendRA.DNS, config_parse_radv_dns, 0, 0
@@ -429,6 +429,7 @@ IPv6Prefix.RouteMetric, config_parse_prefix_metric,
IPv6Prefix.Token, config_parse_prefix_token, 0, 0
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
+IPv6RoutePrefix.Preference, config_parse_route_prefix_preference, 0, 0
IPv6PREF64Prefix.Prefix, config_parse_pref64_prefix, 0, 0
IPv6PREF64Prefix.LifetimeSec, config_parse_pref64_prefix_lifetime, 0, 0
LLDP.MUDURL, config_parse_mud_url, 0, offsetof(Network, lldp_mudurl)
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
index deb37c4850..fbf87091a3 100644
--- a/src/network/networkd-radv.c
+++ b/src/network/networkd-radv.c
@@ -1134,6 +1134,37 @@ int config_parse_route_prefix_lifetime(
return 0;
}
+int config_parse_route_prefix_preference(
+ 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_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
+ Network *network = ASSERT_PTR(userdata);
+ int r;
+
+ assert(filename);
+
+ r = route_prefix_new_static(network, filename, section_line, &p);
+ if (r < 0)
+ return log_oom();
+
+ r = config_parse_router_preference(unit, filename, line, section, section_line,
+ lvalue, ltype, rvalue, &p->route.preference, NULL);
+ if (r <= 0)
+ return r;
+
+ TAKE_PTR(p);
+ return 0;
+}
+
int config_parse_pref64_prefix(
const char *unit,
const char *filename,
@@ -1511,25 +1542,18 @@ int config_parse_router_preference(
void *data,
void *userdata) {
- Network *network = userdata;
+ uint8_t *preference = ASSERT_PTR(data);
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (streq(rvalue, "high"))
- network->router_preference = SD_NDISC_PREFERENCE_HIGH;
- else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
- network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
+ if (isempty(rvalue) || STR_IN_SET(rvalue, "medium", "normal", "default"))
+ *preference = SD_NDISC_PREFERENCE_MEDIUM;
+ else if (streq(rvalue, "high"))
+ *preference = SD_NDISC_PREFERENCE_HIGH;
else if (streq(rvalue, "low"))
- network->router_preference = SD_NDISC_PREFERENCE_LOW;
+ *preference = SD_NDISC_PREFERENCE_LOW;
else
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid router preference, ignoring assignment: %s", rvalue);
+ return log_syntax_parse_error(unit, filename, line, 0, lvalue, rvalue);
- return 0;
+ return 1;
}
int config_parse_router_home_agent_lifetime(
diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h
index afde1fcfe2..3f0a374632 100644
--- a/src/network/networkd-radv.h
+++ b/src/network/networkd-radv.h
@@ -86,6 +86,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix_lifetime);
CONFIG_PARSER_PROTOTYPE(config_parse_router_home_agent_lifetime);
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index b6549b96b3..a151e00a2f 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -6494,6 +6494,22 @@ class NetworkdRATests(unittest.TestCase, Utilities):
networkctl_reload()
self.check_router_preference('01', 100, 'high', 300, 'low')
+ # Use route options with preference to configure default routes.
+ with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
+ f.write('LifetimeSec=1200\nPreference=low\n')
+ with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
+ f.write('LifetimeSec=1200\nPreference=high\n')
+ networkctl_reload()
+ self.check_router_preference('01', 300, 'low', 100, 'high')
+
+ # Set zero lifetime again to the route options.
+ with open(os.path.join(network_unit_dir, '25-veth-router-high.network'), mode='a', encoding='utf-8') as f:
+ f.write('LifetimeSec=0\n')
+ with open(os.path.join(network_unit_dir, '25-veth-router-low.network'), mode='a', encoding='utf-8') as f:
+ f.write('LifetimeSec=0\n')
+ networkctl_reload()
+ self.check_router_preference('01', 100, 'high', 300, 'low')
+
def _test_ndisc_vs_static_route(self, manage_foreign_nexthops):
if not manage_foreign_nexthops:
copy_networkd_conf_dropin('networkd-manage-foreign-nexthops-no.conf')