summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2018-07-03 19:20:45 +0200
committerLubomir Rintel <lkundrak@v3.sk>2018-09-24 15:17:02 +0200
commit9664f284a1d8575798daa9abf9cd7f49a19b48d9 (patch)
tree15318b40afb20380f0b7e39665f5b21207133d48
parent2cec94bacce4a09c0e5ffa241b8d50fd4702dddc (diff)
downloadNetworkManager-9664f284a1d8575798daa9abf9cd7f49a19b48d9.tar.gz
connectivity: allow limiting the connectivity check to a specified AF
Nothing changes practically, as the NMDevice still starts this with AF_UNSPEC. That is going to change in the following commit. The ugly part: priv->concheck_x[0] in few places. I believe we shouldn't be using union aliasing here, and instead of indexing the v4/v6 arrays by a boolean it should be an enum. I'm not fixing it here, but I eventually plan to if this gets an ACK.
-rw-r--r--src/devices/nm-device.c227
-rw-r--r--src/devices/nm-device.h1
-rw-r--r--src/nm-connectivity.c40
-rw-r--r--src/nm-connectivity.h1
-rw-r--r--src/nm-manager.c7
5 files changed, 173 insertions, 103 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 035165dd34..b145a96257 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -175,6 +175,7 @@ struct _NMDeviceConnectivityHandle {
bool is_periodic:1;
bool is_periodic_bump:1;
bool is_periodic_bump_on_complete:1;
+ int addr_family;
};
typedef struct {
@@ -555,24 +556,24 @@ typedef struct _NMDevicePrivate {
NMLldpListener *lldp_listener;
NMConnectivity *concheck_mgr;
+ CList concheck_lst_head;
+ struct {
+ /* if periodic checks are enabled, this is the source id for the next check. */
+ guint p_cur_id;
- /* if periodic checks are enabled, this is the source id for the next check. */
- guint concheck_p_cur_id;
-
- /* the currently configured max periodic interval. */
- guint concheck_p_max_interval;
+ /* the currently configured max periodic interval. */
+ guint p_max_interval;
- /* the current interval. If we are probing, the interval might be lower
- * then the configured max interval. */
- guint concheck_p_cur_interval;
+ /* the current interval. If we are probing, the interval might be lower
+ * then the configured max interval. */
+ guint p_cur_interval;
- /* the timestamp, when we last scheduled the timer concheck_p_cur_id with current interval
- * concheck_p_cur_interval. */
- gint64 concheck_p_cur_basetime_ns;
+ /* the timestamp, when we last scheduled the timer p_cur_id with current interval
+ * p_cur_interval. */
+ gint64 p_cur_basetime_ns;
- NMConnectivityState connectivity_state;
-
- CList concheck_lst_head;
+ NMConnectivityState state;
+ } concheck_x[2];
guint check_delete_unrealized_id;
@@ -643,7 +644,10 @@ static void _set_mtu (NMDevice *self, guint32 mtu);
static void _commit_mtu (NMDevice *self, const NMIP4Config *config);
static void _cancel_activation (NMDevice *self);
-static void concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_periodic);
+static void concheck_update_state (NMDevice *self,
+ int addr_family,
+ NMConnectivityState state,
+ gboolean is_periodic);
/*****************************************************************************/
@@ -2092,13 +2096,14 @@ nm_device_get_route_metric_default (NMDeviceType device_type)
}
static gboolean
-default_route_metric_penalty_detect (NMDevice *self)
+default_route_metric_penalty_detect (NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
/* currently we don't differentiate between IPv4 and IPv6 when detecting
* connectivity. */
- if ( priv->connectivity_state != NM_CONNECTIVITY_FULL
+ if ( priv->concheck_x[IS_IPv4].state != NM_CONNECTIVITY_FULL
&& nm_connectivity_check_enabled (concheck_get_mgr (self)))
return TRUE;
@@ -2448,24 +2453,36 @@ typedef enum {
} ConcheckScheduleMode;
static NMDeviceConnectivityHandle *concheck_start (NMDevice *self,
+ int addr_family,
NMDeviceConnectivityCallback callback,
gpointer user_data,
gboolean is_periodic);
static void concheck_periodic_schedule_set (NMDevice *self,
+ int addr_family,
ConcheckScheduleMode mode);
static gboolean
-concheck_periodic_timeout_cb (gpointer user_data)
+_concheck_periodic_timeout_cb (NMDevice *self, int addr_family)
{
- NMDevice *self = user_data;
-
_LOGt (LOGD_CONCHECK, "connectivity: periodic timeout");
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_PERIODIC);
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_CHECK_PERIODIC);
return G_SOURCE_REMOVE;
}
static gboolean
+concheck_ip4_periodic_timeout_cb (gpointer user_data)
+{
+ return _concheck_periodic_timeout_cb (user_data, AF_INET);
+}
+
+static gboolean
+concheck_ip6_periodic_timeout_cb (gpointer user_data)
+{
+ return _concheck_periodic_timeout_cb (user_data, AF_INET6);
+}
+
+static gboolean
concheck_is_possible (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@@ -2483,17 +2500,18 @@ concheck_is_possible (NMDevice *self)
}
static gboolean
-concheck_periodic_schedule_do (NMDevice *self, gint64 now_ns)
+concheck_periodic_schedule_do (NMDevice *self, int addr_family, gint64 now_ns)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean periodic_check_disabled = FALSE;
gint64 expiry, tdiff;
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
/* we always cancel whatever was pending. */
- if (nm_clear_g_source (&priv->concheck_p_cur_id))
+ if (nm_clear_g_source (&priv->concheck_x[IS_IPv4].p_cur_id))
periodic_check_disabled = TRUE;
- if (priv->concheck_p_max_interval == 0) {
+ if (priv->concheck_x[IS_IPv4].p_max_interval == 0) {
/* periodic checks are disabled */
goto out;
}
@@ -2502,23 +2520,24 @@ concheck_periodic_schedule_do (NMDevice *self, gint64 now_ns)
goto out;
nm_assert (now_ns > 0);
- nm_assert (priv->concheck_p_cur_interval > 0);
+ nm_assert (priv->concheck_x[IS_IPv4].p_cur_interval > 0);
/* we schedule the timeout based on our current settings cur-interval and cur-basetime.
* Before calling concheck_periodic_schedule_do(), make sure that these properties are
* correct. */
- expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ expiry = priv->concheck_x[IS_IPv4].p_cur_basetime_ns + (priv->concheck_x[IS_IPv4].p_cur_interval * NM_UTILS_NS_PER_SECOND);
tdiff = expiry - now_ns;
_LOGT (LOGD_CONCHECK, "connectivity: periodic-check: %sscheduled in %lld milliseconds (%u seconds interval)",
periodic_check_disabled ? "re-" : "",
(long long) (tdiff / NM_UTILS_NS_PER_MSEC),
- priv->concheck_p_cur_interval);
+ priv->concheck_x[IS_IPv4].p_cur_interval);
- priv->concheck_p_cur_id = g_timeout_add (NM_MAX ((gint64) 0, tdiff) / NM_UTILS_NS_PER_MSEC,
- concheck_periodic_timeout_cb,
- self);
+ priv->concheck_x[IS_IPv4].p_cur_id =
+ g_timeout_add (NM_MAX ((gint64) 0, tdiff) / NM_UTILS_NS_PER_MSEC,
+ IS_IPv4 ? concheck_ip4_periodic_timeout_cb : concheck_ip6_periodic_timeout_cb,
+ self);
return TRUE;
out:
if (periodic_check_disabled)
@@ -2529,19 +2548,19 @@ out:
#define CONCHECK_P_PROBE_INTERVAL 1
static void
-concheck_periodic_schedule_set (NMDevice *self,
- ConcheckScheduleMode mode)
+concheck_periodic_schedule_set (NMDevice *self, int addr_family, ConcheckScheduleMode mode)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gint64 new_expiry, exp_expiry, cur_expiry, tdiff;
gint64 now_ns = 0;
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
- if (priv->concheck_p_max_interval == 0) {
+ if (priv->concheck_x[IS_IPv4].p_max_interval == 0) {
/* periodic check is disabled. Nothing to do. */
return;
}
- if (!priv->concheck_p_cur_id) {
+ if (!priv->concheck_x[IS_IPv4].p_cur_id) {
/* we currently don't have a timeout scheduled. No need to reschedule
* another one... */
if (NM_IN_SET (mode, CONCHECK_SCHEDULE_UPDATE_INTERVAL,
@@ -2555,19 +2574,19 @@ concheck_periodic_schedule_set (NMDevice *self,
switch (mode) {
case CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART:
- priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
- priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
- if (concheck_periodic_schedule_do (self, now_ns))
- concheck_start (self, NULL, NULL, TRUE);
+ priv->concheck_x[IS_IPv4].p_cur_interval = NM_MIN (priv->concheck_x[IS_IPv4].p_max_interval, CONCHECK_P_PROBE_INTERVAL);
+ priv->concheck_x[IS_IPv4].p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ if (concheck_periodic_schedule_do (self, addr_family, now_ns))
+ concheck_start (self, addr_family, NULL, NULL, TRUE);
return;
case CONCHECK_SCHEDULE_UPDATE_INTERVAL:
- /* called with "UPDATE_INTERVAL" and already have a concheck_p_cur_id scheduled. */
+ /* called with "UPDATE_INTERVAL" and already have a p_cur_id scheduled. */
- nm_assert (priv->concheck_p_max_interval > 0);
- nm_assert (priv->concheck_p_cur_interval > 0);
+ nm_assert (priv->concheck_x[IS_IPv4].p_max_interval > 0);
+ nm_assert (priv->concheck_x[IS_IPv4].p_cur_interval > 0);
- if (priv->concheck_p_cur_interval <= priv->concheck_p_max_interval) {
+ if (priv->concheck_x[IS_IPv4].p_cur_interval <= priv->concheck_x[IS_IPv4].p_max_interval) {
/* we currently have a shorter interval set, than what we now have. Either,
* because we are probing, or because the previous max interval was shorter.
*
@@ -2576,17 +2595,17 @@ concheck_periodic_schedule_set (NMDevice *self,
return;
}
- cur_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_max_interval * NM_UTILS_NS_PER_SECOND);
+ cur_expiry = priv->concheck_x[IS_IPv4].p_cur_basetime_ns + (priv->concheck_x[IS_IPv4].p_max_interval * NM_UTILS_NS_PER_SECOND);
nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
- priv->concheck_p_cur_interval = priv->concheck_p_max_interval;
+ priv->concheck_x[IS_IPv4].p_cur_interval = priv->concheck_x[IS_IPv4].p_max_interval;
if (cur_expiry <= now_ns) {
/* Since the last time we scheduled a periodic check, already more than the
* new max_interval passed. We need to start a check right away (and
* schedule a timeout in cur-interval in the future). */
- priv->concheck_p_cur_basetime_ns = now_ns;
- if (concheck_periodic_schedule_do (self, now_ns))
- concheck_start (self, NULL, NULL, TRUE);
+ priv->concheck_x[IS_IPv4].p_cur_basetime_ns = now_ns;
+ if (concheck_periodic_schedule_do (self, addr_family, now_ns))
+ concheck_start (self, addr_family, NULL, NULL, TRUE);
} else {
/* we are reducing the max-interval to a shorter interval that we have currently
* scheduled (with cur_interval).
@@ -2594,24 +2613,26 @@ concheck_periodic_schedule_set (NMDevice *self,
* However, since the last time we scheduled the check, not even the new max-interval
* expired. All we need to do, is reschedule the timer to expire sooner. The cur_basetime
* is unchanged. */
- concheck_periodic_schedule_do (self, now_ns);
+ concheck_periodic_schedule_do (self, addr_family, now_ns);
}
return;
case CONCHECK_SCHEDULE_CHECK_EXTERNAL:
/* a external connectivity check delays our periodic check. We reset the counter. */
- priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
- concheck_periodic_schedule_do (self, now_ns);
+ priv->concheck_x[IS_IPv4].p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ concheck_periodic_schedule_do (self, addr_family, now_ns);
return;
case CONCHECK_SCHEDULE_CHECK_PERIODIC:
{
gboolean any_periodic_pending;
NMDeviceConnectivityHandle *handle;
- guint old_interval = priv->concheck_p_cur_interval;
+ guint old_interval = priv->concheck_x[IS_IPv4].p_cur_interval;
any_periodic_pending = FALSE;
c_list_for_each_entry (handle, &priv->concheck_lst_head, concheck_lst) {
+ if (handle->addr_family != addr_family)
+ continue;
if (handle->is_periodic_bump) {
handle->is_periodic_bump = FALSE;
handle->is_periodic_bump_on_complete = FALSE;
@@ -2622,7 +2643,7 @@ concheck_periodic_schedule_set (NMDevice *self,
/* we reached a timeout to schedule a new periodic request, however we still
* have period requests pending that didn't complete yet. We need to bump the
* interval already. */
- priv->concheck_p_cur_interval = NM_MIN (old_interval * 2, priv->concheck_p_max_interval);
+ priv->concheck_x[IS_IPv4].p_cur_interval = NM_MIN (old_interval * 2, priv->concheck_x[IS_IPv4].p_max_interval);
}
/* we just reached a timeout. The expected expiry (exp_expiry) should be
@@ -2630,13 +2651,13 @@ concheck_periodic_schedule_set (NMDevice *self,
*
* We want to reschedule the timeout at exp_expiry (aka now) + cur_interval. */
nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
- exp_expiry = priv->concheck_p_cur_basetime_ns + (old_interval * NM_UTILS_NS_PER_SECOND);
- new_expiry = exp_expiry + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ exp_expiry = priv->concheck_x[IS_IPv4].p_cur_basetime_ns + (old_interval * NM_UTILS_NS_PER_SECOND);
+ new_expiry = exp_expiry + (priv->concheck_x[IS_IPv4].p_cur_interval * NM_UTILS_NS_PER_SECOND);
tdiff = NM_MAX (new_expiry - now_ns, 0);
- priv->concheck_p_cur_basetime_ns = (now_ns + tdiff) - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
- if (concheck_periodic_schedule_do (self, now_ns)) {
- handle = concheck_start (self, NULL, NULL, TRUE);
- if (old_interval != priv->concheck_p_cur_interval) {
+ priv->concheck_x[IS_IPv4].p_cur_basetime_ns = (now_ns + tdiff) - (priv->concheck_x[IS_IPv4].p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ if (concheck_periodic_schedule_do (self, addr_family, now_ns)) {
+ handle = concheck_start (self, addr_family, NULL, NULL, TRUE);
+ if (old_interval != priv->concheck_x[IS_IPv4].p_cur_interval) {
/* we just bumped the interval already when scheduling this check.
* When the handle returns, don't bump a second time.
*
@@ -2651,13 +2672,13 @@ concheck_periodic_schedule_set (NMDevice *self,
/* we just got an event that we lost connectivity (that is, concheck returned). We reset
* the interval to min/max or increase the probe interval (bump). */
case CONCHECK_SCHEDULE_RETURNED_MIN:
- priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
+ priv->concheck_x[IS_IPv4].p_cur_interval = NM_MIN (priv->concheck_x[IS_IPv4].p_max_interval, CONCHECK_P_PROBE_INTERVAL);
break;
case CONCHECK_SCHEDULE_RETURNED_MAX:
- priv->concheck_p_cur_interval = priv->concheck_p_max_interval;
+ priv->concheck_x[IS_IPv4].p_cur_interval = priv->concheck_x[IS_IPv4].p_max_interval;
break;
case CONCHECK_SCHEDULE_RETURNED_BUMP:
- priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_cur_interval * 2, priv->concheck_p_max_interval);
+ priv->concheck_x[IS_IPv4].p_cur_interval = NM_MIN (priv->concheck_x[IS_IPv4].p_cur_interval * 2, priv->concheck_x[IS_IPv4].p_max_interval);
break;
}
@@ -2667,38 +2688,40 @@ concheck_periodic_schedule_set (NMDevice *self,
* last check, instead of counting from now. The reason is that we want that the times
* when we schedule checks be at precise intervals, without including the time it took for
* the connectivity check. */
- new_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ new_expiry = priv->concheck_x[IS_IPv4].p_cur_basetime_ns + (priv->concheck_x[IS_IPv4].p_cur_interval * NM_UTILS_NS_PER_SECOND);
tdiff = NM_MAX (new_expiry - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns), 0);
- priv->concheck_p_cur_basetime_ns = now_ns + tdiff - (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
- concheck_periodic_schedule_do (self, now_ns);
+ priv->concheck_x[IS_IPv4].p_cur_basetime_ns = now_ns + tdiff - (priv->concheck_x[IS_IPv4].p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ concheck_periodic_schedule_do (self, addr_family, now_ns);
}
static void
-concheck_update_interval (NMDevice *self, gboolean check_now)
+concheck_update_interval (NMDevice *self, int addr_family, gboolean check_now)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint new_interval;
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
new_interval = nm_connectivity_get_interval (concheck_get_mgr (self));
new_interval = NM_MIN (new_interval, 7 *24 * 3600);
- if (new_interval != priv->concheck_p_max_interval) {
+ if (new_interval != priv->concheck_x[IS_IPv4].p_max_interval) {
_LOGT (LOGD_CONCHECK, "connectivity: periodic-check: set interval to %u seconds", new_interval);
- priv->concheck_p_max_interval = new_interval;
+ priv->concheck_x[IS_IPv4].p_max_interval = new_interval;
}
if (!new_interval) {
/* this will cancel any potentially pending timeout because max-interval is zero.
* But it logs a nice message... */
- concheck_periodic_schedule_do (self, 0);
+ concheck_periodic_schedule_do (self, addr_family, 0);
/* also update the fake connectivity state. */
- concheck_update_state (self, NM_CONNECTIVITY_FAKE, TRUE);
+ concheck_update_state (self, addr_family, NM_CONNECTIVITY_FAKE, TRUE);
return;
}
concheck_periodic_schedule_set (self,
+ addr_family,
check_now
? CONCHECK_SCHEDULE_UPDATE_INTERVAL_RESTART
: CONCHECK_SCHEDULE_UPDATE_INTERVAL);
@@ -2707,13 +2730,16 @@ concheck_update_interval (NMDevice *self, gboolean check_now)
void
nm_device_check_connectivity_update_interval (NMDevice *self)
{
- concheck_update_interval (self, FALSE);
+ concheck_update_interval (self, AF_INET, FALSE);
+ concheck_update_interval (self, AF_INET6, FALSE);
}
static void
-concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow_periodic_bump)
+concheck_update_state (NMDevice *self, int addr_family,
+ NMConnectivityState state, gboolean allow_periodic_bump)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
/* @state is a result of the connectivity check. We only expect a precise
* number of possible values. */
@@ -2726,7 +2752,7 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow
if (state == NM_CONNECTIVITY_ERROR) {
/* on error, we don't change the current connectivity state,
* except making UNKNOWN to NONE. */
- state = priv->connectivity_state;
+ state = priv->concheck_x[IS_IPv4].state;
if (state == NM_CONNECTIVITY_UNKNOWN)
state = NM_CONNECTIVITY_NONE;
} else if (state == NM_CONNECTIVITY_FAKE) {
@@ -2745,11 +2771,11 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow
state = NM_CONNECTIVITY_NONE;
}
- if (priv->connectivity_state == state) {
+ if (priv->concheck_x[IS_IPv4].state == state) {
/* we got a connectivty update, but the state didn't change. If we were probing,
* we bump the probe frequency. */
if (allow_periodic_bump)
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_RETURNED_BUMP);
return;
}
/* we need to update the probe interval before emitting signals. Emitting
@@ -2758,20 +2784,20 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow
if (state == NM_CONNECTIVITY_FULL) {
/* we reached full connectivity state. Stop probing by setting the
* interval to the max. */
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MAX);
- } else if (priv->connectivity_state == NM_CONNECTIVITY_FULL) {
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_RETURNED_MAX);
+ } else if (priv->concheck_x[IS_IPv4].state == NM_CONNECTIVITY_FULL) {
/* we are about to loose connectivity. (re)start probing by setting
* the timeout interval to the min. */
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MIN);
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_RETURNED_MIN);
} else {
if (allow_periodic_bump)
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_RETURNED_BUMP);
}
_LOGD (LOGD_CONCHECK, "connectivity state changed from %s to %s",
- nm_connectivity_state_to_string (priv->connectivity_state),
+ nm_connectivity_state_to_string (priv->concheck_x[IS_IPv4].state),
nm_connectivity_state_to_string (state));
- priv->connectivity_state = state;
+ priv->concheck_x[IS_IPv4].state = state;
_notify (self, PROP_CONNECTIVITY);
g_signal_emit (self, signals[CONNECTIVITY_CHANGED], 0);
@@ -2788,9 +2814,10 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow
}
static void
-concheck_handle_complete (NMDeviceConnectivityHandle *handle,
- GError *error)
+concheck_handle_complete (NMDeviceConnectivityHandle *handle, GError *error)
{
+ const gboolean IS_IPv4 = (handle->addr_family == AF_INET);
+
/* The moment we invoke the callback, we unlink it. It signals
* that @handle is handled -- as far as the callee of callback
* is concerned. */
@@ -2802,7 +2829,7 @@ concheck_handle_complete (NMDeviceConnectivityHandle *handle,
if (handle->callback) {
handle->callback (handle->self,
handle,
- NM_DEVICE_GET_PRIVATE (handle->self)->connectivity_state,
+ NM_DEVICE_GET_PRIVATE (handle->self)->concheck_x[IS_IPv4].state,
error,
handle->user_data);
}
@@ -2864,6 +2891,8 @@ concheck_cb (NMConnectivity *connectivity,
any_periodic_before = FALSE;
any_periodic_after = FALSE;
c_list_for_each_entry (other_handle, &priv->concheck_lst_head, concheck_lst) {
+ if (other_handle->addr_family != handle->addr_family)
+ continue;
if (other_handle->is_periodic_bump_on_complete) {
if (other_handle->seq < seq)
any_periodic_before = TRUE;
@@ -2890,7 +2919,7 @@ concheck_cb (NMConnectivity *connectivity,
}
/* first update the new state, and emit signals. */
- concheck_update_state (self, state, allow_periodic_bump);
+ concheck_update_state (self, handle->addr_family, state, allow_periodic_bump);
handle_is_alive = FALSE;
@@ -2902,6 +2931,8 @@ concheck_cb (NMConnectivity *connectivity,
* @handle, as they are automatically obsoleted. */
check_handles:
c_list_for_each_entry (other_handle, &priv->concheck_lst_head, concheck_lst) {
+ if (other_handle->addr_family != handle->addr_family)
+ continue;
if (other_handle->seq >= seq) {
/* it's not guaranteed that @handle is still in the list. It might already
* be canceled while invoking callbacks for a previous other_handle.
@@ -2939,6 +2970,7 @@ check_handles:
static NMDeviceConnectivityHandle *
concheck_start (NMDevice *self,
+ int addr_family,
NMDeviceConnectivityCallback callback,
gpointer user_data,
gboolean is_periodic)
@@ -2959,6 +2991,7 @@ concheck_start (NMDevice *self,
handle->is_periodic = is_periodic;
handle->is_periodic_bump = is_periodic;
handle->is_periodic_bump_on_complete = is_periodic;
+ handle->addr_family = addr_family;
c_list_link_tail (&priv->concheck_lst_head, &handle->concheck_lst);
@@ -2967,6 +3000,7 @@ concheck_start (NMDevice *self,
is_periodic ? ", periodic-check" : "");
handle->c_handle = nm_connectivity_check_start (concheck_get_mgr (self),
+ handle->addr_family,
nm_device_get_ip_ifindex (self),
nm_device_get_ip_iface (self),
concheck_cb,
@@ -2976,6 +3010,7 @@ concheck_start (NMDevice *self,
NMDeviceConnectivityHandle *
nm_device_check_connectivity (NMDevice *self,
+ int addr_family,
NMDeviceConnectivityCallback callback,
gpointer user_data)
{
@@ -2984,8 +3019,8 @@ nm_device_check_connectivity (NMDevice *self,
if (!concheck_is_possible (self))
return NULL;
- concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_EXTERNAL);
- handle = concheck_start (self, callback, user_data, FALSE);
+ concheck_periodic_schedule_set (self, addr_family, CONCHECK_SCHEDULE_CHECK_EXTERNAL);
+ handle = concheck_start (self, addr_family, callback, user_data, FALSE);
return handle;
}
@@ -3009,9 +3044,13 @@ nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle)
NMConnectivityState
nm_device_get_connectivity_state (NMDevice *self)
{
+ NMDevicePrivate *priv;
+
g_return_val_if_fail (NM_IS_DEVICE (self), NM_CONNECTIVITY_UNKNOWN);
- return NM_DEVICE_GET_PRIVATE (self)->connectivity_state;
+ priv = NM_DEVICE_GET_PRIVATE (self);
+
+ return NM_MAX (priv->concheck_x[0].state, priv->concheck_x[1].state);
}
/*****************************************************************************/
@@ -7083,7 +7122,7 @@ ip_config_merge_and_apply (NMDevice *self,
if (commit) {
gboolean v;
- v = default_route_metric_penalty_detect (self);
+ v = default_route_metric_penalty_detect (self, addr_family);
if (IS_IPv4)
priv->default_route_metric_penalty_ip4_has = v;
else
@@ -14851,8 +14890,8 @@ _set_state_full (NMDevice *self,
if (ip_config_valid (old_state) && !ip_config_valid (state))
notify_ip_properties (self);
- concheck_update_interval (self,
- state == NM_DEVICE_STATE_ACTIVATED);
+ concheck_update_interval (self, AF_INET, state == NM_DEVICE_STATE_ACTIVATED);
+ concheck_update_interval (self, AF_INET6, state == NM_DEVICE_STATE_ACTIVATED);
/* Dispose of the cached activation request */
if (req)
@@ -15816,7 +15855,8 @@ nm_device_init (NMDevice *self)
c_list_init (&self->devices_lst);
c_list_init (&priv->slaves);
- priv->connectivity_state = NM_CONNECTIVITY_UNKNOWN;
+ priv->concheck_x[0].state = NM_CONNECTIVITY_UNKNOWN;
+ priv->concheck_x[1].state = NM_CONNECTIVITY_UNKNOWN;
nm_dbus_track_obj_path_init (&priv->parent_device, G_OBJECT (self), obj_properties[PROP_PARENT]);
nm_dbus_track_obj_path_init (&priv->act_request, G_OBJECT (self), obj_properties[PROP_ACTIVE_CONNECTION]);
@@ -16017,7 +16057,8 @@ dispose (GObject *object)
g_clear_object (&priv->lldp_listener);
}
- nm_clear_g_source (&priv->concheck_p_cur_id);
+ nm_clear_g_source (&priv->concheck_x[0].p_cur_id);
+ nm_clear_g_source (&priv->concheck_x[1].p_cur_id);
G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
@@ -16355,7 +16396,7 @@ get_property (GObject *object, guint prop_id,
g_value_set_uint64 (value, priv->stats.rx_bytes);
break;
case PROP_CONNECTIVITY:
- g_value_set_uint (value, priv->connectivity_state);
+ g_value_set_uint (value, nm_device_get_connectivity_state (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 056d1c9cab..d32bf25250 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -818,6 +818,7 @@ typedef void (*NMDeviceConnectivityCallback) (NMDevice *self,
void nm_device_check_connectivity_update_interval (NMDevice *self);
NMDeviceConnectivityHandle *nm_device_check_connectivity (NMDevice *self,
+ int addr_family,
NMDeviceConnectivityCallback callback,
gpointer user_data);
diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c
index 2ce5481b49..3e39960b4d 100644
--- a/src/nm-connectivity.c
+++ b/src/nm-connectivity.c
@@ -68,6 +68,7 @@ struct _NMConnectivityCheckHandle {
gpointer user_data;
char *ifspec;
+ int addr_family;
#if WITH_CONCHECK
struct {
@@ -145,9 +146,10 @@ NM_DEFINE_SINGLETON_GETTER (NMConnectivity, nm_connectivity_get, NM_TYPE_CONNECT
_nm_log (__level, _NMLOG2_DOMAIN, 0, \
(cb_data->ifspec ? &cb_data->ifspec[3] : NULL), \
NULL, \
- "connectivity: (%s) " \
+ "connectivity: (%s,AF_INET%s) " \
_NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
- (cb_data->ifspec ? &cb_data->ifspec[3] : "") \
+ (cb_data->ifspec ? &cb_data->ifspec[3] : ""), \
+ (cb_data->addr_family == AF_INET6 ? "6" : "") \
_NM_UTILS_MACRO_REST (__VA_ARGS__)); \
} \
} G_STMT_END
@@ -572,6 +574,7 @@ do_curl_request (NMConnectivityCheckHandle *cb_data)
{
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (cb_data->self);
CURL *ehandle;
+ long resolve;
ehandle = curl_easy_init ();
if (!ehandle) {
@@ -579,6 +582,21 @@ do_curl_request (NMConnectivityCheckHandle *cb_data)
return;
}
+ switch (cb_data->addr_family) {
+ case AF_INET:
+ resolve = CURL_IPRESOLVE_V4;
+ break;
+ case AF_INET6:
+ resolve = CURL_IPRESOLVE_V6;
+ break;
+ case AF_UNSPEC:
+ resolve = CURL_IPRESOLVE_WHATEVER;
+ break;
+ default:
+ resolve = CURL_IPRESOLVE_WHATEVER;
+ g_warn_if_reached ();
+ }
+
cb_data->concheck.response = g_strdup (priv->response);
cb_data->concheck.curl_ehandle = ehandle;
cb_data->concheck.request_headers = curl_slist_append (NULL, "Connection: close");
@@ -593,6 +611,7 @@ do_curl_request (NMConnectivityCheckHandle *cb_data)
curl_easy_setopt (ehandle, CURLOPT_HTTPHEADER, cb_data->concheck.request_headers);
curl_easy_setopt (ehandle, CURLOPT_INTERFACE, cb_data->ifspec);
curl_easy_setopt (ehandle, CURLOPT_RESOLVE, cb_data->concheck.hosts);
+ curl_easy_setopt (ehandle, CURLOPT_IPRESOLVE, resolve);
curl_multi_add_handle (priv->concheck.curl_mhandle, ehandle);
}
@@ -607,7 +626,7 @@ resolve_cb (GObject *object, GAsyncResult *res, gpointer user_data)
GVariant *addresses;
gsize no_addresses;
int ifindex;
- int family;
+ int addr_family;
GVariant *address = NULL;
const guchar *address_buf;
gsize len = 0;
@@ -635,14 +654,13 @@ resolve_cb (GObject *object, GAsyncResult *res, gpointer user_data)
g_variant_unref (result);
for (i = 0; i < no_addresses; i++) {
- g_variant_get_child (addresses, i, "(ii@ay)", &ifindex, &family, &address);
+ g_variant_get_child (addresses, i, "(ii@ay)", &ifindex, &addr_family, &address);
address_buf = g_variant_get_fixed_array (address, &len, 1);
- if ( (family == AF_INET && len == sizeof (struct in_addr))
- || (family == AF_INET6 && len == sizeof (struct in6_addr))) {
- inet_ntop (family, address_buf, str, sizeof (str));
- host = g_strdup_printf ("%s:%s:%s", priv->host,
- priv->port ? priv->port : "80", str);
+ if ( (addr_family == AF_INET && len == sizeof (struct in_addr))
+ || (addr_family == AF_INET6 && len == sizeof (struct in6_addr))) {
+ inet_ntop (addr_family, address_buf, str, sizeof (str));
+ host = g_strdup_printf ("%s:%s:%s", priv->host, priv->port ?: "80", str);
cb_data->concheck.hosts = curl_slist_append (cb_data->concheck.hosts, host);
_LOG2T ("adding '%s' to curl resolve list", host);
g_free (host);
@@ -685,7 +703,7 @@ resolved_proxy_created (GObject *object, GAsyncResult *res, gpointer user_data)
g_variant_new ("(isit)",
cb_data->concheck.ifindex,
priv->host,
- (gint32) AF_UNSPEC,
+ (gint32) cb_data->addr_family,
(guint64) SD_RESOLVED_DNS),
G_DBUS_CALL_FLAGS_NONE,
-1,
@@ -699,6 +717,7 @@ resolved_proxy_created (GObject *object, GAsyncResult *res, gpointer user_data)
NMConnectivityCheckHandle *
nm_connectivity_check_start (NMConnectivity *self,
+ int addr_family,
int ifindex,
const char *iface,
NMConnectivityCheckCallback callback,
@@ -719,6 +738,7 @@ nm_connectivity_check_start (NMConnectivity *self,
cb_data->callback = callback;
cb_data->user_data = user_data;
cb_data->completed_state = NM_CONNECTIVITY_UNKNOWN;
+ cb_data->addr_family = addr_family;
if (iface)
cb_data->ifspec = g_strdup_printf ("if!%s", iface);
diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h
index 2bf07bc080..fad248be7b 100644
--- a/src/nm-connectivity.h
+++ b/src/nm-connectivity.h
@@ -58,6 +58,7 @@ typedef void (*NMConnectivityCheckCallback) (NMConnectivity *self,
gpointer user_data);
NMConnectivityCheckHandle *nm_connectivity_check_start (NMConnectivity *self,
+ int family,
int ifindex,
const char *iface,
NMConnectivityCheckCallback callback,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 27d7c5ad98..120cecd928 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2812,6 +2812,7 @@ device_realized (NMDevice *device,
static void
device_connectivity_changed (NMDevice *device,
+ GParamSpec *pspec,
NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
@@ -6041,6 +6042,12 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
if (nm_device_check_connectivity (device,
+ AF_INET,
+ device_connectivity_done,
+ data))
+ data->remaining++;
+ if (nm_device_check_connectivity (device,
+ AF_INET6,
device_connectivity_done,
data))
data->remaining++;