From 9dac51d9c0ac470c302973d2e3e49c6e62ddf95d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 21 Feb 2017 16:26:49 +0100 Subject: [PATCH] team: support the ethernet.cloned-mac-address property The only reliable way of setting a MAC address for the team is through the "hwaddr" property in the configuration passed to teamd. In order to rewrite the configuration we need Jansson support; since it is already a requirement for teamd, let the team plugin depend on it. --- Makefile.am | 2 ++ configure.ac | 15 +++++++-- src/devices/team/nm-device-team.c | 54 +++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Makefile.am b/Makefile.am index 083b7701da..8576215744 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2572,6 +2572,7 @@ src_devices_team_libnm_device_plugin_team_la_CPPFLAGS = \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(LIBTEAMDCTL_CFLAGS) \ + $(JANSSON_CFLAGS) \ $(GLIB_CFLAGS) src_devices_team_libnm_device_plugin_team_la_LDFLAGS = \ @@ -2581,6 +2582,7 @@ src_devices_team_libnm_device_plugin_team_la_LDFLAGS = \ src_devices_team_libnm_device_plugin_team_la_LIBADD = \ introspection/libnmdbus.la \ $(LIBTEAMDCTL_LIBS) \ + $(JANSSON_LIBS) \ $(GLIB_LIBS) \ $(GUDEV_LIBS) diff --git a/configure.ac b/configure.ac index e8910a6fdf..354db306e8 100644 --- a/configure.ac +++ b/configure.ac @@ -550,11 +550,20 @@ PKG_CHECK_MODULES(UUID, uuid) PKG_CHECK_MODULES(JANSSON, [jansson], [have_jansson=yes], [have_jansson=no]) PKG_CHECK_MODULES(LIBTEAMDCTL, [libteamdctl >= 1.9], [have_teamdctl=yes],[have_teamdctl=no]) +if test "$have_jansson" = "yes" -a "$have_teamdctl" = "yes"; then + have_team_prereq=yes +else + have_team_prereq=no +fi + AC_ARG_ENABLE(teamdctl, AS_HELP_STRING([--enable-teamdctl], [enable Teamd control support]), - [enable_teamdctl=${enableval}], [enable_teamdctl=${have_teamdctl}]) + [enable_teamdctl=${enableval}], [enable_teamdctl=${have_team_prereq}]) if (test "${enable_teamdctl}" = "yes"); then - if test x"$have_teamdctl" = x"no"; then - AC_MSG_ERROR(Teamd control is required) + if test "$have_teamdctl" = "no"; then + AC_MSG_ERROR(Libteamdctl is required for team support) + fi + if test "$have_jansson" = "no"; then + AC_MSG_ERROR(Jansson is required for team support) fi # temporary bug workaround LIBTEAMDCTL_CFLAGS=`echo $LIBTEAMDCTL_CFLAGS | sed -e 's:/teamdctl.h::'` diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index a3f621f467..5a94e76df2 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" @@ -72,7 +73,7 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) /*****************************************************************************/ -static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team); +static gboolean teamd_start (NMDevice *device, NMConnection *connection); /*****************************************************************************/ @@ -449,7 +450,7 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, NMConnection *connection = nm_device_get_applied_connection (device); g_assert (connection); - if (!teamd_start (device, nm_connection_get_setting_team (connection))) + if (!teamd_start (device, connection)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } @@ -513,7 +514,7 @@ teamd_kill (NMDeviceTeam *self, const char *teamd_binary, GError **error) } static gboolean -teamd_start (NMDevice *device, NMSettingTeam *s_team) +teamd_start (NMDevice *device, NMConnection *connection) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); @@ -523,6 +524,12 @@ teamd_start (NMDevice *device, NMSettingTeam *s_team) gs_free char *tmp_str = NULL; const char *teamd_binary; const char *config; + nm_auto_free const char *config_free = NULL; + NMSettingTeam *s_team; + gs_free char *cloned_mac = NULL; + + s_team = nm_connection_get_setting_team (connection); + g_return_val_if_fail (s_team, FALSE); teamd_binary = nm_utils_find_helper ("teamd", NULL, NULL); if (!teamd_binary) { @@ -548,7 +555,39 @@ teamd_start (NMDevice *device, NMSettingTeam *s_team) g_ptr_array_add (argv, (gpointer) "-t"); g_ptr_array_add (argv, (gpointer) iface); - config = nm_setting_team_get_config(s_team); + config = nm_setting_team_get_config (s_team); + if (!nm_device_hw_addr_get_cloned (device, connection, FALSE, &cloned_mac, NULL, &error)) { + _LOGW (LOGD_DEVICE, "set-hw-addr: %s", error->message); + return FALSE; + } + + if (cloned_mac) { + json_t *json, *hwaddr; + json_error_t jerror; + + /* Inject the hwaddr property into the JSON configuration. + * While doing so, detect potential conflicts */ + + json = json_loads (config ?: "{}", 0, &jerror); + g_return_val_if_fail (json, FALSE); + + hwaddr = json_object_get (json, "hwaddr"); + if (hwaddr) { + if ( !json_is_string (hwaddr) + || !nm_streq0 (json_string_value (hwaddr), cloned_mac)) + _LOGW (LOGD_TEAM, "set-hw-addr: can't set team cloned-mac-address as the JSON configuration already contains \"hwaddr\""); + } else { + hwaddr = json_string (cloned_mac); + json_object_set (json, "hwaddr", hwaddr); + config = config_free = json_dumps (json, JSON_INDENT(0) | + JSON_ENSURE_ASCII | + JSON_SORT_KEYS); + _LOGD (LOGD_TEAM, "set-hw-addr: injected \"hwaddr\" \"%s\" into team configuration", cloned_mac); + json_decref (hwaddr); + } + json_decref (json); + } + if (config) { g_ptr_array_add (argv, (gpointer) "-c"); g_ptr_array_add (argv, (gpointer) config); @@ -587,13 +626,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gs_free_error GError *error = NULL; NMSettingTeam *s_team; + NMConnection *connection; const char *cfg; ret = NM_DEVICE_CLASS (nm_device_team_parent_class)->act_stage1_prepare (device, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - s_team = (NMSettingTeam *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_TEAM); + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + s_team = nm_connection_get_setting_team (connection); g_return_val_if_fail (s_team, NM_ACT_STAGE_RETURN_FAILURE); if (priv->tdc) { @@ -621,7 +663,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) teamd_cleanup (device, TRUE); } - return teamd_start (device, s_team) ? + return teamd_start (device, connection) ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE; }