summaryrefslogtreecommitdiff
path: root/src/nm-device-bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-device-bridge.c')
-rw-r--r--src/nm-device-bridge.c208
1 files changed, 52 insertions, 156 deletions
diff --git a/src/nm-device-bridge.c b/src/nm-device-bridge.c
index 6f3d70e4b..39275c8b4 100644
--- a/src/nm-device-bridge.c
+++ b/src/nm-device-bridge.c
@@ -46,8 +46,8 @@ G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE_WIRED)
#define NM_BRIDGE_ERROR (nm_bridge_error_quark ())
typedef struct {
- gboolean ip4_waiting;
- gboolean ip6_waiting;
+ guint8 hw_addr[NM_UTILS_HWADDR_LEN_MAX];
+ gsize hw_addr_len;
} NMDeviceBridgePrivate;
enum {
@@ -81,44 +81,39 @@ nm_bridge_error_quark (void)
/******************************************************************/
static void
-device_state_changed (NMDevice *device,
- NMDeviceState new_state,
- NMDeviceState old_state,
- NMDeviceStateReason reason)
+carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
{
- NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
-
- if (new_state == NM_DEVICE_STATE_UNAVAILABLE) {
- /* Use NM_DEVICE_STATE_REASON_CARRIER to make sure num retries is reset */
- nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
- }
-
- if (new_state <= NM_DEVICE_STATE_DISCONNECTED || new_state > NM_DEVICE_STATE_ACTIVATED) {
- priv->ip4_waiting = FALSE;
- priv->ip6_waiting = FALSE;
- }
+ /* Bridge carrier state follows IFF_UP with no ports, and port carrier
+ * states when ports are added. Thus carrier isn't useful when deciding
+ * to auto-activate the bridge master. Also, like bond masters, when the
+ * carrier state changes due to slave changes, we shouldn't deactivate the
+ * bridge since the user may be reconfiguring ports.
+ *
+ * For these reasons, carrier changes are effectively ignored by overriding
+ * the parent class' carrier handling and doing nothing.
+ */
}
static void
update_hw_address (NMDevice *dev)
{
- const guint8 *hw_addr;
- guint8 old_addr[NM_UTILS_HWADDR_LEN_MAX];
- int addrtype, addrlen;
-
- addrtype = nm_device_wired_get_hwaddr_type (NM_DEVICE_WIRED (dev));
- g_assert (addrtype >= 0);
- addrlen = nm_utils_hwaddr_len (addrtype);
- g_assert (addrlen > 0);
-
- hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
- memcpy (old_addr, hw_addr, addrlen);
-
- NM_DEVICE_CLASS (nm_device_bridge_parent_class)->update_hw_address (dev);
+ NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (dev);
+ gsize addrlen;
+ gboolean changed = FALSE;
+
+ addrlen = nm_device_read_hwaddr (dev, priv->hw_addr, sizeof (priv->hw_addr), &changed);
+ if (addrlen) {
+ priv->hw_addr_len = addrlen;
+ if (changed)
+ g_object_notify (G_OBJECT (dev), NM_DEVICE_BRIDGE_HW_ADDRESS);
+ }
+}
- hw_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (dev));
- if (memcmp (old_addr, hw_addr, addrlen))
- g_object_notify (G_OBJECT (dev), NM_DEVICE_BRIDGE_HW_ADDRESS);
+static const guint8 *
+get_hw_address (NMDevice *device, guint *out_len)
+{
+ *out_len = NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_addr_len;
+ return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_addr;
}
static guint32
@@ -247,10 +242,11 @@ complete_connection (NMDevice *device,
static gboolean
spec_match_list (NMDevice *device, const GSList *specs)
{
+ NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
char *hwaddr;
gboolean matched;
- hwaddr = nm_utils_hwaddr_ntoa (nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (device)), ARPHRD_ETHER);
+ hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len));
matched = nm_match_spec_hwaddr (specs, hwaddr);
g_free (hwaddr);
@@ -311,6 +307,7 @@ static void
set_sysfs_uint (const char *iface,
GObject *obj,
const char *obj_prop,
+ const char *dir,
const char *sysfs_prop,
gboolean default_if_zero,
gboolean user_hz_compensate)
@@ -353,7 +350,7 @@ set_sysfs_uint (const char *iface,
if (user_hz_compensate)
uval *= 100;
- path = g_strdup_printf ("/sys/class/net/%s/bridge/%s", iface, sysfs_prop);
+ path = g_strdup_printf ("/sys/class/net/%s/%s/%s", iface, dir, sysfs_prop);
s = g_strdup_printf ("%u", uval);
/* FIXME: how should failure be handled? */
nm_utils_do_sysctl (path, s);
@@ -371,9 +368,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
- NM_DEVICE_BRIDGE_GET_PRIVATE (dev)->ip4_waiting = FALSE;
- NM_DEVICE_BRIDGE_GET_PRIVATE (dev)->ip6_waiting = FALSE;
-
ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage1_prepare (dev, reason);
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
connection = nm_device_get_connection (dev);
@@ -385,12 +379,12 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
iface = nm_device_get_ip_iface (dev);
g_assert (iface);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_STP, "stp_state", FALSE, FALSE);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_PRIORITY, "priority", TRUE, FALSE);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY, "forward_delay", TRUE, TRUE);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", TRUE, TRUE);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_MAX_AGE, "max_age", TRUE, TRUE);
- set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", TRUE, TRUE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_STP, "bridge", "stp_state", FALSE, FALSE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_PRIORITY, "bridge", "priority", TRUE, FALSE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY, "bridge", "forward_delay", TRUE, TRUE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME, "bridge", "hello_time", TRUE, TRUE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_MAX_AGE, "bridge", "max_age", TRUE, TRUE);
+ set_sysfs_uint (iface, G_OBJECT (s_bridge), NM_SETTING_BRIDGE_AGEING_TIME, "bridge", "ageing_time", TRUE, TRUE);
}
return ret;
}
@@ -398,7 +392,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
static gboolean
enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
{
- NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
gboolean success;
NMSettingBridgePort *s_port;
const char *iface = nm_device_get_ip_iface (device);
@@ -414,28 +407,15 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
/* Set port properties */
s_port = nm_connection_get_setting_bridge_port (connection);
if (s_port) {
- set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY, "priority", TRUE, FALSE);
- set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST, "path_cost", TRUE, FALSE);
- set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", FALSE, FALSE);
+ set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY, "brport", "priority", TRUE, FALSE);
+ set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST, "brport", "path_cost", TRUE, FALSE);
+ set_sysfs_uint (slave_iface, G_OBJECT (s_port), NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "brport", "hairpin_mode", FALSE, FALSE);
}
- nm_log_info (LOGD_DEVICE, "(%s): attached bridge port %s", iface, slave_iface);
+ nm_log_info (LOGD_BRIDGE, "(%s): attached bridge port %s", iface, slave_iface);
g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES);
- /* If waiting for a slave to continue with IP config, start now */
- if (priv->ip4_waiting) {
- nm_log_info (LOGD_DEVICE | LOGD_IP4, "(%s): retrying IPv4 config with first slave", iface);
- priv->ip4_waiting = FALSE;
- nm_device_activate_stage3_ip4_start (device);
- }
-
- if (priv->ip6_waiting) {
- nm_log_info (LOGD_DEVICE | LOGD_IP6, "(%s): retrying IPv6 config with first slave", iface);
- priv->ip6_waiting = FALSE;
- nm_device_activate_stage3_ip6_start (device);
- }
-
return TRUE;
}
@@ -448,7 +428,7 @@ release_slave (NMDevice *device, NMDevice *slave)
nm_device_get_ip_iface (device),
nm_device_get_ip_ifindex (slave),
nm_device_get_ip_iface (slave));
- nm_log_info (LOGD_DEVICE, "(%s): detached bridge port %s (success %d)",
+ nm_log_info (LOGD_BRIDGE, "(%s): detached bridge port %s (success %d)",
nm_device_get_ip_iface (device),
nm_device_get_ip_iface (slave),
success);
@@ -456,92 +436,6 @@ release_slave (NMDevice *device, NMDevice *slave)
return success;
}
-static NMActStageReturn
-act_stage3_ip4_config_start (NMDevice *device,
- NMIP4Config **out_config,
- NMDeviceStateReason *reason)
-{
- NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
- NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
- NMConnection *connection;
- NMSettingIP4Config *s_ip4;
- const char *method = NULL;
- GSList *slaves;
-
- priv->ip4_waiting = FALSE;
-
- slaves = nm_device_master_get_slaves (device);
- if (slaves == NULL) {
- connection = nm_device_get_connection (device);
- g_assert (connection);
-
- s_ip4 = nm_connection_get_setting_ip4_config (connection);
- if (s_ip4)
- method = nm_setting_ip4_config_get_method (s_ip4);
-
- if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0)
- priv->ip4_waiting = TRUE;
- }
- g_slist_free (slaves);
-
- if (priv->ip4_waiting) {
- ret = NM_ACT_STAGE_RETURN_WAIT;
- nm_log_info (LOGD_DEVICE | LOGD_IP4, "(%s): IPv4 config waiting until slaves are present",
- nm_device_get_ip_iface (device));
- } else {
- /* We have slaves; proceed with normal IPv4 configuration */
- ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage3_ip4_config_start (device, out_config, reason);
- }
-
- return ret;
-}
-
-static NMActStageReturn
-act_stage3_ip6_config_start (NMDevice *device,
- NMIP6Config **out_config,
- NMDeviceStateReason *reason)
-{
- NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
- NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
- NMConnection *connection;
- NMSettingIP6Config *s_ip6;
- const char *method = NULL;
- GSList *slaves;
-
- priv->ip6_waiting = FALSE;
-
- slaves = nm_device_master_get_slaves (device);
- if (slaves == NULL) {
- connection = nm_device_get_connection (device);
- g_assert (connection);
-
- s_ip6 = nm_connection_get_setting_ip6_config (connection);
- if (s_ip6)
- method = nm_setting_ip6_config_get_method (s_ip6);
-
- /* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
- * to complete addressing. SLAAC and DHCP obviously need a peer to
- * provide a prefix, while Link-Local must perform DAD on the local link.
- */
- if ( !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
- || !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)
- || !g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
- priv->ip6_waiting = TRUE;
- }
- g_slist_free (slaves);
-
- if (priv->ip6_waiting) {
- ret = NM_ACT_STAGE_RETURN_WAIT;
- nm_log_info (LOGD_DEVICE | LOGD_IP6, "(%s): IPv6 config waiting until slaves are present",
- nm_device_get_ip_iface (device));
- } else {
- /* We have slaves; proceed with normal IPv6 configuration */
- ret = NM_DEVICE_CLASS (nm_device_bridge_parent_class)->act_stage3_ip6_config_start (device, out_config, reason);
- }
-
- return ret;
-}
-
/******************************************************************/
NMDevice *
@@ -556,6 +450,7 @@ nm_device_bridge_new (const char *udi, const char *iface)
NM_DEVICE_DRIVER, "bridge",
NM_DEVICE_TYPE_DESC, "Bridge",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
+ NM_DEVICE_IS_MASTER, TRUE,
NULL);
}
@@ -564,7 +459,7 @@ constructed (GObject *object)
{
G_OBJECT_CLASS (nm_device_bridge_parent_class)->constructed (object);
- nm_log_dbg (LOGD_HW | LOGD_DEVICE, "(%s): kernel ifindex %d",
+ nm_log_dbg (LOGD_HW | LOGD_BRIDGE, "(%s): kernel ifindex %d",
nm_device_get_iface (NM_DEVICE (object)),
nm_device_get_ifindex (NM_DEVICE (object)));
}
@@ -578,14 +473,15 @@ static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
- const guint8 *current_addr;
+ NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object);
GPtrArray *slaves;
GSList *list, *iter;
+ char *hwaddr;
switch (prop_id) {
case PROP_HW_ADDRESS:
- current_addr = nm_device_wired_get_hwaddr (NM_DEVICE_WIRED (object));
- g_value_take_string (value, nm_utils_hwaddr_ntoa (current_addr, ARPHRD_ETHER));
+ hwaddr = nm_utils_hwaddr_ntoa (priv->hw_addr, nm_utils_hwaddr_type (priv->hw_addr_len));
+ g_value_take_string (value, hwaddr);
break;
case PROP_CARRIER:
g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (object)));
@@ -620,6 +516,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *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 (NMDeviceBridgePrivate));
@@ -630,6 +527,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->update_hw_address = update_hw_address;
+ parent_class->get_hw_address = get_hw_address;
parent_class->is_available = is_available;
parent_class->get_best_auto_connection = get_best_auto_connection;
parent_class->check_connection_compatible = check_connection_compatible;
@@ -639,12 +537,10 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
parent_class->connection_match_config = connection_match_config;
parent_class->act_stage1_prepare = act_stage1_prepare;
- parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
- parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
parent_class->enslave_slave = enslave_slave;
parent_class->release_slave = release_slave;
- parent_class->state_changed = device_state_changed;
+ wired_class->carrier_action = carrier_action;
/* properties */
g_object_class_install_property