Beniamino Galvani 2021-07-05 17:21:50 +02:00
commit 5dfd80683d
18 changed files with 1254 additions and 686 deletions

View file

@ -868,6 +868,9 @@ ipv6.ip6-privacy=0
<listitem><para>If unspecified or zero, use 50 for VPN profiles
and 100 for other profiles.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv4.required-timeout</varname></term>
</varlistentry>
<varlistentry>
<term><varname>ipv4.route-metric</varname></term>
</varlistentry>
@ -910,6 +913,9 @@ ipv6.ip6-privacy=0
"/proc/sys/net/ipv6/conf/default/use_tempaddr" as last fallback.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ipv6.required-timeout</varname></term>
</varlistentry>
<varlistentry>
<term><varname>ipv6.route-metric</varname></term>
</varlistentry>

View file

@ -499,8 +499,18 @@ typedef struct _NMDevicePrivate {
NMDeviceStageState stage1_sriov_state : 3;
bool ip_config_started : 1;
char *current_stable_id;
union {
struct {
GSource *ip_req_timeout_source_6;
GSource *ip_req_timeout_source_4;
};
GSource *ip_req_timeout_source_x[2];
};
/* Proxy Configuration */
NMProxyConfig * proxy_config;
NMPacrunnerConfId *pacrunner_conf_id;
@ -766,6 +776,7 @@ static void sriov_op_cb(GError *error, gpointer user_data);
static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self);
static gboolean device_link_changed(NMDevice *self);
static void check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update);
/*****************************************************************************/
@ -1364,6 +1375,40 @@ out:
return timeout;
}
static guint32
_prop_get_ipvx_required_timeout(NMDevice *self, int addr_family)
{
NMConnection * connection;
NMSettingIPConfig *s_ip;
int timeout;
nm_assert(NM_IS_DEVICE(self));
nm_assert_addr_family(addr_family);
connection = nm_device_get_applied_connection(self);
if (!connection)
return 0;
s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
if (!s_ip)
return 0;
timeout = nm_setting_ip_config_get_required_timeout(s_ip);
nm_assert(timeout >= -1);
if (timeout > -1)
return (guint32) timeout;
return nm_config_data_get_connection_default_int64(
NM_CONFIG_GET_DATA,
NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.required-timeout")
: NM_CON_DEFAULT("ipv6.required-timeout"),
self,
0,
G_MAXINT32,
0);
}
/**
* _prop_get_ipvx_dhcp_iaid:
* @self: the #NMDevice
@ -2787,14 +2832,72 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities)
/*****************************************************************************/
static gboolean
ip_required_timeout_x(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
_LOGD(LOGD_CORE,
"required-timeout expired for IPv%c",
nm_utils_addr_family_to_char(addr_family));
nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[NM_IS_IPv4(addr_family)]);
check_ip_state(self, FALSE, TRUE);
return G_SOURCE_CONTINUE;
}
static gboolean
ip_required_timeout_4(gpointer data)
{
return ip_required_timeout_x(data, AF_INET);
}
static gboolean
ip_required_timeout_6(gpointer data)
{
return ip_required_timeout_x(data, AF_INET6);
}
static void
_set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
guint timeout_msec;
int v4;
nm_assert_addr_family(addr_family);
if (new_state == NM_DEVICE_IP_STATE_CONF && !priv->ip_config_started) {
/* Start the required-timeout timers when one of IPv4/IPv6
* enters the CONF state. This means that if there is no carrier and
* ipv4.method=auto,ipv6.method=manual, the timeout for IPv4 will
* start as soon as connection is activated, even if DHCPv4 did not
* start yet.
*/
priv->ip_config_started = TRUE;
for (v4 = 1; v4 >= 0; v4--) {
char buf[32];
nm_assert(!priv->ip_req_timeout_source_x[v4]);
if ((timeout_msec = _prop_get_ipvx_required_timeout(self, v4 ? AF_INET : AF_INET6))) {
_LOGD(LOGD_CORE,
"required-timeout in %s msec for IPv%c",
timeout_msec == G_MAXINT32 ? "" : nm_sprintf_buf(buf, "%u", timeout_msec),
v4 ? '4' : '6');
if (timeout_msec == G_MAXINT32) {
priv->ip_req_timeout_source_x[v4] = g_source_ref(nm_g_source_sentinel_get(0));
} else {
priv->ip_req_timeout_source_x[v4] =
nm_g_timeout_add_source(timeout_msec,
v4 ? ip_required_timeout_4 : ip_required_timeout_6,
self);
}
}
}
}
if (priv->ip_state_x[IS_IPv4] == new_state)
return;
@ -6576,6 +6679,7 @@ check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update)
gboolean ip4_disabled = FALSE, ip6_disabled = FALSE;
NMSettingIPConfig *s_ip4, *s_ip6;
NMDeviceState state;
int IS_IPv4;
if (full_state_update && nm_device_get_state(self) != NM_DEVICE_STATE_IP_CONFIG)
return;
@ -6605,6 +6709,13 @@ check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update)
return;
}
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_CONF
&& priv->ip_req_timeout_source_x[IS_IPv4]) {
return;
}
}
if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL
|| (ip4_disabled && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE))
&& (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL
@ -11810,6 +11921,8 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
req = nm_device_get_act_request(self);
g_assert(req);
nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[IS_IPv4]);
/* Interface must be IFF_UP before IP config can be applied */
ip_ifindex = nm_device_get_ip_ifindex(self);
g_return_if_fail(ip_ifindex);
@ -15777,6 +15890,10 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
_cleanup_ip_pre(self, AF_INET, cleanup_type);
_cleanup_ip_pre(self, AF_INET6, cleanup_type);
priv->ip_config_started = FALSE;
nm_clear_g_source_inst(&priv->ip_req_timeout_source_4);
nm_clear_g_source_inst(&priv->ip_req_timeout_source_6);
}
static void

View file

@ -1895,6 +1895,8 @@ make_ip4_setting(shvarFile *ifcfg,
svGetValueBoolean(ifcfg, "DHCP_SEND_HOSTNAME", TRUE),
NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,
(int) svGetValueInt64(ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0),
NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT,
(int) svGetValueInt64(ifcfg, "IPV4_REQUIRED_TIMEOUT", 10, 0, G_MAXINT32, -1),
NULL);
nm_clear_g_free(&value);
@ -2403,6 +2405,8 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
svGetValueBoolean(ifcfg, "DHCPV6_SEND_HOSTNAME", TRUE),
NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,
(int) svGetValueInt64(ifcfg, "IPV6_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0),
NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT,
(int) svGetValueInt64(ifcfg, "IPV6_REQUIRED_TIMEOUT", 10, 0, G_MAXINT32, -1),
NM_SETTING_IP6_CONFIG_RA_TIMEOUT,
(int) svGetValueInt64(ifcfg, "IPV6_RA_TIMEOUT", 10, 0, G_MAXINT32, 0),
NULL);

View file

@ -958,6 +958,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = {
_KEY_TYPE("IPV4_DHCP_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV4_DNS_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV4_FAILURE_FATAL", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV4_REQUIRED_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV4_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV4_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6ADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
@ -980,6 +981,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = {
_KEY_TYPE("IPV6_PRIVACY", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_PRIVACY_PREFER_PUBLIC_IP", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_RA_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_REQUIRED_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_RES_OPTIONS", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_ROUTE_METRIC", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IPV6_ROUTE_TABLE", NMS_IFCFG_KEY_TYPE_IS_PLAIN),

View file

@ -33,7 +33,7 @@ typedef struct {
NMSIfcfgKeyTypeFlags key_flags;
} NMSIfcfgKeyTypeInfo;
extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[249];
extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[251];
const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx);

View file

@ -2840,6 +2840,9 @@ write_ip4_setting(NMConnection *connection,
timeout = nm_setting_ip_config_get_dhcp_timeout(s_ip4);
svSetValueInt64_cond(ifcfg, "IPV4_DHCP_TIMEOUT", timeout != 0, timeout);
timeout = nm_setting_ip_config_get_required_timeout(s_ip4);
svSetValueInt64_cond(ifcfg, "IPV4_REQUIRED_TIMEOUT", timeout != -1, timeout);
svSetValueBoolean(ifcfg, "IPV4_FAILURE_FATAL", !nm_setting_ip_config_get_may_fail(s_ip4));
route_metric = nm_setting_ip_config_get_route_metric(s_ip4);
@ -3037,6 +3040,9 @@ write_ip6_setting(NMConnection *connection,
timeout = nm_setting_ip_config_get_dhcp_timeout(s_ip6);
svSetValueInt64_cond(ifcfg, "IPV6_DHCP_TIMEOUT", timeout != 0, timeout);
timeout = nm_setting_ip_config_get_required_timeout(s_ip6);
svSetValueInt64_cond(ifcfg, "IPV6_REQUIRED_TIMEOUT", timeout != -1, timeout);
flags = nm_setting_ip_config_get_dhcp_hostname_flags(s_ip6);
svSetValueInt64_cond(ifcfg,
"DHCPV6_HOSTNAME_FLAGS",

View file

@ -1793,3 +1793,7 @@ global:
nm_setting_match_new;
nm_setting_wired_get_accept_all_mac_addresses;
} libnm_1_30_0;
libnm_1_32_4 {
nm_setting_ip_config_get_required_timeout;
} libnm_1_32_0;

View file

@ -3905,6 +3905,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig,
PROP_MAY_FAIL,
PROP_DAD_TIMEOUT,
PROP_DHCP_TIMEOUT,
PROP_REQUIRED_TIMEOUT,
PROP_DHCP_IAID,
PROP_DHCP_REJECT_SERVERS, );
@ -3925,6 +3926,7 @@ typedef struct {
int dns_priority;
int dad_timeout;
int dhcp_timeout;
int required_timeout;
guint32 route_table;
bool ignore_auto_routes : 1;
bool ignore_auto_dns : 1;
@ -5205,6 +5207,25 @@ nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting)
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dhcp_timeout;
}
/**
* nm_setting_ip_config_get_required_timeout:
* @setting: the #NMSettingIPConfig
*
* Returns the value contained in the #NMSettingIPConfig:required-timeout
* property.
*
* Returns: the required timeout for the address family
*
* Since: 1.34, 1.32.4
**/
int
nm_setting_ip_config_get_required_timeout(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), -1);
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->required_timeout;
}
/**
* nm_setting_ip_config_get_dhcp_iaid:
* @setting: the #NMSettingIPConfig
@ -5908,6 +5929,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
case PROP_DHCP_TIMEOUT:
g_value_set_int(value, nm_setting_ip_config_get_dhcp_timeout(setting));
break;
case PROP_REQUIRED_TIMEOUT:
g_value_set_int(value, nm_setting_ip_config_get_required_timeout(setting));
break;
case PROP_DHCP_IAID:
g_value_set_string(value, nm_setting_ip_config_get_dhcp_iaid(setting));
break;
@ -6018,6 +6042,9 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
case PROP_DHCP_TIMEOUT:
priv->dhcp_timeout = g_value_get_int(value);
break;
case PROP_REQUIRED_TIMEOUT:
priv->required_timeout = g_value_get_int(value);
break;
case PROP_DHCP_IAID:
g_free(priv->dhcp_iaid);
priv->dhcp_iaid = g_value_dup_string(value);
@ -6049,6 +6076,7 @@ nm_setting_ip_config_init(NMSettingIPConfig *setting)
priv->dhcp_send_hostname = TRUE;
priv->may_fail = TRUE;
priv->dad_timeout = -1;
priv->required_timeout = -1;
}
static void
@ -6483,6 +6511,38 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass)
0,
G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:required-timeout:
*
* The minimum time interval in milliseconds for which dynamic IP configuration
* should be tried before the connection succeeds.
*
* This property is useful for example if both IPv4 and IPv6 are enabled and
* are allowed to fail. Normally the connection succeeds as soon as one of
* the two address families completes; by setting a required timeout for
* e.g. IPv4, one can ensure that even if IP6 succeeds earlier than IPv4,
* NetworkManager waits some time for IPv4 before the connection becomes
* active.
*
* Note that if #NMSettingIPConfig:may-fail is FALSE for the same address
* family, this property has no effect as NetworkManager needs to wait for
* the full DHCP timeout.
*
* A zero value means that no required timeout is present, -1 means the
* default value (either configuration ipvx.required-timeout override or
* zero).
*
* Since: 1.34, 1.32.4
**/
obj_properties[PROP_REQUIRED_TIMEOUT] = g_param_spec_int(
NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT,
"",
"",
-1,
G_MAXINT32,
-1,
G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:dhcp-iaid:
*

View file

@ -3868,6 +3868,7 @@ test_connection_diff_a_only(void)
{NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DAD_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DNS_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_IAID, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, NM_SETTING_DIFF_RESULT_IN_A},

View file

@ -331,6 +331,7 @@ char *nm_ip_routing_rule_to_string(const NMIPRoutingRule * self,
#define NM_SETTING_IP_CONFIG_MAY_FAIL "may-fail"
#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout"
#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout"
#define NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT "required-timeout"
#define NM_SETTING_IP_CONFIG_DHCP_IAID "dhcp-iaid"
#define NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS "dhcp-reject-servers"
@ -473,6 +474,8 @@ NM_AVAILABLE_IN_1_2
int nm_setting_ip_config_get_dad_timeout(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_2
int nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_32_4
int nm_setting_ip_config_get_required_timeout(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_22
const char *nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting);

View file

@ -6014,6 +6014,21 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
PROPERTY_INFO (NM_SETTING_IP_CONFIG_MAY_FAIL, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL,
.property_type = &_pt_gobject_bool,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_REQUIRED_TIMEOUT,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
.value_infos = INT_VALUE_INFOS (
{
.value.i64 = -1,
.nick = "default",
},
{
.value.i64 = G_MAXINT32,
.nick = "infinity",
},
),
),
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_DAD_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
@ -6217,6 +6232,21 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = {
PROPERTY_INFO (NM_SETTING_IP_CONFIG_MAY_FAIL, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_MAY_FAIL,
.property_type = &_pt_gobject_bool,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_REQUIRED_TIMEOUT,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
.value_infos = INT_VALUE_INFOS (
{
.value.i64 = -1,
.nick = "default",
},
{
.value.i64 = G_MAXINT32,
.nick = "infinity",
},
),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
.property_type = &_pt_gobject_enum,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_enum,

View file

@ -247,6 +247,7 @@
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_REQUIRED_TIMEOUT N_("The minimum time interval in milliseconds for which dynamic IP configuration should be tried before the connection succeeds. This property is useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. Normally the connection succeeds as soon as one of the two address families completes; by setting a required timeout for e.g. IPv4, one can ensure that even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for IPv4 before the connection becomes active. Note that if \"may-fail\" is FALSE for the same address family, this property has no effect as NetworkManager needs to wait for the full DHCP timeout. A zero value means that no required timeout is present, -1 means the default value (either configuration ipvx.required-timeout override or zero).")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("A list of IPv4 destination addresses, prefix length, optional IPv4 next hop addresses, optional route metric, optional attribute. The valid syntax is: \"ip[/prefix] [next-hop] [metric] [attribute=val]...[,ip[/prefix]...]\". For example \"192.0.2.0/24 10.1.1.1 77, 198.51.100.0/24\".")
@ -272,6 +273,7 @@
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_RA_TIMEOUT N_("A timeout for waiting Router Advertisements in seconds. If zero (the default), a globally configured default is used. If still unspecified, the timeout depends on the sysctl settings of the device. Set to 2147483647 (MAXINT32) for infinity.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_REQUIRED_TIMEOUT N_("The minimum time interval in milliseconds for which dynamic IP configuration should be tried before the connection succeeds. This property is useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. Normally the connection succeeds as soon as one of the two address families completes; by setting a required timeout for e.g. IPv4, one can ensure that even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for IPv4 before the connection becomes active. Note that if \"may-fail\" is FALSE for the same address family, this property has no effect as NetworkManager needs to wait for the full DHCP timeout. A zero value means that no required timeout is present, -1 means the default value (either configuration ipvx.required-timeout override or zero).")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC N_("The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is chosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE N_("Enable policy routing (source routing) and set the routing table used when adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes and static routes. But note that static routes can individually overwrite the setting by explicitly specifying a non-zero routing table. If the table setting is left at zero, it is eligible to be overwritten via global configuration. If the property is zero even after applying the global configuration value, policy routing is disabled for the address family of this connection. Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")

View file

@ -9,7 +9,8 @@
#include "nm-connection.h"
#include "nm-utils.h"
#define NMI_WAIT_DEVICE_TIMEOUT_MS 60000
#define NMI_WAIT_DEVICE_TIMEOUT_MSEC 60000
#define NMI_IP_REQUIRED_TIMEOUT_MSEC 20000
static inline int
get_ip_address_family(const char *str, gboolean with_prefix)

View file

@ -119,6 +119,8 @@ reader_create_connection(Reader * reader,
reader->dhcp_timeout,
NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER,
reader->dhcp4_vci,
NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT,
NMI_IP_REQUIRED_TIMEOUT_MSEC,
NULL);
setting = nm_setting_ip6_config_new();
@ -401,18 +403,19 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
gs_unref_hashtable GHashTable *ibft = NULL;
const char * tmp;
const char * tmp2;
const char * kind = NULL;
const char * client_ip = NULL;
const char * peer = NULL;
const char * gateway_ip = NULL;
const char * netmask = NULL;
const char * client_hostname = NULL;
const char * iface_spec = NULL;
const char * mtu = NULL;
const char * macaddr = NULL;
int client_ip_family = AF_UNSPEC;
int client_ip_prefix = -1;
const char * dns[2] = {
const char * kind = NULL;
const char * client_ip = NULL;
const char * peer = NULL;
const char * gateway_ip = NULL;
const char * netmask = NULL;
const char * client_hostname = NULL;
const char * iface_spec = NULL;
const char * mtu = NULL;
const char * macaddr = NULL;
int client_ip_family = AF_UNSPEC;
int client_ip_prefix = -1;
gboolean clear_ip4_required_timeout = TRUE;
const char * dns[2] = {
NULL,
NULL,
};
@ -679,8 +682,13 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
g_clear_error(&error);
}
}
} else {
clear_ip4_required_timeout = FALSE;
}
if (clear_ip4_required_timeout)
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, -1, NULL);
if (peer && *peer)
_LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer);
@ -1062,7 +1070,7 @@ connection_set_needed(NMConnection *connection)
g_object_set(s_con,
NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT,
(int) NMI_WAIT_DEVICE_TIMEOUT_MS,
(int) NMI_WAIT_DEVICE_TIMEOUT_MSEC,
NULL);
}

View file

@ -275,6 +275,7 @@ test_dhcp_timeout(void)
==,
NM_SETTING_IP4_CONFIG_METHOD_AUTO);
g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, data[i].timeout);
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip4), ==, -1);
s_ip6 = nm_connection_get_setting_ip6_config(connection);
g_assert(s_ip6);
@ -282,6 +283,7 @@ test_dhcp_timeout(void)
==,
NM_SETTING_IP6_CONFIG_METHOD_AUTO);
g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, data[i].timeout);
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip6), ==, -1);
}
}
@ -420,6 +422,7 @@ test_if_ip4_manual(void)
g_assert_cmpint(nm_ip_address_get_prefix(ip_addr), ==, 24);
g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.0.2.1");
g_assert_cmpstr(nm_setting_ip_config_get_dhcp_hostname(s_ip4), ==, "hostname0.example.com");
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip4), ==, -1);
s_ip6 = nm_connection_get_setting_ip6_config(connection);
g_assert(s_ip6);
@ -427,6 +430,7 @@ test_if_ip4_manual(void)
==,
NM_SETTING_IP6_CONFIG_METHOD_DISABLED);
g_assert(nm_setting_ip_config_get_may_fail(s_ip6));
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip6), ==, -1);
connection = g_hash_table_lookup(connections, "eth4");
nmtst_assert_connection_verifies_without_normalization(connection);
@ -702,7 +706,7 @@ test_multiple_bootdev(void)
g_assert(s_con);
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con),
==,
NMI_WAIT_DEVICE_TIMEOUT_MS);
NMI_WAIT_DEVICE_TIMEOUT_MSEC);
s_ip4 = nm_connection_get_setting_ip4_config(connection);
g_assert(s_ip4);
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
@ -744,7 +748,7 @@ test_bootdev(void)
g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "ens3");
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con),
==,
NMI_WAIT_DEVICE_TIMEOUT_MS);
NMI_WAIT_DEVICE_TIMEOUT_MSEC);
connection = g_hash_table_lookup(connections, "vlan2");
nmtst_assert_connection_verifies_without_normalization(connection);
@ -1153,6 +1157,9 @@ test_bridge(void)
g_assert_cmpint(nm_ip_route_get_metric(ip_route), ==, -1);
g_assert(!nm_ip_route_get_next_hop(ip_route));
g_assert_cmpint(nm_ip_route_get_prefix(ip_route), ==, 32);
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip4),
==,
NMI_IP_REQUIRED_TIMEOUT_MSEC);
s_ip6 = nm_connection_get_setting_ip6_config(connection);
g_assert(s_ip6);
@ -1162,6 +1169,7 @@ test_bridge(void)
g_assert(!nm_setting_ip_config_get_gateway(s_ip6));
g_assert_cmpint(nm_setting_ip_config_get_num_routes(s_ip6), ==, 0);
g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, 10);
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip6), ==, -1);
s_bridge = nm_connection_get_setting_bridge(connection);
g_assert(s_bridge);
@ -1902,7 +1910,38 @@ test_bootif_ip(void)
}
static void
test_neednet(void)
test_neednet_no_args(void)
{
const char *const *ARGV = NM_MAKE_STRV("rd.neednet");
gs_unref_object NMConnection *connection = NULL;
NMSettingWired * s_wired;
NMSettingIPConfig * s_ip4;
NMSettingIPConfig * s_ip6;
connection = _parse_con(ARGV, "default_connection");
g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection");
s_wired = nm_connection_get_setting_wired(connection);
g_assert(s_wired);
s_ip4 = nm_connection_get_setting_ip4_config(connection);
g_assert(s_ip4);
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
g_assert(nm_setting_ip_config_get_may_fail(s_ip4));
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip4),
==,
NMI_IP_REQUIRED_TIMEOUT_MSEC);
s_ip6 = nm_connection_get_setting_ip6_config(connection);
g_assert(s_ip6);
g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
g_assert(nm_setting_ip_config_get_may_fail(s_ip6));
g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip6), ==, -1);
}
static void
test_neednet_args(void)
{
gs_unref_hashtable GHashTable *connections = NULL;
const char *const * ARGV = NM_MAKE_STRV("rd.neednet",
@ -1922,7 +1961,7 @@ test_neednet(void)
g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno1");
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con),
==,
NMI_WAIT_DEVICE_TIMEOUT_MS);
NMI_WAIT_DEVICE_TIMEOUT_MSEC);
connection = g_hash_table_lookup(connections, "eno2");
nmtst_assert_connection_verifies_without_normalization(connection);
@ -1931,7 +1970,7 @@ test_neednet(void)
g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno2");
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con),
==,
NMI_WAIT_DEVICE_TIMEOUT_MS);
NMI_WAIT_DEVICE_TIMEOUT_MSEC);
connection = g_hash_table_lookup(connections, "eno3");
nmtst_assert_connection_verifies_without_normalization(connection);
@ -1940,7 +1979,7 @@ test_neednet(void)
g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "eno3");
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con),
==,
NMI_WAIT_DEVICE_TIMEOUT_MS);
NMI_WAIT_DEVICE_TIMEOUT_MSEC);
connection = g_hash_table_lookup(connections, "br0");
nmtst_assert_connection_verifies_without_normalization(connection);
@ -2236,7 +2275,8 @@ main(int argc, char **argv)
g_test_add_func("/initrd/cmdline/bootif/no_ip", test_bootif_no_ip);
g_test_add_func("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype);
g_test_add_func("/initrd/cmdline/bootif/off", test_bootif_off);
g_test_add_func("/initrd/cmdline/neednet", test_neednet);
g_test_add_func("/initrd/cmdline/neednet/no_args", test_neednet_no_args);
g_test_add_func("/initrd/cmdline/neednet/args", test_neednet_args);
g_test_add_func("/initrd/cmdline/dhcp/vendor_class_id", test_dhcp_vendor_class_id);
g_test_add_func("/initrd/cmdline/infiniband/iface", test_infiniband_iface);
g_test_add_func("/initrd/cmdline/infiniband/mac", test_infiniband_mac);

View file

@ -683,6 +683,8 @@
description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." />
<property name="may-fail"
description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." />
<property name="required-timeout"
description="The minimum time interval in milliseconds for which dynamic IP configuration should be tried before the connection succeeds. This property is useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. Normally the connection succeeds as soon as one of the two address families completes; by setting a required timeout for e.g. IPv4, one can ensure that even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for IPv4 before the connection becomes active. Note that if &quot;may-fail&quot; is FALSE for the same address family, this property has no effect as NetworkManager needs to wait for the full DHCP timeout. A zero value means that no required timeout is present, -1 means the default value (either configuration ipvx.required-timeout override or zero)." />
<property name="dad-timeout"
description="Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4." />
<property name="dhcp-vendor-class-identifier"
@ -722,6 +724,8 @@
description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." />
<property name="may-fail"
description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." />
<property name="required-timeout"
description="The minimum time interval in milliseconds for which dynamic IP configuration should be tried before the connection succeeds. This property is useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. Normally the connection succeeds as soon as one of the two address families completes; by setting a required timeout for e.g. IPv4, one can ensure that even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for IPv4 before the connection becomes active. Note that if &quot;may-fail&quot; is FALSE for the same address family, this property has no effect as NetworkManager needs to wait for the full DHCP timeout. A zero value means that no required timeout is present, -1 means the default value (either configuration ipvx.required-timeout override or zero)." />
<property name="ip6-privacy"
description="Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64. This enhances privacy, but could cause problems in some applications, on the other hand. The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses). Having a per-connection setting set to &quot;-1&quot; (unknown) means fallback to global configuration &quot;ipv6.ip6-privacy&quot;. If also global configuration is unspecified or set to &quot;-1&quot;, fallback to read &quot;/proc/sys/net/ipv6/conf/default/use_tempaddr&quot;. Note that this setting is distinct from the Stable Privacy addresses that can be enabled with the &quot;addr-gen-mode&quot; property&apos;s &quot;stable-privacy&quot; setting as another way of avoiding host tracking with IPv6 addresses." />
<property name="addr-gen-mode"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff