summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2019-08-23 10:39:22 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2019-08-30 09:53:04 +0200
commit5f0c6f8d3be548ee8880e21d96088fef36d74848 (patch)
tree59bc231b219d42160a2d5c5a36287afcc1b157da
parentc0a825bc8e02f0134d8f62a9c614575cffae3080 (diff)
downloadNetworkManager-5f0c6f8d3be548ee8880e21d96088fef36d74848.tar.gz
ipv6: set neighbor parameters from RAs
IPv6 router advertisement messages contain the following parameters (RFC 4861): - Reachable time: 32-bit unsigned integer. The time, in milliseconds, that a node assumes a neighbor is reachable after having received a reachability confirmation. Used by the Neighbor Unreachability Detection algorithm. A value of zero means unspecified (by this router). - Retrans Timer: 32-bit unsigned integer. The time, in milliseconds, between retransmitted Neighbor Solicitation messages. Used by address resolution and the Neighbor Unreachability Detection algorithm. A value of zero means unspecified (by this router). Currently NM ignores them; however, since it leaves accept_ra=1, the kernel parses RAs and applies those parameters for us [1]. In the next commit kernel handling of RAs will be disabled, so let NM set those neighbor-related parameters. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv6/ndisc.c?h=v5.2#n1353
-rw-r--r--src/devices/nm-device.c12
-rw-r--r--src/ndisc/nm-lndp-ndisc.c13
-rw-r--r--src/ndisc/nm-ndisc.c8
-rw-r--r--src/ndisc/nm-ndisc.h4
-rw-r--r--src/nm-iface-helper.c12
-rw-r--r--src/platform/nm-platform.c48
-rw-r--r--src/platform/nm-platform.h6
7 files changed, 103 insertions, 0 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 5262670886..fb8ac91f34 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -9658,6 +9658,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (nm_device_get_platform (self), nm_device_get_ip_iface (self), rdata->hop_limit);
+ if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) {
+ nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (nm_device_get_platform (self),
+ nm_device_get_ip_iface (self),
+ rdata->reachable_time_ms);
+ }
+
+ if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) {
+ nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (nm_device_get_platform (self),
+ nm_device_get_ip_iface (self),
+ rdata->retrans_timer_ms);
+ }
+
if (changed & NM_NDISC_CONFIG_MTU) {
if (priv->ip6_mtu != rdata->mtu) {
_LOGD (LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu);
diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c
index 5643c19286..9352a75352 100644
--- a/src/ndisc/nm-lndp-ndisc.c
+++ b/src/ndisc/nm-lndp-ndisc.c
@@ -116,6 +116,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
gint32 now = nm_utils_get_monotonic_timestamp_s ();
int offset;
int hop_limit;
+ guint32 val;
/* Router discovery is subject to the following RFC documents:
*
@@ -294,6 +295,18 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
changed |= NM_NDISC_CONFIG_HOP_LIMIT;
}
+ val = ndp_msgra_reachable_time (msgra);
+ if (val && rdata->public.reachable_time_ms != val) {
+ rdata->public.reachable_time_ms = val;
+ changed |= NM_NDISC_CONFIG_REACHABLE_TIME;
+ }
+
+ val = ndp_msgra_retransmit_time (msgra);
+ if (val && rdata->public.retrans_timer_ms != val) {
+ rdata->public.retrans_timer_ms = val;
+ changed |= NM_NDISC_CONFIG_RETRANS_TIMER;
+ }
+
/* MTU */
ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_MTU) {
guint32 mtu = ndp_msg_opt_mtu(msg, offset);
diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c
index 1acf5ba9e6..a8fabb5634 100644
--- a/src/ndisc/nm-ndisc.c
+++ b/src/ndisc/nm-ndisc.c
@@ -1039,6 +1039,14 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed)
config_map_to_string (changed, changedstr);
_LOGD ("neighbor discovery configuration changed [%s]:", changedstr);
_LOGD (" dhcp-level %s", dhcp_level_to_string (priv->rdata.public.dhcp_level));
+
+ if (rdata->public.hop_limit)
+ _LOGD (" hop limit : %d", rdata->public.hop_limit);
+ if (rdata->public.reachable_time_ms)
+ _LOGD (" reachable time : %u", (guint) rdata->public.reachable_time_ms);
+ if (rdata->public.retrans_timer_ms)
+ _LOGD (" retrans timer : %u", (guint) rdata->public.retrans_timer_ms);
+
for (i = 0; i < rdata->gateways->len; i++) {
NMNDiscGateway *gateway = &g_array_index (rdata->gateways, NMNDiscGateway, i);
diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h
index 766d4ab9e4..8e07ca41de 100644
--- a/src/ndisc/nm-ndisc.h
+++ b/src/ndisc/nm-ndisc.h
@@ -112,6 +112,8 @@ typedef enum {
NM_NDISC_CONFIG_DNS_DOMAINS = 1 << 5,
NM_NDISC_CONFIG_HOP_LIMIT = 1 << 6,
NM_NDISC_CONFIG_MTU = 1 << 7,
+ NM_NDISC_CONFIG_REACHABLE_TIME = 1 << 8,
+ NM_NDISC_CONFIG_RETRANS_TIMER = 1 << 9,
} NMNDiscConfigMap;
typedef enum {
@@ -137,6 +139,8 @@ typedef struct {
NMNDiscDHCPLevel dhcp_level;
guint32 mtu;
int hop_limit;
+ guint32 reachable_time_ms;
+ guint32 retrans_timer_ms;
guint gateways_n;
guint addresses_n;
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 239b46a140..f93f3470d5 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -220,6 +220,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NM_PLATFORM_GET, global_opt.ifname, rdata->hop_limit);
+ if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) {
+ nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NM_PLATFORM_GET,
+ global_opt.ifname,
+ rdata->reachable_time_ms);
+ }
+
+ if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) {
+ nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NM_PLATFORM_GET,
+ global_opt.ifname,
+ rdata->retrans_timer_ms);
+ }
+
if (changed & NM_NDISC_CONFIG_MTU) {
nm_platform_sysctl_ip_conf_set_int64 (NM_PLATFORM_GET,
AF_INET6,
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 6ead15ed35..0a7acba9ab 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -610,6 +610,54 @@ nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self,
return TRUE;
}
+gboolean
+nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self,
+ const char *iface,
+ guint value_ms)
+{
+ char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
+ char str[128];
+ guint clamped;
+
+ _CHECK_SELF (self, klass, FALSE);
+
+ if (!value_ms)
+ return TRUE;
+
+ /* RFC 4861 says the value can't be greater than one hour.
+ * Also use a reasonable lower threshold. */
+ clamped = NM_CLAMP (value_ms, 100, 3600000);
+ nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface);
+ nm_sprintf_buf (str, "%u", clamped);
+ if (!nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str))
+ return FALSE;
+
+ /* Set stale time in the same way as kernel */
+ nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/gc_stale_time", iface);
+ nm_sprintf_buf (str, "%u", clamped * 3 / 1000);
+
+ return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str);
+}
+
+gboolean
+nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self,
+ const char *iface,
+ guint value_ms)
+{
+ char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
+ char str[128];
+
+ _CHECK_SELF (self, klass, FALSE);
+
+ if (!value_ms)
+ return TRUE;
+
+ nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface);
+ nm_sprintf_buf (str, "%u", NM_CLAMP (value_ms, 10, 3600000));
+
+ return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str);
+}
+
/**
* nm_platform_sysctl_get:
* @self: platform instance
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 248eca44f9..44733809f0 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -1353,6 +1353,12 @@ gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self,
gboolean nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self,
const char *iface,
int value);
+gboolean nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self,
+ const char *iface,
+ guint value_ms);
+gboolean nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self,
+ const char *iface,
+ guint value_ms);
int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4 (NMPlatform *platform,
const char *iface,
gboolean consider_all,