diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 32cfb207e0..e2d698285e 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1148,6 +1148,24 @@ DuplicateAddressDetection=none
+
+ MPLSRouting=
+
+ Control whether Multi-protocol Label Switching (MPLS) routing is enabled on this interface.
+ This configures /proc/sys/net/mpls/conf/INTERFACE/input.
+ Takes a boolean. Defaults to unset, and the kernel's default will be used.
+
+ Note, systemd-networkd does not load any required
+ kernel modules for MPLS. To enable the feature, mpls_router kernel module must
+ be loaded before systemd-networkd.service is started. Consider adding the
+ kernel module to
+ modules-load.d5.
+
+
+
+
+
+
KeepMaster=
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index ab7f2553ec..dc462b690c 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -151,6 +151,7 @@ Network.ProxyARP, config_parse_tristate,
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter)
Network.MulticastIGMPVersion, config_parse_ipv4_force_igmp_version, 0, offsetof(Network, ipv4_force_igmp_version)
+Network.MPLSRouting, config_parse_tristate, 0, offsetof(Network, mpls_input)
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 89dcf4f6c4..3ecddff129 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -482,6 +482,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.proxy_arp_pvlan = -1,
.ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
.ipv4_force_igmp_version = _IPV4_FORCE_IGMP_VERSION_INVALID,
+ .mpls_input = -1,
.ndisc = -1,
.ndisc_use_redirect = true,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 03e3108623..b61914ea7a 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -343,6 +343,7 @@ struct Network {
IPv4ForceIgmpVersion ipv4_force_igmp_version;
int ipv6_proxy_ndp;
Set *ipv6_proxy_ndp_addresses;
+ int mpls_input;
/* NDisc support */
int ndisc;
diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c
index 10a35bc44b..fb2864eb4f 100644
--- a/src/network/networkd-sysctl.c
+++ b/src/network/networkd-sysctl.c
@@ -243,7 +243,7 @@ static bool link_is_configured_for_family(Link *link, int family) {
/* CAN devices do not support IP layer. Most of the functions below are never called for CAN devices,
* but link_set_ipv6_mtu() may be called after setting interface MTU, and warn about the failure. For
* safety, let's unconditionally check if the interface is not a CAN device. */
- if (IN_SET(family, AF_INET, AF_INET6) && link->iftype == ARPHRD_CAN)
+ if (IN_SET(family, AF_INET, AF_INET6, AF_MPLS) && link->iftype == ARPHRD_CAN)
return false;
if (family == AF_INET6 && !socket_ipv6_is_supported())
@@ -671,6 +671,19 @@ static int link_set_ipv4_promote_secondaries(Link *link) {
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "promote_secondaries", true, manager_get_sysctl_shadow(link->manager));
}
+static int link_set_mpls_input(Link *link) {
+ assert(link);
+ assert(link->manager);
+
+ if (!link_is_configured_for_family(link, AF_MPLS))
+ return 0;
+
+ if (link->network->mpls_input < 0)
+ return 0;
+
+ return sysctl_write_ip_property_boolean(AF_MPLS, link->ifname, "input", link->network->mpls_input > 0, manager_get_sysctl_shadow(link->manager));
+}
+
int link_set_sysctl(Link *link) {
int r;
@@ -743,6 +756,10 @@ int link_set_sysctl(Link *link) {
if (r < 0)
log_link_warning_errno(link, r, "Cannot enable promote_secondaries for interface, ignoring: %m");
+ r = link_set_mpls_input(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set MPLS input, ignoring: %m");
+
return 0;
}