From 54f9a670f75d08ed9a4b1c5f8d5cda0f7104f7ea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 15 Nov 2012 17:52:24 -0600 Subject: [PATCH] core: allow device subclasses to postpone IPv4 or IPv6 configuration If, for example, a bond interface has dynamic IPv4 configuration and static IPv6 configuration, then without slaves IPv6 config can proceed but IPv4 cannot until a slave is present. Allow subclasses to postpone a specific IP configuration path until they're ready, but let others proceed. --- src/nm-device-private.h | 5 ++ src/nm-device.c | 106 +++++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/src/nm-device-private.h b/src/nm-device-private.h index a056ae66e3..57e16c0f88 100644 --- a/src/nm-device-private.h +++ b/src/nm-device-private.h @@ -30,6 +30,7 @@ enum NMActStageReturn { NM_ACT_STAGE_RETURN_FAILURE = 0, NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */ NM_ACT_STAGE_RETURN_POSTPONE, /* Long-running operation in progress */ + NM_ACT_STAGE_RETURN_WAIT, /* Not ready to start stage; wait */ NM_ACT_STAGE_RETURN_STOP /* Activation stage done; nothing to do */ }; @@ -37,6 +38,10 @@ void nm_device_set_ip_iface (NMDevice *self, const char *iface); void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); +gboolean nm_device_activate_stage3_ip4_start (NMDevice *self); + +gboolean nm_device_activate_stage3_ip6_start (NMDevice *self); + gboolean nm_device_hw_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmware); void nm_device_hw_take_down (NMDevice *self, gboolean block); diff --git a/src/nm-device.c b/src/nm-device.c index 53c4e29edb..2faf51c155 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -139,6 +139,7 @@ G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT) typedef enum { IP_NONE = 0, + IP_WAIT, IP_CONF, IP_DONE } IpState; @@ -2649,6 +2650,79 @@ act_stage3_ip6_config_start (NMDevice *self, return ret; } +/** + * nm_device_activate_stage3_ip4_start: + * @self: the device + * + * Try starting IPv4 configuration. + */ +gboolean +nm_device_activate_stage3_ip4_start (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMIP4Config *ip4_config = NULL; + + g_assert (priv->ip4_state == IP_WAIT); + + priv->ip4_state = IP_CONF; + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip4_config); + nm_device_activate_schedule_ip4_config_result (self, ip4_config); + g_object_unref (ip4_config); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + return FALSE; + } else if (ret == NM_ACT_STAGE_RETURN_STOP) { + /* Early finish */ + priv->ip4_state = IP_DONE; + } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { + /* Wait for something to try IP config again */ + priv->ip4_state = IP_WAIT; + } else + g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); + + return TRUE; +} + +/** + * nm_device_activate_stage3_ip6_start: + * @self: the device + * + * Try starting IPv6 configuration. + */ +gboolean +nm_device_activate_stage3_ip6_start (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMActStageReturn ret; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + NMIP6Config *ip6_config = NULL; + + g_assert (priv->ip6_state == IP_WAIT); + + priv->ip6_state = IP_CONF; + ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); + if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { + g_assert (ip6_config); + nm_device_activate_schedule_ip6_config_result (self, ip6_config); + g_object_unref (ip6_config); + } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + return FALSE; + } else if (ret == NM_ACT_STAGE_RETURN_STOP) { + /* Early finish */ + priv->ip6_state = IP_DONE; + } else if (ret == NM_ACT_STAGE_RETURN_WAIT) { + /* Wait for something to try IP config again */ + priv->ip6_state = IP_WAIT; + } else + g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); + + return TRUE; +} /* * nm_device_activate_stage3_ip_config_start @@ -2662,10 +2736,6 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data) NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *iface; - NMActStageReturn ret; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - NMIP4Config *ip4_config = NULL; - NMIP6Config *ip6_config = NULL; int ifindex; NMDevice *master; @@ -2681,7 +2751,7 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data) if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE)) nm_system_iface_set_up (ifindex, TRUE, NULL); - priv->ip4_state = priv->ip6_state = IP_CONF; + priv->ip4_state = priv->ip6_state = IP_WAIT; /* If the device is a slave, then we don't do any IP configuration but we * use the IP config stage to indicate to the master we're ready for @@ -2703,34 +2773,12 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data) } /* IPv4 */ - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - g_assert (ip4_config); - nm_device_activate_schedule_ip4_config_result (self, ip4_config); - g_object_unref (ip4_config); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + if (!nm_device_activate_stage3_ip4_start (self)) goto out; - } else if (ret == NM_ACT_STAGE_RETURN_STOP) { - /* Nothing to do */ - priv->ip4_state = IP_DONE; - } else - g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); /* IPv6 */ - ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - g_assert (ip6_config); - nm_device_activate_schedule_ip6_config_result (self, ip6_config); - g_object_unref (ip6_config); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + if (!nm_device_activate_stage3_ip6_start (self)) goto out; - } else if (ret == NM_ACT_STAGE_RETURN_STOP) { - /* Nothing to do */ - priv->ip6_state = IP_DONE; - } else - g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE); out: nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);