diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2019-08-23 10:39:22 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2019-08-30 09:53:04 +0200 |
commit | 5f0c6f8d3be548ee8880e21d96088fef36d74848 (patch) | |
tree | 59bc231b219d42160a2d5c5a36287afcc1b157da | |
parent | c0a825bc8e02f0134d8f62a9c614575cffae3080 (diff) | |
download | NetworkManager-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.c | 12 | ||||
-rw-r--r-- | src/ndisc/nm-lndp-ndisc.c | 13 | ||||
-rw-r--r-- | src/ndisc/nm-ndisc.c | 8 | ||||
-rw-r--r-- | src/ndisc/nm-ndisc.h | 4 | ||||
-rw-r--r-- | src/nm-iface-helper.c | 12 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 48 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 6 |
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, |