From 11102cba69b1ed73372cbfd60164d44ecf3b11f4 Mon Sep 17 00:00:00 2001 From: Susant Sahani <145210+ssahani@users.noreply.github.com> Date: Fri, 20 Apr 2018 15:08:39 +0530 Subject: [PATCH] networkd: add support to configure IPv6 MTU (#8664) This patch supports to configure IPv6 MTU. Closes #8632 --- man/systemd.network.xml | 6 ++++ src/network/networkd-link.c | 30 +++++++++++++++++++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 37 ++++++++++++++++++++++++ src/network/networkd-network.h | 5 +++- 5 files changed, 78 insertions(+), 1 deletion(-) 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 @@ -666,6 +666,12 @@ sections for more configuration options. + + IPv6MTUBytes= + Configures IPv6 maximum transmission unit (MTU). + An integer greater than or equal to 1280 bytes. Defaults to unset. + + Bridge= 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);