From 56d193e68661889606a106b288a49e25ad389777 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 23 Mar 2019 16:58:57 +0100 Subject: [PATCH] ifcfg-rh: add bridge vlans support --- libnm-core/nm-setting-bridge-port.c | 7 ++ libnm-core/nm-setting-bridge.c | 7 ++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 47 ++++++++++++ .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 75 ++++++++++++++++--- ...fcfg-Test_Write_Bridge_Component.cexpected | 1 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 28 +++++++ 6 files changed, 153 insertions(+), 12 deletions(-) diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c index 404a486251..ebac2fc2c3 100644 --- a/libnm-core/nm-setting-bridge-port.c +++ b/libnm-core/nm-setting-bridge-port.c @@ -558,6 +558,13 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass) * * Since: 1.18 **/ + /* ---ifcfg-rh--- + * property: vlans + * variable: BRIDGE_PORT_VLANS + * description: List of VLANs on the bridge port + * example: BRIDGE_PORT_VLANS="1 pvid untagged,20,40 untagged" + * ---end--- + */ obj_properties[PROP_VLANS] = g_param_spec_boxed (NM_SETTING_BRIDGE_PORT_VLANS, "", "", G_TYPE_PTR_ARRAY, diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index ae70942c09..18ed5f54db 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -1393,6 +1393,13 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) * * Since: 1.18 **/ + /* ---ifcfg-rh--- + * property: vlans + * variable: BRIDGE_VLANS + * description: List of VLANs on the bridge + * example: BRIDGE_VLANS="1 pvid untagged,20,40 untagged" + * ---end--- + */ obj_properties[PROP_VLANS] = g_param_spec_boxed (NM_SETTING_BRIDGE_VLANS, "", "", G_TYPE_PTR_ARRAY, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index d0f37ea95a..de45c084ef 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5054,6 +5054,43 @@ handle_bridging_opts (NMSetting *setting, } } +static void +read_bridge_vlans (shvarFile *ifcfg, + const char *key, + NMSetting *setting, + const char *property) +{ + gs_unref_ptrarray GPtrArray *array = NULL; + gs_free char *value_to_free = NULL; + const char *value; + + value = svGetValueStr (ifcfg, key, &value_to_free); + if (value) { + gs_free const char **strv = NULL; + const char *const *iter; + GError *local = NULL; + NMBridgeVlan *vlan; + + array = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); + + strv = nm_utils_strsplit_set (value, ",", FALSE); + if (strv) { + for (iter = strv; *iter; iter++) { + vlan = nm_bridge_vlan_from_str (*iter, &local); + if (!vlan) { + PARSE_WARNING ("invalid bridge VLAN: %s", local->message); + g_clear_error (&local); + continue; + } + g_ptr_array_add (array, vlan); + } + } + nm_clear_g_free (&value_to_free); + } + + g_object_set (setting, property, array, NULL); +} + static NMSetting * make_bridge_setting (shvarFile *ifcfg, const char *file, @@ -5112,6 +5149,11 @@ make_bridge_setting (shvarFile *ifcfg, nm_clear_g_free (&value_to_free); } + read_bridge_vlans (ifcfg, + "BRIDGE_VLANS", + NM_SETTING (s_bridge), + NM_SETTING_BRIDGE_VLANS); + return (NMSetting *) g_steal_pointer (&s_bridge); } @@ -5181,6 +5223,11 @@ make_bridge_port_setting (shvarFile *ifcfg) handle_bridging_opts (s_port, FALSE, value, handle_bridge_option, BRIDGE_OPT_TYPE_PORT_OPTION); nm_clear_g_free (&value_to_free); } + + read_bridge_vlans (ifcfg, + "BRIDGE_PORT_VLANS", + s_port, + NM_SETTING_BRIDGE_PORT_VLANS); } return s_port; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index f7fc36bfd6..f6b8f8c21a 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1463,6 +1463,43 @@ get_setting_default_boolean (NMSetting *setting, const char *prop) return ret; } +static gboolean +write_bridge_vlans (NMSetting *setting, + const char *property_name, + shvarFile *ifcfg, + const char *key, + GError **error) +{ + gs_unref_ptrarray GPtrArray *vlans = NULL; + NMBridgeVlan *vlan; + GString *string; + guint i; + + g_object_get (setting, property_name, &vlans, NULL); + + if (!vlans || !vlans->len) { + svUnsetValue (ifcfg, key); + return TRUE; + } + + string = g_string_new (""); + for (i = 0; i < vlans->len; i++) { + gs_free char *vlan_str = NULL; + + vlan = vlans->pdata[i]; + vlan_str = nm_bridge_vlan_to_str (vlan, error); + if (!vlan_str) + return FALSE; + if (string->len > 0) + g_string_append (string, ", "); + g_string_append (string, vlan_str); + } + + svSetValueStr (ifcfg, key, string->str); + g_string_free (string, TRUE); + return TRUE; +} + static gboolean write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error) { @@ -1552,6 +1589,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); + if (!write_bridge_vlans ((NMSetting *) s_bridge, + NM_SETTING_BRIDGE_VLANS, + ifcfg, + "BRIDGE_VLANS", + error)) + return FALSE; + svSetValueStr (ifcfg, "TYPE", TYPE_BRIDGE); *wired = write_wired_for_virtual (connection, ifcfg); @@ -1564,7 +1608,7 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError ** { NMSettingBridgePort *s_port; guint32 i; - GString *opts; + GString *string; s_port = nm_connection_get_setting_bridge_port (connection); if (!s_port) @@ -1573,28 +1617,35 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError ** svUnsetValue (ifcfg, "BRIDGING_OPTS"); /* Bridge options */ - opts = g_string_sized_new (32); + string = g_string_sized_new (32); i = nm_setting_bridge_port_get_priority (s_port); if (i != get_setting_default_uint (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY)) - g_string_append_printf (opts, "priority=%u", i); + g_string_append_printf (string, "priority=%u", i); i = nm_setting_bridge_port_get_path_cost (s_port); if (i != get_setting_default_uint (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST)) { - if (opts->len) - g_string_append_c (opts, ' '); - g_string_append_printf (opts, "path_cost=%u", i); + if (string->len) + g_string_append_c (string, ' '); + g_string_append_printf (string, "path_cost=%u", i); } if (nm_setting_bridge_port_get_hairpin_mode (s_port)) { - if (opts->len) - g_string_append_c (opts, ' '); - g_string_append_printf (opts, "hairpin_mode=1"); + if (string->len) + g_string_append_c (string, ' '); + g_string_append_printf (string, "hairpin_mode=1"); } - if (opts->len) - svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); - g_string_free (opts, TRUE); + if (string->len) + svSetValueStr (ifcfg, "BRIDGING_OPTS", string->str); + g_string_free (string, TRUE); + + if (!write_bridge_vlans ((NMSetting *) s_port, + NM_SETTING_BRIDGE_PORT_VLANS, + ifcfg, + "BRIDGE_PORT_VLANS", + error)) + return FALSE; return TRUE; } diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected index c478db38cc..0b4db7c1ed 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected @@ -2,6 +2,7 @@ HWADDR=31:33:33:37:BE:CD MTU=1492 TYPE=Ethernet BRIDGING_OPTS="priority=50 path_cost=33" +BRIDGE_PORT_VLANS="1 untagged, 2 pvid untagged, 4" NAME="Test Write Bridge Component" UUID=${UUID} ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index e504c7bbdf..99ffae403b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -7533,6 +7533,8 @@ test_write_bridge_main (void) NMIPAddress *addr; static const char *mac = "31:33:33:37:be:cd"; GError *error = NULL; + gs_unref_ptrarray GPtrArray *vlans = NULL; + NMBridgeVlan *vlan; connection = nm_simple_connection_new (); g_assert (connection); @@ -7553,11 +7555,23 @@ test_write_bridge_main (void) s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); nm_connection_add_setting (connection, NM_SETTING (s_bridge)); + vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); + vlan = nm_bridge_vlan_new (11); + nm_bridge_vlan_set_untagged (vlan, TRUE); + g_ptr_array_add (vlans, vlan); + vlan = nm_bridge_vlan_new (22); + nm_bridge_vlan_set_pvid (vlan, TRUE); + nm_bridge_vlan_set_untagged (vlan, TRUE); + g_ptr_array_add (vlans, vlan); + vlan = nm_bridge_vlan_new (44); + g_ptr_array_add (vlans, vlan); + g_object_set (s_bridge, NM_SETTING_BRIDGE_MAC_ADDRESS, mac, NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, 19008, NM_SETTING_BRIDGE_VLAN_FILTERING, TRUE, NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, 4000, + NM_SETTING_BRIDGE_VLANS, vlans, NULL); /* IP4 setting */ @@ -7635,6 +7649,8 @@ test_write_bridge_component (void) NMSetting *s_port; static const char *mac = "31:33:33:37:be:cd"; guint32 mtu = 1492; + gs_unref_ptrarray GPtrArray *vlans = NULL; + NMBridgeVlan *vlan; connection = nm_simple_connection_new (); g_assert (connection); @@ -7662,11 +7678,23 @@ test_write_bridge_component (void) NULL); /* Bridge port */ + vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); + vlan = nm_bridge_vlan_new (1); + nm_bridge_vlan_set_untagged (vlan, TRUE); + g_ptr_array_add (vlans, vlan); + vlan = nm_bridge_vlan_new (2); + nm_bridge_vlan_set_pvid (vlan, TRUE); + nm_bridge_vlan_set_untagged (vlan, TRUE); + g_ptr_array_add (vlans, vlan); + vlan = nm_bridge_vlan_new (4); + g_ptr_array_add (vlans, vlan); + s_port = nm_setting_bridge_port_new (); nm_connection_add_setting (connection, s_port); g_object_set (s_port, NM_SETTING_BRIDGE_PORT_PRIORITY, 50, NM_SETTING_BRIDGE_PORT_PATH_COST, 33, + NM_SETTING_BRIDGE_PORT_VLANS, vlans, NULL); nmtst_assert_connection_verifies (connection);