summary refs log tree commit diff
path: root/src/nm-device-wired.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-device-wired.c')
-rw-r--r--src/nm-device-wired.c235
1 files changed, 75 insertions, 160 deletions
diff --git a/src/nm-device-wired.c b/src/nm-device-wired.c
index 44510fc6..6d459630 100644
--- a/src/nm-device-wired.c
+++ b/src/nm-device-wired.c
@@ -49,9 +49,6 @@ G_DEFINE_TYPE (NMDeviceWired, nm_device_wired, NM_TYPE_DEVICE)
 #define NM_DEVICE_WIRED_LOG_LEVEL(dev) ((nm_device_get_device_type (dev) == NM_DEVICE_TYPE_INFINIBAND) ? LOGD_INFINIBAND : LOGD_ETHER)
 
 typedef struct {
-	guint8              hw_addr[NM_UTILS_HWADDR_LEN_MAX];         /* Currently set MAC address */
-	guint               hw_addr_type;
-	guint               hw_addr_len;
 	gboolean            carrier;
 	guint32             speed;
 
@@ -134,31 +131,37 @@ carrier_action_defer_clear (NMDeviceWired *self)
 	}
 }
 
-static gboolean
-carrier_action_defer_cb (gpointer user_data)
+static void
+carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
 {
-	NMDeviceWired *self = NM_DEVICE_WIRED (user_data);
-	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
-	NMDeviceState state;
+	NMDevice *device = NM_DEVICE (self);
 
-	priv->carrier_action_defer_id = 0;
-
-	state = nm_device_get_state (NM_DEVICE (self));
 	if (state == NM_DEVICE_STATE_UNAVAILABLE) {
-		if (priv->carrier)
-			nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
+		if (carrier)
+			nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
 		else {
 			/* clear any queued state changes if they wouldn't be valid when the
 			 * carrier is off.
 			 */
-			if (nm_device_queued_state_peek (NM_DEVICE (self)) >= NM_DEVICE_STATE_DISCONNECTED)
-				nm_device_queued_state_clear (NM_DEVICE (self));
+			if (nm_device_queued_state_peek (device) >= NM_DEVICE_STATE_DISCONNECTED)
+				nm_device_queued_state_clear (device);
 		}
 	} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
-		if (!priv->carrier)
-			nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
+		if (!carrier && !nm_device_get_enslaved (device))
+			nm_device_queue_state (device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
 	}
+}
 
+static gboolean
+carrier_action_defer_cb (gpointer user_data)
+{
+	NMDeviceWired *self = NM_DEVICE_WIRED (user_data);
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+
+	priv->carrier_action_defer_id = 0;
+	NM_DEVICE_WIRED_GET_CLASS (self)->carrier_action (self,
+	                                                  nm_device_get_state (NM_DEVICE (self)),
+	                                                  priv->carrier);
 	return FALSE;
 }
 
@@ -167,13 +170,11 @@ set_carrier (NMDeviceWired *self,
              const gboolean carrier,
              const gboolean defer_action)
 {
-	NMDeviceWiredPrivate *priv;
+	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
+	NMDevice *device = NM_DEVICE (self);
 	NMDeviceState state;
 	guint32 caps;
 
-	g_return_if_fail (NM_IS_DEVICE (self));
-
-	priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
 	if (priv->carrier == carrier)
 		return;
 
@@ -184,22 +185,32 @@ set_carrier (NMDeviceWired *self,
 	 * doesn't support carrier detect.  These devices assume
 	 * the carrier is always up.
 	 */
-	caps = nm_device_get_capabilities (NM_DEVICE (self));
+	caps = nm_device_get_capabilities (device);
 	g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT);
 
 	priv->carrier = carrier;
-	g_object_notify (G_OBJECT (self), "carrier");
 
-	state = nm_device_get_state (NM_DEVICE (self));
+	state = nm_device_get_state (device);
 	if (state >= NM_DEVICE_STATE_UNAVAILABLE) {
-		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
+		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (device),
 		             "(%s): carrier now %s (device state %d%s)",
-		             nm_device_get_iface (NM_DEVICE (self)),
+		             nm_device_get_iface (device),
 		             carrier ? "ON" : "OFF",
 		             state,
 		             defer_action ? ", deferring action for 4 seconds" : "");
 	}
 
+	g_object_notify (G_OBJECT (self), "carrier");
+
+	/* Retry IP configuration for master devices now that the carrier is on */
+	if (nm_device_is_master (device) && priv->carrier) {
+		if (nm_device_activate_ip4_state_in_wait (device))
+			nm_device_activate_stage3_ip4_start (device);
+
+		if (nm_device_activate_ip6_state_in_wait (device))
+			nm_device_activate_stage3_ip6_start (device);
+	}
+
 	if (defer_action)
 		priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
 	else
@@ -301,22 +312,6 @@ constructor (GType type,
 	            nm_device_get_iface (NM_DEVICE (self)),
 	            nm_device_get_ifindex (NM_DEVICE (self)));
 
-	if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_ETHERNET) {
-		priv->hw_addr_type = ARPHRD_ETHER;
-		priv->hw_addr_len = ETH_ALEN;
-	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_INFINIBAND) {
-		priv->hw_addr_type = ARPHRD_INFINIBAND;
-		priv->hw_addr_len = INFINIBAND_ALEN;
-	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_BOND) {
-		/* We may not know the hardware address type until a slave is added */
-		priv->hw_addr_type = ARPHRD_ETHER;
-		priv->hw_addr_len = ETH_ALEN;
-	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_BRIDGE) {
-		priv->hw_addr_type = ARPHRD_ETHER;
-		priv->hw_addr_len = ETH_ALEN;
-	} else
-		g_assert_not_reached ();
-
 	caps = nm_device_get_capabilities (self);
 	if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
 		/* Only listen to netlink for cards that support carrier detect */
@@ -357,70 +352,20 @@ nm_device_wired_init (NMDeviceWired * self)
 }
 
 static gboolean
-hw_is_up (NMDevice *device)
-{
-	return nm_system_iface_is_up (nm_device_get_ip_ifindex (device));
-}
-
-static gboolean
 hw_bring_up (NMDevice *dev, gboolean *no_firmware)
 {
-	gboolean success, carrier;
+	gboolean result, carrier;
 	guint32 caps;
 
-	success = nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware);
-	if (success) {
+	result = NM_DEVICE_CLASS(nm_device_wired_parent_class)->hw_bring_up (dev, no_firmware);
+	if (result) {
 		caps = nm_device_get_capabilities (dev);
 		if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
 			carrier = get_carrier_sync (NM_DEVICE_WIRED (dev));
 			set_carrier (NM_DEVICE_WIRED (dev), carrier, carrier ? FALSE : TRUE);
 		}
 	}
-	return success;
-}
-
-static void
-hw_take_down (NMDevice *dev)
-{
-	nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL);
-}
-
-static void
-update_hw_address (NMDevice *dev)
-{
-	NMDeviceWired *self = NM_DEVICE_WIRED (dev);
-	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
-	struct rtnl_link *rtnl;
-	struct nl_addr *addr;
-
-	rtnl = nm_netlink_index_to_rtnl_link (nm_device_get_ip_ifindex (dev));
-	if (!rtnl) {
-		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
-		            "(%s) failed to read hardware address (error %d)",
-		            nm_device_get_iface (dev), errno);
-		return;
-	}
-
-	addr = rtnl_link_get_addr (rtnl);
-	if (!addr) {
-		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
-		            "(%s) no hardware address?",
-		            nm_device_get_iface (dev));
-		rtnl_link_put (rtnl);
-		return;
-	}
-
-	if (nl_addr_get_len (addr) != priv->hw_addr_len) {
-		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
-		            "(%s) hardware address is wrong length (expected %d got %d)",
-		            nm_device_get_iface (dev),
-		            priv->hw_addr_len, nl_addr_get_len (addr));
-	} else {
-		memcpy (&priv->hw_addr, nl_addr_get_binary_addr (addr),
-				priv->hw_addr_len);
-	}
-
-	rtnl_link_put (rtnl);
+	return result;
 }
 
 static gboolean
@@ -468,6 +413,36 @@ connection_match_config (NMDevice *self, const GSList *connections)
 	return NULL;
 }
 
+static NMActStageReturn
+act_stage3_ip4_config_start (NMDevice *device,
+                             NMIP4Config **out_config,
+                             NMDeviceStateReason *reason)
+{
+	if (nm_device_is_master (device) && !nm_device_wired_get_carrier (NM_DEVICE_WIRED (device))) {
+		nm_log_info (LOGD_IP4 | NM_DEVICE_WIRED_LOG_LEVEL (device),
+		             "(%s): IPv4 config waiting until carrier is on",
+		             nm_device_get_ip_iface (device));
+		return NM_ACT_STAGE_RETURN_WAIT;
+	}
+
+	return NM_DEVICE_CLASS (nm_device_wired_parent_class)->act_stage3_ip4_config_start (device, out_config, reason);
+}
+
+static NMActStageReturn
+act_stage3_ip6_config_start (NMDevice *device,
+                             NMIP6Config **out_config,
+                             NMDeviceStateReason *reason)
+{
+	if (nm_device_is_master (device) && !nm_device_wired_get_carrier (NM_DEVICE_WIRED (device))) {
+		nm_log_info (LOGD_IP6 | NM_DEVICE_WIRED_LOG_LEVEL (device),
+		             "(%s): IPv6 config waiting until carrier is on",
+		             nm_device_get_ip_iface (device));
+		return NM_ACT_STAGE_RETURN_WAIT;
+	}
+
+	return NM_DEVICE_CLASS (nm_device_wired_parent_class)->act_stage3_ip6_config_start (device, out_config, reason);
+}
+
 static void
 dispose (GObject *object)
 {
@@ -498,6 +473,7 @@ nm_device_wired_class_init (NMDeviceWiredClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
+	NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass);
 
 	g_type_class_add_private (object_class, sizeof (NMDeviceWiredPrivate));
 
@@ -505,75 +481,14 @@ nm_device_wired_class_init (NMDeviceWiredClass *klass)
 	object_class->constructor = constructor;
 	object_class->dispose = dispose;
 
-	parent_class->hw_is_up = hw_is_up;
 	parent_class->hw_bring_up = hw_bring_up;
-	parent_class->hw_take_down = hw_take_down;
 	parent_class->can_interrupt_activation = can_interrupt_activation;
-	parent_class->update_hw_address = update_hw_address;
 	parent_class->is_available = is_available;
 	parent_class->connection_match_config = connection_match_config;
-}
-
-/**
- * nm_device_wired_get_hwaddr:
- * @dev: an #NMDeviceWired
- *
- * Get a device's hardware address
- *
- * Returns: (transfer none): @dev's hardware address
- */
-const guint8 *
-nm_device_wired_get_hwaddr (NMDeviceWired *dev)
-{
-	NMDeviceWiredPrivate *priv;
-
-	g_return_val_if_fail (dev != NULL, NULL);
+	parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
+	parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
 
-	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
-	return priv->hw_addr;
-}
-
-/**
- * nm_device_wired_set_hwaddr:
- * @dev: an #NMDeviceWired
- * @addr: the new hardware address, @addrlen bytes in length
- * @addrlen: the length in bytes of @addr
- *
- * Sets the device's hardware address.
- */
-void
-nm_device_wired_set_hwaddr (NMDeviceWired *dev,
-                            const guint8 *addr,
-                            guint addrlen)
-{
-	NMDeviceWiredPrivate *priv;
-
-	g_return_if_fail (dev != NULL);
-	g_return_if_fail (addr != NULL);
-
-	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
-	g_return_if_fail (addrlen == priv->hw_addr_len);
-
-	memcpy (priv->hw_addr, addr, priv->hw_addr_len);
-}
-
-/**
- * nm_device_wired_get_hwaddr_type:
- * @dev: an #NMDeviceWired
- *
- * Get the type of a device's hardware address
- *
- * Returns: the type of @dev's hardware address
- */
-int
-nm_device_wired_get_hwaddr_type (NMDeviceWired *dev)
-{
-	NMDeviceWiredPrivate *priv;
-
-	g_return_val_if_fail (dev != NULL, -1);
-
-	priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
-	return priv->hw_addr_type;
+	wired_class->carrier_action = carrier_action;
 }
 
 /**