From 10f9b6c58bcf3679a117ea75913cdf3aeee15578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Thu, 22 Aug 2013 20:41:01 +0200 Subject: [PATCH] core: support slave devices in nm_platform_generate_connection() Ask each device class to update the slave configuration for their type of slave. --- src/devices/nm-device-bridge.c | 48 +++++++++++++++++++++++++++++ src/devices/nm-device-bridge.h | 2 ++ src/devices/nm-device-team.c | 56 ++++++++++++++++++++++++++++++++++ src/devices/nm-device-team.h | 2 ++ src/devices/nm-device.c | 41 +++++++++++++++++++++++++ 5 files changed, 149 insertions(+) diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 92a6d8a85d..0f99502826 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -310,6 +310,54 @@ update_connection (NMDevice *device, NMConnection *connection) } } +/** + * nm_bridge_update_slave_connection: + * @slave: the slave #NMDevice, is *not* necessarily a bridge interface + * @connection: the #NMConnection to update with the bridge port settings + * + * Reads bridge port configuration and updates @connection with those + * properties. + * + * Returns: %TRUE if the port configuration was read and @connection updated, + * %FALSE if not. + */ +gboolean +nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection) +{ + NMSettingBridgePort *s_port; + int ifindex = nm_device_get_ifindex (slave); + const Option *option; + + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + s_port = nm_connection_get_setting_bridge_port (connection); + if (!s_port) { + s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new (); + nm_connection_add_setting (connection, NM_SETTING (s_port)); + } + + for (option = slave_options; option->name; option++) { + gs_free char *str = nm_platform_slave_get_option (ifindex, option->sysname); + int value; + + if (str) { + value = strtol (str, NULL, 10); + + /* See comments in set_sysfs_uint() about centiseconds. */ + if (option->user_hz_compensate) + value /= 100; + + g_object_set (s_port, option->name, value, NULL); + } else { + nm_log_warn (LOGD_BRIDGE, "(%s): failed to read bridge port setting '%s'", + nm_device_get_iface (slave), option->sysname); + } + } + + return TRUE; +} + static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { diff --git a/src/devices/nm-device-bridge.h b/src/devices/nm-device-bridge.h index 5570c73555..4194f5a411 100644 --- a/src/devices/nm-device-bridge.h +++ b/src/devices/nm-device-bridge.h @@ -57,6 +57,8 @@ GType nm_device_bridge_get_type (void); NMDevice *nm_device_bridge_new (NMPlatformLink *platform_device); NMDevice *nm_device_bridge_new_for_connection (NMConnection *connection); +gboolean nm_bridge_update_slave_connection (NMDevice *slave, NMConnection *connection); + G_END_DECLS #endif /* NM_DEVICE_BRIDGE_H */ diff --git a/src/devices/nm-device-team.c b/src/devices/nm-device-team.c index f302ce3fb8..b52842ab18 100644 --- a/src/devices/nm-device-team.c +++ b/src/devices/nm-device-team.c @@ -31,6 +31,7 @@ #if WITH_TEAMDCTL #include #endif +#include #include "nm-device-team.h" #include "nm-logging.h" @@ -246,6 +247,61 @@ update_connection (NMDevice *device, NMConnection *connection) /******************************************************************/ +gboolean +nm_team_update_slave_connection (NMDevice *slave, NMConnection *connection) +{ + NMSettingTeamPort *s_port; + const char *iface = nm_device_get_iface (slave); + char *port_config = NULL; + gboolean success = FALSE; +#if WITH_TEAMDCTL + const char *master_iface; + int master_ifindex; + struct teamdctl *tdc; + int err; +#endif + + g_return_val_if_fail (NM_IS_DEVICE (slave), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + +#if WITH_TEAMDCTL + master_ifindex = nm_platform_link_get_master (nm_device_get_ifindex (slave)); + g_assert (master_ifindex > 0); + master_iface = nm_platform_link_get_name (master_ifindex); + g_assert (master_iface); + + tdc = teamdctl_alloc (); + g_assert (tdc); + err = teamdctl_connect (tdc, master_iface, NULL, NULL); + if (err) { + nm_log_err (LOGD_TEAM, "(%s): failed to connect to teamd for master %s", + iface, master_iface); + teamdctl_free (tdc); + return FALSE; + } + /* FIXME: wait for libteamd to implement getting port config */ +/* port_config = teamdctl_port_config_get_raw (tdc, iface); */ + teamdctl_free (tdc); +#endif + + s_port = nm_connection_get_setting_team_port (connection); + if (!s_port) { + s_port = (NMSettingTeamPort *) nm_setting_team_port_new (); + nm_connection_add_setting (connection, NM_SETTING (s_port)); + } + + if (port_config) { + g_object_set (G_OBJECT (s_port), NM_SETTING_TEAM_PORT_CONFIG, port_config, NULL); + free (port_config); + success = TRUE; + } else + nm_log_err (LOGD_TEAM, "(%s): failed to read teamd port configuration", iface); + + return success; +} + +/******************************************************************/ + static gboolean ensure_killed (gpointer data) { diff --git a/src/devices/nm-device-team.h b/src/devices/nm-device-team.h index ebe5ae7d9f..fe1275c6b0 100644 --- a/src/devices/nm-device-team.h +++ b/src/devices/nm-device-team.h @@ -57,6 +57,8 @@ GType nm_device_team_get_type (void); NMDevice *nm_device_team_new (NMPlatformLink *platform_device); NMDevice *nm_device_team_new_for_connection (NMConnection *connection); +gboolean nm_team_update_slave_connection (NMDevice *slave, NMConnection *connection); + G_END_DECLS #endif /* NM_DEVICE_TEAM_H */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 58b0dfdd48..2754fccf15 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -69,6 +69,10 @@ #include "nm-config.h" #include "nm-platform.h" +#include "nm-device-bridge.h" +#include "nm-device-bond.h" +#include "nm-device-team.h" + static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context); #include "nm-device-glue.h" @@ -1634,12 +1638,14 @@ nm_device_generate_connection (NMDevice *device) NMDeviceClass *klass = NM_DEVICE_GET_CLASS (device); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); const char *ifname = nm_device_get_iface (device); + int ifindex = nm_device_get_ifindex (device); NMConnection *connection; NMSetting *s_con; NMSetting *s_ip4; NMSetting *s_ip6; gs_free char *uuid = NULL; gs_free char *name = NULL; + int master_ifindex = 0; /* If update_connection() is not implemented, just fail. */ if (!klass->update_connection) @@ -1666,6 +1672,41 @@ nm_device_generate_connection (NMDevice *device) g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, klass->connection_type, NULL); nm_connection_add_setting (connection, s_con); + /* If the device is a slave, update various slave settings */ + if (ifindex) + master_ifindex = nm_platform_link_get_master (ifindex); + if (master_ifindex) { + const char *master_iface = nm_platform_link_get_name (master_ifindex); + const char *slave_type = NULL; + gboolean success = FALSE; + + switch (nm_platform_link_get_type (master_ifindex)) { + case NM_LINK_TYPE_BRIDGE: + slave_type = NM_SETTING_BRIDGE_SETTING_NAME; + success = nm_bridge_update_slave_connection (device, connection); + break; + case NM_LINK_TYPE_BOND: + slave_type = NM_SETTING_BOND_SETTING_NAME; + success = TRUE; + break; + case NM_LINK_TYPE_TEAM: + slave_type = NM_SETTING_TEAM_SETTING_NAME; + success = nm_team_update_slave_connection (device, connection); + break; + default: + g_warn_if_reached (); + break; + } + + if (!success) + nm_log_err (LOGD_DEVICE, "(%s): failed to read slave configuration", ifname); + + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, master_iface, + NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, + NULL); + } + s_ip4 = nm_setting_ip4_config_new (); nm_connection_add_setting (connection, s_ip4); if (priv->ip4_config)