diff options
Diffstat (limited to 'src/nm-device-bridge.c')
-rw-r--r-- | src/nm-device-bridge.c | 208 |
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 |