device/ndisc: let calling code determine the used RA timeout for NMNDisc

Previously, if we passed ra_timeout 0 to NMNDisc, then it would
calculate the effective timeout based on the router-solicitations
and the router-solicitation-interval.

The caller may want to know the used timeout, to also run its own timers
with the same timeout. Hence, it cannot leave this automatism internal
to NMNDisc.
This commit is contained in:
Thomas Haller 2020-09-14 18:49:34 +02:00
parent f6692367b1
commit e8eaaa78d1
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
8 changed files with 179 additions and 62 deletions

View file

@ -1179,7 +1179,7 @@ out_good:
return duid_out;
}
static gint32
static guint32
_prop_get_ipv6_ra_timeout (NMDevice *self)
{
NMConnection *connection;
@ -1191,9 +1191,9 @@ _prop_get_ipv6_ra_timeout (NMDevice *self)
connection = nm_device_get_applied_connection (self);
timeout = nm_setting_ip6_config_get_ra_timeout (NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)));
nm_assert (timeout >= 0);
if (timeout)
if (timeout > 0)
return timeout;
nm_assert (timeout == 0);
return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
NM_CON_DEFAULT ("ipv6.ra-timeout"),
@ -10981,15 +10981,6 @@ addrconf6_start_with_link_ready (NMDevice *self)
return;
}
static NMNDiscNodeType
ndisc_node_type (NMDevice *self)
{
if (nm_streq (nm_device_get_effective_ip_config_method (self, AF_INET6),
NM_SETTING_IP4_CONFIG_METHOD_SHARED))
return NM_NDISC_NODE_TYPE_ROUTER;
return NM_NDISC_NODE_TYPE_HOST;
}
static gboolean
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
{
@ -10999,6 +10990,12 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
GError *error = NULL;
NMUtilsStableType stable_type;
const char *stable_id;
NMNDiscNodeType node_type;
int max_addresses;
int router_solicitations;
int router_solicitation_interval;
guint32 ra_timeout;
guint32 default_ra_timeout;
connection = nm_device_get_applied_connection (self);
g_assert (connection);
@ -11012,6 +11009,27 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
g_assert (s_ip6);
if (nm_streq (nm_device_get_effective_ip_config_method (self, AF_INET6),
NM_SETTING_IP4_CONFIG_METHOD_SHARED))
node_type = NM_NDISC_NODE_TYPE_ROUTER;
else
node_type = NM_NDISC_NODE_TYPE_HOST;
nm_lndp_ndisc_get_sysctl (nm_device_get_platform (self),
nm_device_get_ip_iface (self),
&max_addresses,
&router_solicitations,
&router_solicitation_interval,
&default_ra_timeout);
if (node_type == NM_NDISC_NODE_TYPE_ROUTER)
ra_timeout = 0u;
else {
ra_timeout = _prop_get_ipv6_ra_timeout (self);
if (ra_timeout == 0u)
ra_timeout = default_ra_timeout;
}
stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
priv->ndisc = nm_lndp_ndisc_new (nm_device_get_platform (self),
nm_device_get_ip_ifindex (self),
@ -11019,8 +11037,11 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
stable_type,
stable_id,
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
ndisc_node_type (self),
_prop_get_ipv6_ra_timeout (self),
node_type,
max_addresses,
router_solicitations,
router_solicitation_interval,
ra_timeout,
&error);
if (!priv->ndisc) {
_LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);

View file

@ -360,6 +360,10 @@ nm_fake_ndisc_new (int ifindex, const char *ifname)
NM_NDISC_NODE_TYPE, (int) NM_NDISC_NODE_TYPE_HOST,
NM_NDISC_STABLE_TYPE, (int) NM_UTILS_STABLE_TYPE_UUID,
NM_NDISC_NETWORK_ID, "fake",
NM_NDISC_MAX_ADDRESSES, NM_NDISC_MAX_ADDRESSES_DEFAULT,
NM_NDISC_ROUTER_SOLICITATIONS, NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
NM_NDISC_ROUTER_SOLICITATION_INTERVAL, NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT,
NM_NDISC_RA_TIMEOUT, 30u,
NULL);
}

View file

@ -550,6 +550,51 @@ ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property,
defval);
}
void
nm_lndp_ndisc_get_sysctl (NMPlatform *platform,
const char *ifname,
int *out_max_addresses,
int *out_router_solicitations,
int *out_router_solicitation_interval,
guint32 *out_default_ra_timeout)
{
int router_solicitation_interval = 0;
int router_solicitations = 0;
if (out_max_addresses) {
*out_max_addresses = ipv6_sysctl_get (platform,
ifname,
"max_addresses",
0,
G_MAXINT32,
NM_NDISC_MAX_ADDRESSES_DEFAULT);
}
if (out_router_solicitations || out_default_ra_timeout) {
router_solicitations = ipv6_sysctl_get (platform,
ifname,
"router_solicitations",
1,
G_MAXINT32,
NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT);
NM_SET_OUT (out_router_solicitations, router_solicitations);
}
if (out_router_solicitation_interval || out_default_ra_timeout) {
router_solicitation_interval = ipv6_sysctl_get (platform,
ifname,
"router_solicitation_interval",
1,
G_MAXINT32,
NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT);
NM_SET_OUT (out_router_solicitation_interval, router_solicitation_interval);
}
if (out_default_ra_timeout) {
*out_default_ra_timeout = NM_MAX ((((gint64) router_solicitations) * router_solicitation_interval) + 1,
30);
}
}
/*****************************************************************************/
static void
nm_lndp_ndisc_init (NMLndpNDisc *lndp_ndisc)
{
@ -563,7 +608,10 @@ nm_lndp_ndisc_new (NMPlatform *platform,
const char *network_id,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
NMNDiscNodeType node_type,
gint32 ra_timeout,
int max_addresses,
int router_solicitations,
int router_solicitation_interval,
guint32 ra_timeout,
GError **error)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
@ -586,16 +634,10 @@ nm_lndp_ndisc_new (NMPlatform *platform,
NM_NDISC_NETWORK_ID, network_id,
NM_NDISC_ADDR_GEN_MODE, (int) addr_gen_mode,
NM_NDISC_NODE_TYPE, (int) node_type,
NM_NDISC_MAX_ADDRESSES, ipv6_sysctl_get (platform, ifname,
"max_addresses",
0, G_MAXINT32, NM_NDISC_MAX_ADDRESSES_DEFAULT),
NM_NDISC_RA_TIMEOUT, (int) ra_timeout,
NM_NDISC_ROUTER_SOLICITATIONS, ipv6_sysctl_get (platform, ifname,
"router_solicitations",
1, G_MAXINT32, NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT),
NM_NDISC_ROUTER_SOLICITATION_INTERVAL, ipv6_sysctl_get (platform, ifname,
"router_solicitation_interval",
1, G_MAXINT32, NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT),
NM_NDISC_MAX_ADDRESSES, max_addresses,
NM_NDISC_ROUTER_SOLICITATIONS, router_solicitations,
NM_NDISC_ROUTER_SOLICITATION_INTERVAL, router_solicitation_interval,
NM_NDISC_RA_TIMEOUT, (guint) ra_timeout,
NULL);
priv = NM_LNDP_NDISC_GET_PRIVATE (ndisc);

View file

@ -28,7 +28,17 @@ NMNDisc *nm_lndp_ndisc_new (NMPlatform *platform,
const char *network_id,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
NMNDiscNodeType node_type,
gint32 ra_timeout,
int max_addresses,
int router_solicitations,
int router_solicitation_interval,
guint32 ra_timeout,
GError **error);
void nm_lndp_ndisc_get_sysctl (NMPlatform *platform,
const char *ifname,
int *out_max_addresses,
int *out_router_solicitations,
int *out_router_solicitation_interval,
guint32 *out_default_ra_timeout);
#endif /* __NETWORKMANAGER_LNDP_NDISC_H__ */

View file

@ -25,6 +25,9 @@ struct _NMNDiscPrivate {
/* this *must* be the first field. */
NMNDiscDataInternal rdata;
char *last_error;
GSource *ra_timeout_source;
union {
gint32 solicitations_left;
gint32 announcements_left;
@ -37,9 +40,7 @@ struct _NMNDiscPrivate {
gint32 last_rs;
gint32 last_ra;
};
guint ra_timeout_id; /* first RA timeout */
guint timeout_id; /* prefix/dns/etc lifetime timeout */
char *last_error;
NMUtilsIPv6IfaceId iid;
/* immutable values: */
@ -48,7 +49,7 @@ struct _NMNDiscPrivate {
char *network_id;
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
NMUtilsStableType stable_type;
gint32 ra_timeout;
guint32 ra_timeout;
gint32 max_addresses;
gint32 router_solicitations;
gint32 router_solicitation_interval;
@ -899,7 +900,7 @@ ndisc_ra_timeout_cb (gpointer user_data)
{
NMNDisc *ndisc = NM_NDISC (user_data);
NM_NDISC_GET_PRIVATE (ndisc)->ra_timeout_id = 0;
nm_clear_g_source_inst (&NM_NDISC_GET_PRIVATE (ndisc)->ra_timeout_source);
g_signal_emit (ndisc, signals[RA_TIMEOUT_SIGNAL], 0);
return G_SOURCE_REMOVE;
}
@ -915,7 +916,7 @@ nm_ndisc_start (NMNDisc *ndisc)
priv = NM_NDISC_GET_PRIVATE (ndisc);
nm_assert (NM_NDISC_GET_CLASS (ndisc)->start);
nm_assert (!priv->ra_timeout_id);
nm_assert (!priv->ra_timeout_source);
_LOGD ("starting neighbor discovery for ifindex %d%s",
priv->ifindex,
@ -929,23 +930,32 @@ nm_ndisc_start (NMNDisc *ndisc)
NM_NDISC_GET_CLASS (ndisc)->start (ndisc);
if (priv->node_type == NM_NDISC_NODE_TYPE_HOST) {
gint32 ra_timeout = priv->ra_timeout;
G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_DEFAULT == 0);
G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_INFINITY == G_MAXINT32);
if (ra_timeout != NM_RA_TIMEOUT_INFINITY) {
if (ra_timeout == NM_RA_TIMEOUT_DEFAULT) {
ra_timeout = NM_MAX ((((gint64) priv->router_solicitations) * priv->router_solicitation_interval) + 1,
30);
}
nm_assert (ra_timeout > 0 && ra_timeout < NM_RA_TIMEOUT_INFINITY);
_LOGD ("scheduling RA timeout in %d seconds", ra_timeout);
priv->ra_timeout_id = g_timeout_add_seconds (ra_timeout, ndisc_ra_timeout_cb, ndisc);
nm_assert (priv->ra_timeout > 0u);
nm_assert (priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY);
if (priv->ra_timeout < NM_RA_TIMEOUT_INFINITY) {
guint timeout_msec;
_LOGD ("scheduling RA timeout in %u seconds", priv->ra_timeout);
if (priv->ra_timeout < G_MAXUINT / 1000u)
timeout_msec = priv->ra_timeout * 1000u;
else
timeout_msec = G_MAXUINT;
priv->ra_timeout_source = nm_g_timeout_source_new (timeout_msec,
G_PRIORITY_DEFAULT,
ndisc_ra_timeout_cb,
ndisc,
NULL);
g_source_attach (priv->ra_timeout_source, NULL);
}
solicit_routers (ndisc);
return;
}
nm_assert (priv->ra_timeout == 0u);
nm_assert (priv->node_type == NM_NDISC_NODE_TYPE_ROUTER);
announce_router_initial (ndisc);
}
@ -1254,7 +1264,7 @@ nm_ndisc_ra_received (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed)
{
NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE (ndisc);
nm_clear_g_source (&priv->ra_timeout_id);
nm_clear_g_source_inst (&priv->ra_timeout_source);
nm_clear_g_source (&priv->send_rs_id);
nm_clear_g_free (&priv->last_error);
check_timestamps (ndisc, now, changed);
@ -1328,7 +1338,8 @@ set_property (GObject *object, guint prop_id,
break;
case PROP_RA_TIMEOUT:
/* construct-only */
priv->ra_timeout = g_value_get_int (value);
priv->ra_timeout = g_value_get_uint (value);
nm_assert (priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY);
break;
case PROP_ROUTER_SOLICITATIONS:
/* construct-only */
@ -1381,7 +1392,7 @@ dispose (GObject *object)
NMNDisc *ndisc = NM_NDISC (object);
NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE (ndisc);
nm_clear_g_source (&priv->ra_timeout_id);
nm_clear_g_source_inst (&priv->ra_timeout_source);
nm_clear_g_source (&priv->send_rs_id);
nm_clear_g_source (&priv->send_ra_id);
nm_clear_g_free (&priv->last_error);
@ -1468,11 +1479,11 @@ nm_ndisc_class_init (NMNDiscClass *klass)
G_PARAM_STATIC_STRINGS);
G_STATIC_ASSERT_EXPR (G_MAXINT32 == NM_RA_TIMEOUT_INFINITY);
obj_properties[PROP_RA_TIMEOUT] =
g_param_spec_int (NM_NDISC_RA_TIMEOUT, "", "",
0, G_MAXINT32, 0,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_param_spec_uint (NM_NDISC_RA_TIMEOUT, "", "",
0, G_MAXINT32, 0,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ROUTER_SOLICITATIONS] =
g_param_spec_int (NM_NDISC_ROUTER_SOLICITATIONS, "", "",
1, G_MAXINT32, NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,

View file

@ -16,8 +16,8 @@
#include "platform/nm-platform.h"
#include "platform/nmp-object.h"
#define NM_RA_TIMEOUT_DEFAULT ((gint32) 0)
#define NM_RA_TIMEOUT_INFINITY G_MAXINT32
#define NM_RA_TIMEOUT_DEFAULT ((guint32) 0)
#define NM_RA_TIMEOUT_INFINITY ((guint32) G_MAXINT32)
#define NM_TYPE_NDISC (nm_ndisc_get_type ())
#define NM_NDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NDISC, NMNDisc))
@ -112,15 +112,15 @@ typedef enum {
NM_NDISC_NODE_TYPE_ROUTER,
} NMNDiscNodeType;
#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16
#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861 MAX_RTR_SOLICITATIONS */
#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4 /* RFC4861 RTR_SOLICITATION_INTERVAL */
#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861 MAX_INITIAL_RTR_ADVERTISEMENTS */
#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861 MIN_DELAY_BETWEEN_RAS */
#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861 MAX_INITIAL_RTR_ADVERT_INTERVAL */
#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861 MAX_RA_DELAY_TIME */
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861 MaxRtrAdvInterval default */
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16
#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861 MAX_RTR_SOLICITATIONS */
#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4 /* RFC4861 RTR_SOLICITATION_INTERVAL */
#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861 MAX_INITIAL_RTR_ADVERTISEMENTS */
#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861 MIN_DELAY_BETWEEN_RAS */
#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861 MAX_INITIAL_RTR_ADVERT_INTERVAL */
#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861 MAX_RA_DELAY_TIME */
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861 MaxRtrAdvInterval default */
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
struct _NMNDiscPrivate;
struct _NMNDiscDataInternal;

View file

@ -25,6 +25,10 @@ main (int argc, char **argv)
const char *ifname;
NMUtilsIPv6IfaceId iid = { };
GError *error = NULL;
int max_addresses;
int router_solicitations;
int router_solicitation_interval;
guint32 ra_timeout;
nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT");
@ -45,6 +49,13 @@ main (int argc, char **argv)
return EXIT_FAILURE;
}
nm_lndp_ndisc_get_sysctl (NM_PLATFORM_GET,
ifname,
&max_addresses,
&router_solicitations,
&router_solicitation_interval,
&ra_timeout);
ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET,
ifindex,
ifname,
@ -52,7 +63,10 @@ main (int argc, char **argv)
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
NM_NDISC_NODE_TYPE_HOST,
0,
max_addresses,
router_solicitations,
router_solicitation_interval,
ra_timeout,
&error);
if (!ndisc) {
g_print ("Failed to create NMNDisc instance: %s\n", error->message);

View file

@ -552,6 +552,10 @@ main (int argc, char *argv[])
if (global_opt.slaac) {
NMUtilsStableType stable_type = NM_UTILS_STABLE_TYPE_UUID;
const char *stable_id = global_opt.uuid;
int router_solicitation_interval;
int router_solicitations;
guint32 default_ra_timeout;
int max_addresses;
nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, gl.ifindex, TRUE);
@ -564,6 +568,14 @@ main (int argc, char *argv[])
stable_type = (global_opt.stable_id[0] - '0');
stable_id = &global_opt.stable_id[2];
}
nm_lndp_ndisc_get_sysctl (NM_PLATFORM_GET,
global_opt.ifname,
&max_addresses,
&router_solicitations,
&router_solicitation_interval,
&default_ra_timeout);
ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET,
gl.ifindex,
global_opt.ifname,
@ -571,7 +583,10 @@ main (int argc, char *argv[])
stable_id,
global_opt.addr_gen_mode,
NM_NDISC_NODE_TYPE_HOST,
NM_RA_TIMEOUT_DEFAULT,
max_addresses,
router_solicitations,
router_solicitation_interval,
default_ra_timeout,
NULL);
g_assert (ndisc);