diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 92f37f2f52..ca1b56b2ad 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -2174,7 +2174,10 @@ _ethtool_pause_set(NMDevice * self, GHashTableIter iter; const char * name; GVariant * variant; - gboolean has_old = FALSE; + gboolean has_old = FALSE; + NMTernary pause_autoneg = NM_TERNARY_DEFAULT; + NMTernary pause_rx = NM_TERNARY_DEFAULT; + NMTernary pause_tx = NM_TERNARY_DEFAULT; nm_assert(NM_IS_DEVICE(self)); nm_assert(NM_IS_PLATFORM(platform)); @@ -2202,19 +2205,18 @@ _ethtool_pause_set(NMDevice * self, "existing setting)"); return; } - has_old = TRUE; - pause_new = pause_old; + has_old = TRUE; } switch (ethtool_id) { case NM_ETHTOOL_ID_PAUSE_AUTONEG: - pause_new.autoneg = g_variant_get_boolean(variant); + pause_autoneg = g_variant_get_boolean(variant); break; case NM_ETHTOOL_ID_PAUSE_RX: - pause_new.rx = g_variant_get_boolean(variant); + pause_rx = g_variant_get_boolean(variant); break; case NM_ETHTOOL_ID_PAUSE_TX: - pause_new.tx = g_variant_get_boolean(variant); + pause_tx = g_variant_get_boolean(variant); break; default: nm_assert_not_reached(); @@ -2224,6 +2226,20 @@ _ethtool_pause_set(NMDevice * self, if (!has_old) return; + if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) { + /* this implies to explicitly disable autoneg. */ + nm_assert(pause_autoneg != NM_TERNARY_TRUE); + pause_autoneg = NM_TERNARY_FALSE; + } + + pause_new = pause_old; + if (pause_autoneg != NM_TERNARY_DEFAULT) + pause_new.autoneg = !!pause_autoneg; + if (pause_rx != NM_TERNARY_DEFAULT) + pause_new.rx = !!pause_rx; + if (pause_tx != NM_TERNARY_DEFAULT) + pause_new.tx = !!pause_tx; + ethtool_state->pause = nm_memdup(&pause_old, sizeof(pause_old)); if (!nm_platform_ethtool_set_pause(platform, ethtool_state->ifindex, &pause_new)) { diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c index 2329f228a6..abedcae3eb 100644 --- a/src/libnm-core-impl/nm-setting-ethtool.c +++ b/src/libnm-core-impl/nm-setting-ethtool.c @@ -9,6 +9,7 @@ #include "nm-setting-private.h" #include "libnm-base/nm-ethtool-base.h" +#include "libnm-base/nm-ethtool-utils-base.h" /*****************************************************************************/ @@ -288,6 +289,9 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) GVariant *const * variants; guint len; guint i; + NMTernary pause_autoneg = NM_TERNARY_DEFAULT; + NMTernary pause_tx = NM_TERNARY_DEFAULT; + NMTernary pause_rx = NM_TERNARY_DEFAULT; len = _nm_setting_option_get_all(setting, &optnames, &variants); @@ -329,6 +333,25 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error(error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); return FALSE; } + } else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_PAUSE_AUTONEG)) + pause_autoneg = g_variant_get_boolean(variant); + else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_PAUSE_RX)) + pause_rx = g_variant_get_boolean(variant); + else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_PAUSE_TX)) + pause_tx = g_variant_get_boolean(variant); + } + + if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) { + if (pause_autoneg == NM_TERNARY_TRUE) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("pause-autoneg cannot be enabled when setting rx/tx options")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_ETHTOOL_SETTING_NAME, + NM_ETHTOOL_OPTNAME_PAUSE_AUTONEG); + return FALSE; } }