diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 554d1f663c..3812350820 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1099,6 +1099,15 @@ IPv6Token=prefixstable:2002:da8:1::
Defaults to global.
+
+ RouteMetric=
+
+ 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 AddPrefixRoute= is false.
+
+
HomeAddress=
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 58b089901b..145bc25190 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");
@@ -1801,6 +1805,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-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 4fc368547c..0e3361b052 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
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 158f0ffad1..dbb6effa95 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -270,6 +270,7 @@ ManageTemporaryAddress=
Broadcast=
Peer=
Label=
+RouteMetric=
[RoutingPolicyRule]
Table=
IncomingInterface=