summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.network.xml6
-rw-r--r--src/network/networkd-link.c30
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c37
-rw-r--r--src/network/networkd-network.h5
5 files changed, 78 insertions, 1 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index b71e197f11..a45bbe26ea 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -667,6 +667,12 @@
</para></listitem>
</varlistentry>
<varlistentry>
+ <term><varname>IPv6MTUBytes=</varname></term>
+ <listitem><para>Configures IPv6 maximum transmission unit (MTU).
+ An integer greater than or equal to 1280 bytes. Defaults to unset.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>Bridge=</varname></term>
<listitem>
<para>The name of the bridge to add the link to. See
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index d2ec6ce9d6..e51ea88213 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2469,6 +2469,32 @@ static int link_set_ipv6_hop_limit(Link *link) {
return 0;
}
+static int link_set_ipv6_mtu(Link *link) {
+ char buf[DECIMAL_STR_MAX(unsigned) + 1];
+ const char *p = NULL;
+ int r;
+
+ /* Make this a NOP if IPv6 is not available */
+ if (!socket_ipv6_is_supported())
+ return 0;
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (link->network->ipv6_mtu == 0)
+ return 0;
+
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/mtu");
+
+ xsprintf(buf, "%u", link->network->ipv6_mtu);
+
+ r = write_string_file(p, buf, 0);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
+
+ return 0;
+}
+
static int link_drop_foreign_config(Link *link) {
Address *address;
Route *route;
@@ -2623,6 +2649,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_set_ipv6_mtu(link);
+ if (r < 0)
+ return r;
+
if (link_ipv4ll_enabled(link)) {
r = ipv4ll_configure(link);
if (r < 0)
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 281ba657b3..ba5c5db70d 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -69,6 +69,7 @@ Network.IPv6AcceptRouterAdvertisements, config_parse_tristate,
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit)
Network.IPv6ProxyNDP, config_parse_tristate, 0, offsetof(Network, ipv6_proxy_ndp)
+Network.IPv6MTUBytes, config_parse_ipv6_mtu, 0, 0
Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 3873de567d..17d6a62983 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -247,6 +247,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->arp = -1;
network->ipv6_accept_ra_use_dns = true;
network->ipv6_accept_ra_route_table = RT_TABLE_MAIN;
+ network->ipv6_mtu = 0;
dropin_dirname = strjoina(network->name, ".network.d");
@@ -1416,6 +1417,42 @@ int config_parse_dhcp_route_table(const char *unit,
return 0;
}
+int config_parse_ipv6_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 = data;
+ uint32_t mtu;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = safe_atou32(rvalue, &mtu);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 MTU, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ if (mtu < IPV6_MIN_MTU) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 MTU for interface. Allowed minimum MTU is 1280 bytes, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ network->ipv6_mtu = mtu;
+
+ return 0;
+}
+
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index d07db44177..c34788d620 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -33,6 +33,8 @@
#define BRIDGE_VLAN_BITMAP_MAX 4096
#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
+#define IPV6_MIN_MTU 1280
+
typedef enum DHCPClientIdentifier {
DHCP_CLIENT_ID_MAC,
DHCP_CLIENT_ID_DUID,
@@ -199,6 +201,7 @@ struct Network {
int ipv6_hop_limit;
int ipv6_proxy_ndp;
int proxy_arp;
+ unsigned ipv6_mtu;
bool ipv6_accept_ra_use_dns;
bool active_slave;
@@ -291,7 +294,7 @@ int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsign
int config_parse_lldp_mode(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);
int config_parse_dhcp_route_table(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);
int config_parse_ntp(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);
-
+int config_parse_ipv6_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);
/* Legacy IPv4LL support */
int config_parse_ipv4ll(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);