174 lines
7.3 KiB
Diff
174 lines
7.3 KiB
Diff
From 715b55d9253c25bd6c463a2959eb33f12e9ecd1b Mon Sep 17 00:00:00 2001
|
|
From: Susant Sahani <ssahani@users.noreply.github.com>
|
|
Date: Thu, 21 Apr 2016 06:04:13 +0530
|
|
Subject: [PATCH] networkd: bump MTU to 1280 for interfaces which have IPv6
|
|
enabled (#3077)
|
|
|
|
IPv6 protocol requires a minimum MTU of 1280 bytes on the interface.
|
|
This fixes #3046.
|
|
|
|
Introduce helper link_ipv6_enabled() to figure out whether IPV6 is enabled.
|
|
Introduce network_has_static_ipv6_addresses() to find out if any static
|
|
ipv6 address configured.
|
|
If IPv6 is not configured on any interface that is SLAAC, DHCPv6 and static
|
|
IPv6 addresses not configured, then IPv6 will be automatically disabled for that
|
|
interface, that is we write "1" to /proc/sys/net/ipv6/conf//disable_ipv6.
|
|
(cherry picked from commit 439689c6ec48faba67565562d75701d5736567e7)
|
|
Related: rhbug#1352378
|
|
---
|
|
man/systemd.network.xml | 2 ++
|
|
src/basic/missing.h | 4 ++++
|
|
src/network/networkd-link.c | 50 +++++++++++++++++++++++++++++++++++++++++-
|
|
src/network/networkd-network.c | 13 +++++++++++
|
|
src/network/networkd-network.h | 2 ++
|
|
5 files changed, 70 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
|
|
index f88751b672..e3df1b3d14 100644
|
|
--- a/man/systemd.network.xml
|
|
+++ b/man/systemd.network.xml
|
|
@@ -202,6 +202,8 @@
|
|
<para>The maximum transmission unit in bytes to set for the
|
|
device. The usual suffixes K, M, G, are supported and are
|
|
understood to the base of 1024.</para>
|
|
+ <para>Note that if IPv6 is enabled on the interface, and the MTU is chosen
|
|
+ below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
diff --git a/src/basic/missing.h b/src/basic/missing.h
|
|
index 36b060496a..048b3fbc42 100644
|
|
--- a/src/basic/missing.h
|
|
+++ b/src/basic/missing.h
|
|
@@ -912,6 +912,10 @@ static inline int setns(int fd, int nstype) {
|
|
#define IPV6_UNICAST_IF 76
|
|
#endif
|
|
|
|
+#ifndef IPV6_MIN_MTU
|
|
+#define IPV6_MIN_MTU 1280
|
|
+#endif
|
|
+
|
|
#ifndef IFF_MULTI_QUEUE
|
|
#define IFF_MULTI_QUEUE 0x100
|
|
#endif
|
|
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
|
|
index 692c0bf63d..a6039dd3b2 100644
|
|
--- a/src/network/networkd-link.c
|
|
+++ b/src/network/networkd-link.c
|
|
@@ -88,6 +88,15 @@ bool link_ipv6ll_enabled(Link *link) {
|
|
return link->network->link_local & ADDRESS_FAMILY_IPV6;
|
|
}
|
|
|
|
+static bool link_ipv6_enabled(Link *link) {
|
|
+ assert(link);
|
|
+
|
|
+ if (!socket_ipv6_is_supported())
|
|
+ return false;
|
|
+
|
|
+ return link_dhcp6_enabled(link) || link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
|
|
+}
|
|
+
|
|
bool link_lldp_enabled(Link *link) {
|
|
if (link->flags & IFF_LOOPBACK)
|
|
return false;
|
|
@@ -167,6 +176,31 @@ static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
|
|
return link->network->ipv6_privacy_extensions;
|
|
}
|
|
|
|
+static int link_enable_ipv6(Link *link) {
|
|
+ const char *p = NULL;
|
|
+ bool disabled;
|
|
+ int r;
|
|
+
|
|
+ if (link->flags & IFF_LOOPBACK)
|
|
+ return 0;
|
|
+
|
|
+ disabled = !link_ipv6_enabled(link);
|
|
+
|
|
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6");
|
|
+
|
|
+ r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
|
|
+ if (r < 0)
|
|
+ log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m", disabled ? "disable" : "enable", link->ifname);
|
|
+ else {
|
|
+ if (disabled)
|
|
+ log_link_info(link, "IPv6 disabled for interface: %m");
|
|
+ else
|
|
+ log_link_info(link, "IPv6 enabled for interface: %m");
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
void link_update_operstate(Link *link) {
|
|
LinkOperationalState operstate;
|
|
assert(link);
|
|
@@ -1382,7 +1416,21 @@ static int link_up(Link *link) {
|
|
return log_link_error_errno(link, r, "Could not set MAC address: %m");
|
|
}
|
|
|
|
+ /* If IPv6 not configured (no static IPv6 address and neither DHCPv6 nor IPv6LL is enabled)
|
|
+ for this interface then disable IPv6 else enable it. */
|
|
+ (void) link_enable_ipv6(link);
|
|
+
|
|
if (link->network->mtu) {
|
|
+ /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
|
|
+ on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */
|
|
+ if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) {
|
|
+
|
|
+ log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as "
|
|
+ "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes: %m");
|
|
+
|
|
+ link->network->mtu = IPV6_MIN_MTU;
|
|
+ }
|
|
+
|
|
r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
|
|
if (r < 0)
|
|
return log_link_error_errno(link, r, "Could not set MTU: %m");
|
|
@@ -1392,7 +1440,7 @@ static int link_up(Link *link) {
|
|
if (r < 0)
|
|
return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
|
|
|
|
- if (socket_ipv6_is_supported()) {
|
|
+ if (link_ipv6_enabled(link)) {
|
|
/* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
|
|
r = sd_netlink_message_open_container(req, AF_INET6);
|
|
if (r < 0)
|
|
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
|
|
index 54f76fe206..9f2cbcec30 100644
|
|
--- a/src/network/networkd-network.c
|
|
+++ b/src/network/networkd-network.c
|
|
@@ -394,6 +394,19 @@ int network_apply(Manager *manager, Network *network, Link *link) {
|
|
return 0;
|
|
}
|
|
|
|
+bool network_has_static_ipv6_addresses(Network *network) {
|
|
+ Address *address;
|
|
+
|
|
+ assert(network);
|
|
+
|
|
+ LIST_FOREACH(addresses, address, network->static_addresses) {
|
|
+ if (address->family == AF_INET6)
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
int config_parse_netdev(const char *unit,
|
|
const char *filename,
|
|
unsigned line,
|
|
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
|
|
index 03c3f206c3..16533a7ec2 100644
|
|
--- a/src/network/networkd-network.h
|
|
+++ b/src/network/networkd-network.h
|
|
@@ -168,6 +168,8 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
|
int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *mac, Network **ret);
|
|
int network_apply(Manager *manager, Network *network, Link *link);
|
|
|
|
+bool network_has_static_ipv6_addresses(Network *network);
|
|
+
|
|
int config_parse_netdev(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_domains(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_tunnel(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);
|