253 lines
9.2 KiB
Diff
253 lines
9.2 KiB
Diff
|
From 8c6f8c65955d18ca9b43ad2bcd1bccf2cd85e7ed Mon Sep 17 00:00:00 2001
|
||
|
From: Beniamino Galvani <bgalvani@redhat.com>
|
||
|
Date: Mon, 5 Jun 2017 13:51:18 +0200
|
||
|
Subject: [PATCH 1/2] libnm-core: remove unsupported bond options during
|
||
|
normalization
|
||
|
|
||
|
In an ideal world, we should not validate connections containing
|
||
|
options not valid for the current bond mode. However adding such
|
||
|
restriction now means that during an upgrade to the new NM version
|
||
|
some connections that were valid before become invalid, possibly
|
||
|
disrupting connectivity.
|
||
|
|
||
|
Instead, consider invalid options as a normalizable error and remove
|
||
|
them during normalization.
|
||
|
|
||
|
Converting the setting to a "canonical" form without invalid options
|
||
|
is important for the connection matching logic, where such invalid
|
||
|
options can cause false mismatches.
|
||
|
|
||
|
(cherry picked from commit f25e008e2fe655bbddbb8a66612a9d141e982049)
|
||
|
(cherry picked from commit ac7a5c074c72310d8328fb448824d29bbec932f3)
|
||
|
---
|
||
|
libnm-core/nm-connection.c | 31 +++++++++++++++++++++++
|
||
|
libnm-core/nm-setting-bond.c | 18 +++++++++++++
|
||
|
libnm-core/tests/test-setting-bond.c | 49 ++++++++++++++++++++++++++++++++++++
|
||
|
3 files changed, 98 insertions(+)
|
||
|
|
||
|
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
|
||
|
index ecfb978..c1b7506 100644
|
||
|
--- a/libnm-core/nm-connection.c
|
||
|
+++ b/libnm-core/nm-connection.c
|
||
|
@@ -913,6 +913,36 @@ _normalize_bond_mode (NMConnection *self, GHashTable *parameters)
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
+_normalize_bond_options (NMConnection *self, GHashTable *parameters)
|
||
|
+{
|
||
|
+ NMSettingBond *s_bond = nm_connection_get_setting_bond (self);
|
||
|
+ gboolean changed = FALSE;
|
||
|
+ const char *name, *mode_str;
|
||
|
+ NMBondMode mode;
|
||
|
+ guint32 num, i;
|
||
|
+
|
||
|
+ /* Strip away unsupported options for current mode */
|
||
|
+ if (s_bond) {
|
||
|
+ mode_str = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
|
||
|
+ mode = _nm_setting_bond_mode_from_string (mode_str);
|
||
|
+ if (mode == NM_BOND_MODE_UNKNOWN)
|
||
|
+ return FALSE;
|
||
|
+again:
|
||
|
+ num = nm_setting_bond_get_num_options (s_bond);
|
||
|
+ for (i = 0; i < num; i++) {
|
||
|
+ if ( nm_setting_bond_get_option (s_bond, i, &name, NULL)
|
||
|
+ && !_nm_setting_bond_option_supported (name, mode)) {
|
||
|
+ nm_setting_bond_remove_option (s_bond, name);
|
||
|
+ changed = TRUE;
|
||
|
+ goto again;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return changed;
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
_normalize_wireless_mac_address_randomization (NMConnection *self, GHashTable *parameters)
|
||
|
{
|
||
|
NMSettingWireless *s_wifi = nm_connection_get_setting_wireless (self);
|
||
|
@@ -1275,6 +1305,7 @@ nm_connection_normalize (NMConnection *connection,
|
||
|
was_modified |= _normalize_ethernet_link_neg (connection);
|
||
|
was_modified |= _normalize_infiniband_mtu (connection, parameters);
|
||
|
was_modified |= _normalize_bond_mode (connection, parameters);
|
||
|
+ was_modified |= _normalize_bond_options (connection, parameters);
|
||
|
was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters);
|
||
|
was_modified |= _normalize_team_config (connection, parameters);
|
||
|
was_modified |= _normalize_team_port_config (connection, parameters);
|
||
|
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
|
||
|
index 9a8bdc3..b62964c 100644
|
||
|
--- a/libnm-core/nm-setting-bond.c
|
||
|
+++ b/libnm-core/nm-setting-bond.c
|
||
|
@@ -542,6 +542,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
||
|
const char *arp_ip_target = NULL;
|
||
|
const char *lacp_rate;
|
||
|
const char *primary;
|
||
|
+ NMBondMode bond_mode;
|
||
|
|
||
|
g_hash_table_iter_init (&iter, priv->options);
|
||
|
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
|
||
|
@@ -776,6 +777,23 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
||
|
return NM_SETTING_VERIFY_NORMALIZABLE;
|
||
|
}
|
||
|
|
||
|
+ /* normalize unsupported options for the current mode */
|
||
|
+ bond_mode = _nm_setting_bond_mode_from_string (mode_new);
|
||
|
+ g_hash_table_iter_init (&iter, priv->options);
|
||
|
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
|
||
|
+ if (nm_streq (key, "mode"))
|
||
|
+ continue;
|
||
|
+ if (!_nm_setting_bond_option_supported (key, bond_mode)) {
|
||
|
+ g_set_error (error,
|
||
|
+ NM_CONNECTION_ERROR,
|
||
|
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||
|
+ _("'%s' option is not valid with mode '%s'"),
|
||
|
+ key, mode_new);
|
||
|
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
|
||
|
+ return NM_SETTING_VERIFY_NORMALIZABLE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
diff --git a/libnm-core/tests/test-setting-bond.c b/libnm-core/tests/test-setting-bond.c
|
||
|
index 91a8199..e6a65bb 100644
|
||
|
--- a/libnm-core/tests/test-setting-bond.c
|
||
|
+++ b/libnm-core/tests/test-setting-bond.c
|
||
|
@@ -182,6 +182,54 @@ test_compare (void)
|
||
|
((const char *[]){ "num_unsol_na", "4", "num_grat_arp", "4", NULL }));
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+test_normalize_options (const char **opts1, const char **opts2)
|
||
|
+{
|
||
|
+ gs_unref_object NMConnection *con = NULL;
|
||
|
+ NMSettingBond *s_bond;
|
||
|
+ GError *error = NULL;
|
||
|
+ gboolean success;
|
||
|
+ const char **p;
|
||
|
+ int num = 0;
|
||
|
+
|
||
|
+ create_bond_connection (&con, &s_bond);
|
||
|
+
|
||
|
+ for (p = opts1; p[0] && p[1]; p += 2)
|
||
|
+ g_assert (nm_setting_bond_add_option (s_bond, p[0], p[1]));
|
||
|
+
|
||
|
+ nmtst_assert_connection_verifies_and_normalizable (con);
|
||
|
+ nmtst_connection_normalize (con);
|
||
|
+ success = nm_setting_verify ((NMSetting *) s_bond, con, &error);
|
||
|
+ nmtst_assert_success (success, error);
|
||
|
+
|
||
|
+ for (p = opts2; p[0] && p[1]; p += 2) {
|
||
|
+ g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, p[0]), ==, p[1]);
|
||
|
+ num++;
|
||
|
+ }
|
||
|
+
|
||
|
+ g_assert_cmpint (num, ==, nm_setting_bond_get_num_options (s_bond));
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+test_normalize (void)
|
||
|
+{
|
||
|
+ test_normalize_options (
|
||
|
+ ((const char *[]){ "mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL }),
|
||
|
+ ((const char *[]){ "mode", "802.3ad", "ad_actor_system", "00:02:03:04:05:06", NULL }));
|
||
|
+ test_normalize_options (
|
||
|
+ ((const char *[]){ "mode", "1", "miimon", "1", NULL }),
|
||
|
+ ((const char *[]){ "mode", "active-backup", "miimon", "1", NULL }));
|
||
|
+ test_normalize_options (
|
||
|
+ ((const char *[]){ "mode", "balance-alb", "tlb_dynamic_lb", "1", NULL }),
|
||
|
+ ((const char *[]){ "mode", "balance-alb", NULL }));
|
||
|
+ test_normalize_options (
|
||
|
+ ((const char *[]){ "mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL }),
|
||
|
+ ((const char *[]){ "mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL }));
|
||
|
+ test_normalize_options (
|
||
|
+ ((const char *[]){ "mode", "balance-rr", "ad_actor_sys_prio", "4", "packets_per_slave", "3", NULL }),
|
||
|
+ ((const char *[]){ "mode", "balance-rr", "packets_per_slave", "3", NULL }));
|
||
|
+}
|
||
|
+
|
||
|
#define TPATH "/libnm/settings/bond/"
|
||
|
|
||
|
NMTST_DEFINE ();
|
||
|
@@ -193,6 +241,7 @@ main (int argc, char **argv)
|
||
|
|
||
|
g_test_add_func (TPATH "verify", test_verify);
|
||
|
g_test_add_func (TPATH "compare", test_compare);
|
||
|
+ g_test_add_func (TPATH "normalize", test_normalize);
|
||
|
|
||
|
return g_test_run ();
|
||
|
}
|
||
|
--
|
||
|
2.9.3
|
||
|
|
||
|
From 0d96d249ffe95e0232b8247e6bb9c1385a2b4940 Mon Sep 17 00:00:00 2001
|
||
|
From: Beniamino Galvani <bgalvani@redhat.com>
|
||
|
Date: Mon, 5 Jun 2017 14:48:08 +0200
|
||
|
Subject: [PATCH 2/2] bond: add only supported options to the generated
|
||
|
connection
|
||
|
|
||
|
Upstream commit [1] changed in the kernel the default value of
|
||
|
tlb_dynamic_lb bond from 1 to 0 when the mode is not tlb. This is not
|
||
|
wrong, as the option value doesn't really matter for other modes, but
|
||
|
it breaks the connection matching because we read back a 0 value when
|
||
|
we expect a default of 1.
|
||
|
|
||
|
Fix this in a generic way by ignoring altogether options that are not
|
||
|
relevant for the current bond mode, because they are removed from the
|
||
|
connection during normalization.
|
||
|
|
||
|
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8b426dc54cf4056984bab7dfa48c92ee79a46434
|
||
|
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1457909
|
||
|
(cherry picked from commit 056a973a4fdb68abe8bc7bfc5f31250345d71f21)
|
||
|
(cherry picked from commit 61817661c899844ddb364ebd529716f574146588)
|
||
|
---
|
||
|
src/devices/nm-device-bond.c | 10 ++++++++--
|
||
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
|
||
|
index 3325c94..c8748fe 100644
|
||
|
--- a/src/devices/nm-device-bond.c
|
||
|
+++ b/src/devices/nm-device-bond.c
|
||
|
@@ -155,6 +155,7 @@ update_connection (NMDevice *device, NMConnection *connection)
|
||
|
{
|
||
|
NMSettingBond *s_bond = nm_connection_get_setting_bond (connection);
|
||
|
int ifindex = nm_device_get_ifindex (device);
|
||
|
+ NMBondMode mode = NM_BOND_MODE_UNKNOWN;
|
||
|
const char **options;
|
||
|
|
||
|
if (!s_bond) {
|
||
|
@@ -164,7 +165,7 @@ update_connection (NMDevice *device, NMConnection *connection)
|
||
|
|
||
|
/* Read bond options from sysfs and update the Bond setting to match */
|
||
|
options = nm_setting_bond_get_valid_options (s_bond);
|
||
|
- while (options && *options) {
|
||
|
+ for (; *options; options++) {
|
||
|
gs_free char *value = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, *options);
|
||
|
const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options);
|
||
|
char *p;
|
||
|
@@ -176,6 +177,12 @@ update_connection (NMDevice *device, NMConnection *connection)
|
||
|
*p = '\0';
|
||
|
}
|
||
|
|
||
|
+ if (nm_streq (*options, NM_SETTING_BOND_OPTION_MODE))
|
||
|
+ mode = _nm_setting_bond_mode_from_string (value);
|
||
|
+
|
||
|
+ if (!_nm_setting_bond_option_supported (*options, mode))
|
||
|
+ continue;
|
||
|
+
|
||
|
if ( value
|
||
|
&& value[0]
|
||
|
&& !ignore_if_zero (*options, value)
|
||
|
@@ -190,7 +197,6 @@ update_connection (NMDevice *device, NMConnection *connection)
|
||
|
|
||
|
nm_setting_bond_add_option (s_bond, *options, value);
|
||
|
}
|
||
|
- options++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.9.3
|
||
|
|