From d5538efb316eeda45749dfc8ccd6e850316a8540 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Wed, 25 Mar 2020 11:04:09 +0100 Subject: [PATCH 1/7] nm-setting-bridge: hide GObject structs from public API and embed private data Hide the object and class structures from public API. This is an API and ABI break, but of something that is very likely unused. This is mainly done to embed the private structure in the object itself. This has benefits for performance and debugability. --- libnm-core/nm-setting-bridge.c | 18 +++++++++++++++--- libnm-core/nm-setting-bridge.h | 16 +--------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 9c22ac0f7e..62538cff8d 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -63,9 +63,23 @@ typedef struct { bool stp:1; } NMSettingBridgePrivate; +/** + * NMSettingBridge: + * + * Bridging Settings + */ +struct _NMSettingBridge { + NMSetting parent; + NMSettingBridgePrivate _priv; +}; + +struct _NMSettingBridgeClass { + NMSettingClass parent; +}; + G_DEFINE_TYPE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) -#define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate)) +#define NM_SETTING_BRIDGE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingBridge, NM_IS_SETTING_BRIDGE, NMSetting) /*****************************************************************************/ @@ -1182,8 +1196,6 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NMSettingClass *setting_class = NM_SETTING_CLASS (klass); GArray *properties_override = _nm_sett_info_property_override_create_array (); - g_type_class_add_private (klass, sizeof (NMSettingBridgePrivate)); - object_class->get_property = get_property; object_class->set_property = set_property; object_class->finalize = finalize; diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index ee8b45f617..36ac9a5300 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -39,21 +39,7 @@ G_BEGIN_DECLS #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 -/** - * NMSettingBridge: - * - * Bridging Settings - */ -struct _NMSettingBridge { - NMSetting parent; -}; - -typedef struct { - NMSettingClass parent; - - /*< private >*/ - gpointer padding[4]; -} NMSettingBridgeClass; +typedef struct _NMSettingBridgeClass NMSettingBridgeClass; typedef struct _NMBridgeVlan NMBridgeVlan; From 93e38cbe56f4af73046863735e7f8c7747145a29 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Mon, 23 Mar 2020 19:29:24 +0100 Subject: [PATCH 2/7] nm-setting-bridge: add 'group-address' bridge option Also add related unit test. https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 3 + clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 63 ++++++ libnm-core/nm-setting-bridge.h | 4 + libnm-core/nm-utils-private.h | 2 + libnm-core/nm-utils.c | 35 ++++ libnm-core/tests/test-setting.c | 117 ++++++++++- libnm/libnm.ver | 1 + shared/nm-utils/nm-test-utils.h | 4 + src/devices/nm-device-bridge.c | 196 +++++++++++++----- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 4 + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 13 +- 12 files changed, 380 insertions(+), 63 deletions(-) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 27f1d2882b..30b49b44f5 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4890,6 +4890,9 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { .prompt = N_("MAC address ageing time [300]"), .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_GROUP_ADDRESS, + .property_type = &_pt_gobject_mac, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, .is_cli_option = TRUE, .property_alias = "group-forward-mask", diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index cc6bcdbbda..4a9ea829e9 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -114,6 +114,7 @@ #define DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS N_("Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9]).") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_AGEING_TIME N_("The Ethernet MAC address aging time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_FORWARD_DELAY N_("The Spanning Tree Protocol (STP) forwarding delay, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_ADDRESS N_("If specified, The MAC address of the multicast group this bridge uses for STP. The address must be a link-local address in standard Ethernet MAC address format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If not specified the default value is 01:80:C2:00:00:00.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_GROUP_FORWARD_MASK N_("A mask of group addresses to forward. Usually, group addresses in the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to standards. This property is a mask of 16 bits, each corresponding to a group address in that range that must be forwarded. The mask can't have bits 0, 1 or 2 set because they are used for STP, MAC pause frames and LACP.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 62538cff8d..4190497aae 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -41,6 +41,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_HELLO_TIME, PROP_MAX_AGE, PROP_AGEING_TIME, + PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, @@ -51,6 +52,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, typedef struct { GPtrArray *vlans; char * mac_address; + char * group_address; guint32 ageing_time; guint16 priority; guint16 forward_delay; @@ -899,6 +901,22 @@ nm_setting_bridge_clear_vlans (NMSettingBridge *setting) } } +/** + * nm_setting_bridge_get_group_address: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:group-address property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_group_address (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->group_address; +} + /*****************************************************************************/ static gboolean @@ -989,6 +1007,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_SETTING_BRIDGE_VLANS)) return FALSE; + if ( priv->group_address + && !_nm_utils_hwaddr_link_local_valid (priv->group_address)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid link local MAC address")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_GROUP_ADDRESS); + return FALSE; + } + /* Failures from here on are NORMALIZABLE... */ if (!_nm_utils_bridge_vlan_verify_list (priv->vlans, @@ -1069,6 +1097,9 @@ get_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: g_value_set_uint (value, priv->ageing_time); break; + case PROP_GROUP_ADDRESS: + g_value_set_string (value, priv->group_address); + break; case PROP_GROUP_FORWARD_MASK: g_value_set_uint (value, priv->group_forward_mask); break; @@ -1122,6 +1153,11 @@ set_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: priv->ageing_time = g_value_get_uint (value); break; + case PROP_GROUP_ADDRESS: + g_free (priv->group_address); + priv->group_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value), + ETH_ALEN); + break; case PROP_GROUP_FORWARD_MASK: priv->group_forward_mask = (guint16) g_value_get_uint (value); break; @@ -1184,6 +1220,7 @@ finalize (GObject *object) NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object); g_free (priv->mac_address); + g_free (priv->group_address); g_ptr_array_unref (priv->vlans); G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object); @@ -1493,6 +1530,32 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) */ _nm_properties_override_dbus (properties_override, "interface-name", &nm_sett_info_propert_type_deprecated_interface_name); + /** + * NMSettingBridge:group-address: + * + * If specified, The MAC address of the multicast group this bridge uses for STP. + * + * The address must be a link-local address in standard Ethernet MAC address format, + * ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. + * If not specified the default value is 01:80:C2:00:00:00. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: group-address + * variable: BRIDGING_OPTS: group_address= + * description: STP group address. + * example: BRIDGING_OPTS="group_address=01:80:C2:00:00:0A" + * ---end--- + */ + obj_properties[PROP_GROUP_ADDRESS] = + g_param_spec_string (NM_SETTING_BRIDGE_GROUP_ADDRESS, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj (properties_override, obj_properties[PROP_GROUP_ADDRESS], &nm_sett_info_propert_type_mac_address); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index 36ac9a5300..e4ff1af6d0 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -35,6 +35,7 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" #define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" #define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 @@ -116,6 +117,9 @@ char * nm_bridge_vlan_to_str (const NMBridgeVlan *vlan, GError **error); NM_AVAILABLE_IN_1_18 NMBridgeVlan * nm_bridge_vlan_from_str (const char *str, GError **error); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_group_address (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index 67074840ff..f3e9d3f1cb 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -65,6 +65,8 @@ void _nm_utils_bytes_from_dbus (GVariant *dbus_value, char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length); +gboolean _nm_utils_hwaddr_link_local_valid (const char *mac); + void _nm_utils_format_variant_attributes_full (GString *str, const NMUtilsNamedValue *values, guint num_values, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 2cfaea6dd4..062ff39337 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -4186,6 +4186,41 @@ _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length) return g_strdup (mac); } +/* + * Determine if given Ethernet address is link-local + * + * Return value: %TRUE if @mac is link local + * reserved addr (01:80:c2:00:00:0X) per IEEE 802.1Q 8.6.3 Frame filtering, %FALSE if not. + */ +gboolean +_nm_utils_hwaddr_link_local_valid (const char *mac) +{ + guint8 mac_net[ETH_ALEN]; + static const guint8 eth_reserved_addr_base[] = { + 0x01, 0x80, + 0xc2, 0x00, + 0x00 + }; + + if (!mac) + return FALSE; + + if (!nm_utils_hwaddr_aton (mac, mac_net, ETH_ALEN)) + return FALSE; + + if ( memcmp (mac_net, + eth_reserved_addr_base, ETH_ALEN - 1) + || (mac_net[5] & 0xF0)) + return FALSE; + + if ( mac_net[5] == 1 /* 802.3x Pause address */ + || mac_net[5] == 2 /* 802.3ad Slow protocols */ + || mac_net[5] == 3) /* 802.1X PAE address */ + return FALSE; + + return TRUE; +} + /** * nm_utils_hwaddr_matches: * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 382c52a944..878c6472af 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -500,8 +500,6 @@ create_bond_connection (NMConnection **con, NMSettingBond **s_bond) NULL, NM_SETTING_BOND_SETTING_NAME, &s_con); - g_assert (*con); - g_assert (s_con); g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bond0", NULL); @@ -512,28 +510,25 @@ create_bond_connection (NMConnection **con, NMSettingBond **s_bond) } #define test_verify_options(exp, ...) \ - _test_verify_options (NM_MAKE_STRV (__VA_ARGS__), exp) + _test_verify_options (exp, NM_MAKE_STRV (__VA_ARGS__)) static void -_test_verify_options (const char *const *options, - gboolean expected_result) +_test_verify_options (gboolean expected_result, + const char *const *options) { gs_unref_object NMConnection *con = NULL; NMSettingBond *s_bond; - GError *error = NULL; - gboolean success; const char *const *option; + g_assert (NM_PTRARRAY_LEN (options) % 2 == 0); + create_bond_connection (&con, &s_bond); - for (option = options; option[0] && option[1]; option += 2) + for (option = options; option[0]; option += 2) g_assert (nm_setting_bond_add_option (s_bond, option[0], option[1])); if (expected_result) { 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); } else { nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, @@ -1874,6 +1869,105 @@ test_bridge_vlans (void) nm_bridge_vlan_unref (v2); } +static void +create_bridge_connection (NMConnection **con, NMSettingBridge **s_bridge) +{ + NMSettingConnection *s_con; + + g_assert (con); + g_assert (s_bridge); + + *con = nmtst_create_minimal_connection ("bridge", + NULL, + NM_SETTING_BOND_SETTING_NAME, + &s_con); + + g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, "bridge0", NULL); + + *s_bridge = (NMSettingBridge *) nm_setting_bridge_new (); + g_assert (*s_bridge); + + nm_connection_add_setting (*con, NM_SETTING (*s_bridge)); +} + +#define test_verify_options_bridge(exp, ...) \ + _test_verify_options_bridge (exp, NM_MAKE_STRV (__VA_ARGS__)) + +static void +_test_verify_options_bridge (gboolean expected_result, + const char *const *options) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBridge *s_bridge; + const char *const *option; + + g_assert (NM_PTRARRAY_LEN (options) % 2 == 0); + + create_bridge_connection (&con, &s_bridge); + + for (option = options; option[0]; option += 2) { + const char *option_key = option[0]; + const char *option_val = option[1]; + GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (s_bridge), option_key); + + g_assert (pspec); + g_assert (option_val); + + switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { + case G_TYPE_UINT: { + guint uvalue; + + uvalue = _nm_utils_ascii_str_to_uint64 (option_val, 10, 0, G_MAXUINT, 0); + g_object_set (s_bridge, option_key, uvalue, NULL); + } + break; + case G_TYPE_BOOLEAN: { + gboolean bvalue; + + bvalue = _nm_utils_ascii_str_to_bool (option_val, FALSE); + g_object_set (s_bridge, option_key, bvalue, NULL); + } + break; + case G_TYPE_STRING: + g_object_set (s_bridge, option_key, option_val, NULL); + break; + default: + g_assert_not_reached(); + break; + } + } + + if (expected_result) + nmtst_assert_connection_verifies_and_normalizable (con); + else { + nmtst_assert_connection_unnormalizable (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + } +} + +static void +test_bridge_verify (void) +{ + /* group-address */ + test_verify_options_bridge (FALSE, + "group-address", "nonsense"); + test_verify_options_bridge (FALSE, + "group-address", "FF:FF:FF:FF:FF:FF"); + test_verify_options_bridge (FALSE, + "group-address", "01:02:03:04:05:06"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge (FALSE, + "group-address", "01:80:C2:00:00:02"); + test_verify_options_bridge (FALSE, + "group-address", "01:80:C2:00:00:03"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:00"); + test_verify_options_bridge (TRUE, + "group-address", "01:80:C2:00:00:0A"); +} + /*****************************************************************************/ static void @@ -3653,6 +3747,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/tc_config/dbus", test_tc_config_dbus); g_test_add_func ("/libnm/settings/bridge/vlans", test_bridge_vlans); + g_test_add_func ("/libnm/settings/bridge/verify", test_bridge_verify); g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin", test_runner_roundrobin_sync_from_config); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index b83aa33821..d93a14c95a 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1685,6 +1685,7 @@ global: nm_setting_802_1x_get_domain_match; nm_setting_802_1x_get_phase2_domain_match; nm_setting_bond_get_option_normalized; + nm_setting_bridge_get_group_address; nm_setting_vrf_get_table; nm_setting_vrf_get_type; nm_setting_vrf_new; diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index 0d03456319..96e361358f 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -1803,8 +1803,12 @@ nmtst_create_minimal_connection (const char *id, const char *uuid, const char *t con = nm_connection_new (); #endif + g_assert (con); + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); + g_assert (s_con); + g_object_set (s_con, NM_SETTING_CONNECTION_ID, id, NM_SETTING_CONNECTION_UUID, uuid, diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 874d4966e3..ecac47a2b7 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -158,11 +158,26 @@ complete_connection (NMDevice *device, return TRUE; } +static void +from_sysfs_group_address (const char *value, GValue *out) +{ + if (!nm_utils_hwaddr_matches (value, -1, "01:80:C2:00:00:00", -1)) + g_value_set_string (out, value); +} + +static const char * +to_sysfs_group_address (GValue *value) +{ + return g_value_get_string (value) ?: "01:80:C2:00:00:00"; +} + /*****************************************************************************/ typedef struct { const char *name; const char *sysname; + const char *(*to_sysfs) (GValue *value); + void (*from_sysfs) (const char *value, GValue *out); uint nm_min; uint nm_max; uint nm_default; @@ -173,40 +188,55 @@ typedef struct { static const Option master_options[] = { { NM_SETTING_BRIDGE_STP, "stp_state", /* this must stay as the first item */ + NULL, NULL, 0, 1, 1, FALSE, FALSE, FALSE }, { NM_SETTING_BRIDGE_PRIORITY, "priority", + NULL, NULL, 0, G_MAXUINT16, 0x8000, TRUE, FALSE, TRUE }, { NM_SETTING_BRIDGE_FORWARD_DELAY, "forward_delay", + NULL, NULL, 0, NM_BR_MAX_FORWARD_DELAY, 15, TRUE, TRUE, TRUE}, { NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", + NULL, NULL, 0, NM_BR_MAX_HELLO_TIME, 2, TRUE, TRUE, TRUE }, { NM_SETTING_BRIDGE_MAX_AGE, "max_age", + NULL, NULL, 0, NM_BR_MAX_MAX_AGE, 20, TRUE, TRUE, TRUE }, { NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", + NULL, NULL, NM_BR_MIN_AGEING_TIME, NM_BR_MAX_AGEING_TIME, 300, TRUE, TRUE, FALSE }, { NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "group_fwd_mask", + NULL, NULL, 0, 0xFFFF, 0, TRUE, FALSE, FALSE }, { NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "multicast_snooping", + NULL, NULL, 0, 1, 1, FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_GROUP_ADDRESS, "group_addr", + to_sysfs_group_address, from_sysfs_group_address, + 0, 0, 0, + FALSE, FALSE, FALSE }, { NULL, NULL } }; static const Option slave_options[] = { { NM_SETTING_BRIDGE_PORT_PRIORITY, "priority", + NULL, NULL, 0, NM_BR_PORT_MAX_PRIORITY, NM_BR_PORT_DEF_PRIORITY, TRUE, FALSE }, { NM_SETTING_BRIDGE_PORT_PATH_COST, "path_cost", + NULL, NULL, 0, NM_BR_PORT_MAX_PATH_COST, 100, TRUE, FALSE }, { NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", + NULL, NULL, 0, 1, 0, FALSE, FALSE }, { NULL, NULL } @@ -216,10 +246,9 @@ static void commit_option (NMDevice *device, NMSetting *setting, const Option *option, gboolean slave) { int ifindex = nm_device_get_ifindex (device); + nm_auto_unset_gvalue GValue val = G_VALUE_INIT; GParamSpec *pspec; - GValue val = G_VALUE_INIT; - guint32 uval = 0; - char value[100]; + const char *value; g_assert (setting); @@ -229,37 +258,67 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool /* Get the property's value */ g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_object_get_property ((GObject *) setting, option->name, &val); - if (G_VALUE_HOLDS_BOOLEAN (&val)) - uval = g_value_get_boolean (&val) ? 1 : 0; - else if (G_VALUE_HOLDS_UINT (&val)) { - uval = g_value_get_uint (&val); - /* zero means "unspecified" for some NM properties but isn't in the - * allowed kernel range, so reset the property to the default value. - */ - if (option->default_if_zero && uval == 0) { - g_value_unset (&val); - g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_param_value_set_default (pspec, &val); - uval = g_value_get_uint (&val); - } + if (option->to_sysfs) { + value = option->to_sysfs(&val); + goto out; + } - /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. - * In reality it's not centiseconds, but depends on HZ and USER_HZ, which - * is almost always works out to be a multiplier of 100, so we can assume - * centiseconds. See clock_t_to_jiffies(). - */ - if (option->user_hz_compensate) - uval *= 100; - } else - nm_assert_not_reached (); - g_value_unset (&val); + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + value = g_value_get_boolean (&val) ? "1" : "0"; + break; + case G_TYPE_UINT: { + char value_buf[100]; + guint uval; - nm_sprintf_buf (value, "%u", uval); - if (slave) - nm_platform_sysctl_slave_set_option (nm_device_get_platform (device), ifindex, option->sysname, value); - else - nm_platform_sysctl_master_set_option (nm_device_get_platform (device), ifindex, option->sysname, value); + uval = g_value_get_uint (&val); + + /* zero means "unspecified" for some NM properties but isn't in the + * allowed kernel range, so reset the property to the default value. + */ + if (option->default_if_zero && uval == 0) { + g_value_unset (&val); + g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_param_value_set_default (pspec, &val); + uval = g_value_get_uint (&val); + } + + /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. + * In reality it's not centiseconds, but depends on HZ and USER_HZ, which + * is almost always works out to be a multiplier of 100, so we can assume + * centiseconds. See clock_t_to_jiffies(). + */ + if (option->user_hz_compensate) + uval *= 100; + + nm_sprintf_buf (value_buf, "%u", uval); + value = value_buf; + } + break; + case G_TYPE_STRING: + value = g_value_get_string (&val); + break; + default: + nm_assert_not_reached (); + break; + } + +out: + if (!value) + return; + + if (slave) { + nm_platform_sysctl_slave_set_option (nm_device_get_platform (device), + ifindex, + option->sysname, + value); + } else { + nm_platform_sysctl_master_set_option (nm_device_get_platform (device), + ifindex, + option->sysname, + value); + } } static const NMPlatformBridgeVlan ** @@ -335,29 +394,68 @@ update_connection (NMDevice *device, NMConnection *connection) option++; for (; option->name; option++) { - gs_free char *str = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, option->sysname); - uint value; + nm_auto_unset_gvalue GValue value = G_VALUE_INIT; + gs_free char *str = NULL; + GParamSpec *pspec; + + str = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, option->sysname); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (s_bridge), option->name); if (!stp_value && option->only_with_stp) continue; - if (str) { - /* See comments in set_sysfs_uint() about centiseconds. */ - if (option->user_hz_compensate) { - value = _nm_utils_ascii_str_to_int64 (str, 10, - option->nm_min * 100, - option->nm_max * 100, - option->nm_default * 100); - value /= 100; - } else { - value = _nm_utils_ascii_str_to_int64 (str, 10, - option->nm_min, - option->nm_max, - option->nm_default); - } - g_object_set (s_bridge, option->name, value, NULL); - } else + if (!str) { _LOGW (LOGD_BRIDGE, "failed to read bridge setting '%s'", option->sysname); + continue; + } + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + if (option->from_sysfs) { + option->from_sysfs(str, &value); + goto out; + } + + switch (pspec->value_type) { + case G_TYPE_UINT: { + guint uvalue; + + /* See comments in set_sysfs_uint() about centiseconds. */ + if (option->user_hz_compensate) { + uvalue = _nm_utils_ascii_str_to_int64 (str, 10, + option->nm_min * 100, + option->nm_max * 100, + option->nm_default * 100); + uvalue /= 100; + } else { + uvalue = _nm_utils_ascii_str_to_int64 (str, 10, + option->nm_min, + option->nm_max, + option->nm_default); + } + g_value_set_uint (&value, uvalue); + } + break; + case G_TYPE_BOOLEAN: { + gboolean bvalue; + + bvalue = _nm_utils_ascii_str_to_int64 (str, 10, + option->nm_min, + option->nm_max, + option->nm_default); + g_value_set_boolean (&value, bvalue); + } + break; + case G_TYPE_STRING: + g_value_set_string (&value, str); + break; + default: + nm_assert_not_reached(); + break; + } + +out: + g_object_set_property (G_OBJECT (s_bridge), option->name, &value); } } 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 60bc504717..2f8d8afaaf 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5160,6 +5160,7 @@ handle_bridge_option (NMSetting *setting, { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, + { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, @@ -5216,6 +5217,9 @@ handle_bridge_option (NMSetting *setting, goto warn; } return; + case G_TYPE_STRING: + nm_g_object_set_property_string (G_OBJECT (setting), m[i].property_name, value, NULL); + return; default: nm_assert_not_reached (); continue; 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 1876aa31ed..181e6bbf24 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1438,8 +1438,8 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire NMSettingBridge *s_bridge; guint32 i; gboolean b; + const char *s; GString *opts; - const char *mac; s_bridge = nm_connection_get_setting_bridge (connection); if (!s_bridge) { @@ -1450,8 +1450,8 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire svSetValueBoolean (ifcfg, "STP", FALSE); - mac = nm_setting_bridge_get_mac_address (s_bridge); - svSetValueStr (ifcfg, "BRIDGE_MACADDR", mac); + s = nm_setting_bridge_get_mac_address (s_bridge); + svSetValueStr (ifcfg, "BRIDGE_MACADDR", s); /* Bridge options */ opts = g_string_sized_new (32); @@ -1487,6 +1487,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "ageing_time=%u", i); } + s = nm_setting_bridge_get_group_address (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "group_address=%s", s); + } + i = nm_setting_bridge_get_group_forward_mask (s_bridge); if (i != get_setting_default_uint (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_GROUP_FORWARD_MASK)) { if (opts->len) From f5352ff656b888ea7e65c323087806b869b1e153 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 26 Mar 2020 12:02:20 +0100 Subject: [PATCH 3/7] nm-setting-bridge: add 'vlan-protocol' bridge option Also add related unit test. https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 7 +++ clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 62 +++++++++++++++++++ libnm-core/nm-setting-bridge.h | 4 ++ libnm-core/tests/test-setting.c | 11 ++++ libnm/libnm.ver | 1 + src/devices/nm-device-bridge.c | 31 ++++++++++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1 + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 7 +++ 9 files changed, 125 insertions(+) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 30b49b44f5..a46e55510d 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4911,6 +4911,13 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_PROTOCOL, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = NM_MAKE_STRV ("802.1Q", + "802.1ad"), + ), + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLANS, .property_type = &_pt_objlist, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index 4a9ea829e9..8bf37c58aa 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -124,6 +124,7 @@ #define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_PROTOCOL N_("If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 4190497aae..786c75434d 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -46,6 +46,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, + PROP_VLAN_PROTOCOL, PROP_VLANS, ); @@ -53,6 +54,7 @@ typedef struct { GPtrArray *vlans; char * mac_address; char * group_address; + char * vlan_protocol; guint32 ageing_time; guint16 priority; guint16 forward_delay; @@ -917,6 +919,22 @@ nm_setting_bridge_get_group_address (const NMSettingBridge *setting) return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->group_address; } +/** + * nm_setting_bridge_get_vlan_protocol: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-protocol property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_protocol; +} + /*****************************************************************************/ static gboolean @@ -1017,6 +1035,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( priv->vlan_protocol + && !NM_IN_STRSET (priv->vlan_protocol, + "802.1Q", + "802.1ad")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid VLAN filtering protocol")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_VLAN_PROTOCOL); + return FALSE; + } + /* Failures from here on are NORMALIZABLE... */ if (!_nm_utils_bridge_vlan_verify_list (priv->vlans, @@ -1112,6 +1142,9 @@ get_property (GObject *object, guint prop_id, case PROP_VLAN_DEFAULT_PVID: g_value_set_uint (value, priv->vlan_default_pvid); break; + case PROP_VLAN_PROTOCOL: + g_value_set_string (value, priv->vlan_protocol); + break; case PROP_VLANS: g_value_take_boxed (value, _nm_utils_copy_array (priv->vlans, (NMUtilsCopyFunc) nm_bridge_vlan_ref, @@ -1170,6 +1203,10 @@ set_property (GObject *object, guint prop_id, case PROP_VLAN_DEFAULT_PVID: priv->vlan_default_pvid = g_value_get_uint (value); break; + case PROP_VLAN_PROTOCOL: + g_free (priv->vlan_protocol); + priv->vlan_protocol = g_value_dup_string (value); + break; case PROP_VLANS: g_ptr_array_unref (priv->vlans); priv->vlans = _nm_utils_copy_array (g_value_get_boxed (value), @@ -1221,6 +1258,7 @@ finalize (GObject *object) g_free (priv->mac_address); g_free (priv->group_address); + g_free (priv->vlan_protocol); g_ptr_array_unref (priv->vlans); G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object); @@ -1556,6 +1594,30 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj (properties_override, obj_properties[PROP_GROUP_ADDRESS], &nm_sett_info_propert_type_mac_address); + /** + * NMSettingBridge:vlan-protocol: + * + * If specified, the protocol used for VLAN filtering. + * + * Supported values are: '802.1Q', '802.1ad'. + * If not specified the default value is '802.1Q'. + * + * Since: 1.24 + **/ + /* ---ifcfg-rh--- + * property: vlan-protocol + * variable: BRIDGING_OPTS: vlan_protocol= + * description: VLAN filtering protocol. + * example: BRIDGING_OPTS="vlan_protocol=802.1Q" + * ---end--- + */ + obj_properties[PROP_VLAN_PROTOCOL] = + g_param_spec_string (NM_SETTING_BRIDGE_VLAN_PROTOCOL, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index e4ff1af6d0..f1076ab443 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -36,6 +36,7 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" #define NM_SETTING_BRIDGE_VLANS "vlans" #define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" +#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 @@ -120,6 +121,9 @@ NMBridgeVlan * nm_bridge_vlan_from_str (const char *str, GError **error); NM_AVAILABLE_IN_1_24 const char * nm_setting_bridge_get_group_address (const NMSettingBridge *setting); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 878c6472af..58e2bd5108 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -1966,6 +1966,17 @@ test_bridge_verify (void) "group-address", "01:80:C2:00:00:00"); test_verify_options_bridge (TRUE, "group-address", "01:80:C2:00:00:0A"); + /* vlan-protocol */ + test_verify_options_bridge (FALSE, + "vlan-protocol", "nonsense124"); + test_verify_options_bridge (FALSE, + "vlan-protocol", "802.11"); + test_verify_options_bridge (FALSE, + "vlan-protocol", "802.1Q1"); + test_verify_options_bridge (TRUE, + "vlan-protocol", "802.1Q"); + test_verify_options_bridge (TRUE, + "vlan-protocol", "802.1ad"); } /*****************************************************************************/ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index d93a14c95a..14099ebb5b 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1686,6 +1686,7 @@ global: nm_setting_802_1x_get_phase2_domain_match; nm_setting_bond_get_option_normalized; nm_setting_bridge_get_group_address; + nm_setting_bridge_get_vlan_protocol; nm_setting_vrf_get_table; nm_setting_vrf_get_type; nm_setting_vrf_new; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index ecac47a2b7..6b666b9551 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -171,6 +171,33 @@ to_sysfs_group_address (GValue *value) return g_value_get_string (value) ?: "01:80:C2:00:00:00"; } +static void +from_sysfs_vlan_protocol (const char *value, GValue *out) +{ + switch (_nm_utils_ascii_str_to_uint64 (value, 16, 0, G_MAXUINT, -1)) { + case ETH_P_8021Q: + /* default value */ + break; + case ETH_P_8021AD: + g_value_set_string (out, "802.1ad"); + break; + } +} + +static const char * +to_sysfs_vlan_protocol (GValue *value) +{ + const char *str = g_value_get_string (value); + + if (nm_streq0 (str, "802.1ad")) { + G_STATIC_ASSERT_EXPR (ETH_P_8021AD == 0x88A8); + return "0x88A8"; + } + + G_STATIC_ASSERT_EXPR (ETH_P_8021Q == 0x8100); + return "0x8100"; +} + /*****************************************************************************/ typedef struct { @@ -223,6 +250,10 @@ static const Option master_options[] = { to_sysfs_group_address, from_sysfs_group_address, 0, 0, 0, FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_VLAN_PROTOCOL, "vlan_protocol", + to_sysfs_vlan_protocol, from_sysfs_vlan_protocol, + 0, 0, 0, + FALSE, FALSE, FALSE }, { NULL, NULL } }; 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 2f8d8afaaf..6076011fe9 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5162,6 +5162,7 @@ handle_bridge_option (NMSetting *setting, { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_protocol", NM_SETTING_BRIDGE_VLAN_PROTOCOL, BRIDGE_OPT_TYPE_OPTION }, { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, 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 181e6bbf24..fa947f10ab 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1522,6 +1522,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "default_pvid=%u", i); } + s = nm_setting_bridge_get_vlan_protocol (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "vlan_protocol=%s", s); + } + if (opts->len) svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); From bd30491f429763b69ca1401ebea1f6d4678605bd Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 26 Mar 2020 16:23:50 +0100 Subject: [PATCH 4/7] nm-setting-bridge: add 'vlan-stats-enabled' bridge option https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 3 ++ clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 45 +++++++++++++++++++ libnm-core/nm-setting-bridge.h | 32 +++++++------ libnm/libnm.ver | 1 + src/devices/nm-device-bridge.c | 4 ++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1 + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 7 +++ 8 files changed, 80 insertions(+), 14 deletions(-) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index a46e55510d..796ac00217 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4911,6 +4911,9 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, + .property_type = &_pt_gobject_bool, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_PROTOCOL, .property_type = &_pt_gobject_string, .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index 8bf37c58aa..7b35a05364 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -125,6 +125,7 @@ #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_PROTOCOL N_("If specified, the protocol used for VLAN filtering. Supported values are: '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_STATS_ENABLED N_("Controls whether per-VLAN stats accounting is enabled.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 786c75434d..02adcaccc2 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -30,6 +30,7 @@ #define BRIDGE_PRIORITY_DEFAULT 0x8000 #define BRIDGE_STP_DEFAULT TRUE #define BRIDGE_VLAN_DEFAULT_PVID_DEFAULT 1 +#define BRIDGE_VLAN_STATS_ENABLED_DEFAULT FALSE /*****************************************************************************/ @@ -47,6 +48,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, PROP_VLAN_PROTOCOL, + PROP_VLAN_STATS_ENABLED, PROP_VLANS, ); @@ -65,6 +67,7 @@ typedef struct { bool multicast_snooping:1; bool vlan_filtering:1; bool stp:1; + bool vlan_stats_enabled:1; } NMSettingBridgePrivate; /** @@ -935,6 +938,22 @@ nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting) return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_protocol; } +/** + * nm_setting_bridge_get_vlan_stats_enabled: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_stats_enabled; +} + /*****************************************************************************/ static gboolean @@ -1145,6 +1164,9 @@ get_property (GObject *object, guint prop_id, case PROP_VLAN_PROTOCOL: g_value_set_string (value, priv->vlan_protocol); break; + case PROP_VLAN_STATS_ENABLED: + g_value_set_boolean (value, priv->vlan_stats_enabled); + break; case PROP_VLANS: g_value_take_boxed (value, _nm_utils_copy_array (priv->vlans, (NMUtilsCopyFunc) nm_bridge_vlan_ref, @@ -1207,6 +1229,9 @@ set_property (GObject *object, guint prop_id, g_free (priv->vlan_protocol); priv->vlan_protocol = g_value_dup_string (value); break; + case PROP_VLAN_STATS_ENABLED: + priv->vlan_stats_enabled = g_value_get_boolean (value); + break; case PROP_VLANS: g_ptr_array_unref (priv->vlans); priv->vlans = _nm_utils_copy_array (g_value_get_boxed (value), @@ -1236,6 +1261,7 @@ nm_setting_bridge_init (NMSettingBridge *setting) priv->priority = BRIDGE_PRIORITY_DEFAULT; priv->stp = BRIDGE_STP_DEFAULT; priv->vlan_default_pvid = BRIDGE_VLAN_DEFAULT_PVID_DEFAULT; + priv->vlan_stats_enabled = BRIDGE_VLAN_STATS_ENABLED_DEFAULT; } /** @@ -1618,6 +1644,25 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingBridge:vlan-stats-enabled: + * + * Controls whether per-VLAN stats accounting is enabled. + **/ + /* ---ifcfg-rh--- + * property: vlan-stats-enabled + * variable: BRIDGING_OPTS: vlan_stats_enabled= + * default: 0 + * example: BRIDGING_OPTS="vlan_stats_enabled=1" + * ---end--- + */ + obj_properties[PROP_VLAN_STATS_ENABLED] = + g_param_spec_boolean (NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "", "", + BRIDGE_VLAN_STATS_ENABLED_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index f1076ab443..5c955fbefe 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -23,20 +23,21 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_SETTING_NAME "bridge" -#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" -#define NM_SETTING_BRIDGE_STP "stp" -#define NM_SETTING_BRIDGE_PRIORITY "priority" -#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" -#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" -#define NM_SETTING_BRIDGE_MAX_AGE "max-age" -#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" -#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" -#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" -#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" -#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" -#define NM_SETTING_BRIDGE_VLANS "vlans" -#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" -#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" +#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" +#define NM_SETTING_BRIDGE_STP "stp" +#define NM_SETTING_BRIDGE_PRIORITY "priority" +#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" +#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" +#define NM_SETTING_BRIDGE_MAX_AGE "max-age" +#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" +#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" +#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" +#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" +#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" +#define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" +#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" +#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 @@ -124,6 +125,9 @@ const char * nm_setting_bridge_get_group_address (const NMSettingBridge *setti NM_AVAILABLE_IN_1_24 const char * nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setting); +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 14099ebb5b..839272fefe 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1687,6 +1687,7 @@ global: nm_setting_bond_get_option_normalized; nm_setting_bridge_get_group_address; nm_setting_bridge_get_vlan_protocol; + nm_setting_bridge_get_vlan_stats_enabled; nm_setting_vrf_get_table; nm_setting_vrf_get_type; nm_setting_vrf_new; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 6b666b9551..01ef1c4032 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -254,6 +254,10 @@ static const Option master_options[] = { to_sysfs_vlan_protocol, from_sysfs_vlan_protocol, 0, 0, 0, FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "vlan_stats_enabled", + NULL, NULL, + 0, 1, 0, + FALSE, FALSE, FALSE }, { NULL, NULL } }; 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 6076011fe9..51d70c127e 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5163,6 +5163,7 @@ handle_bridge_option (NMSetting *setting, { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, { "vlan_protocol", NM_SETTING_BRIDGE_VLAN_PROTOCOL, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_stats_enabled", NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, BRIDGE_OPT_TYPE_OPTION }, { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, 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 fa947f10ab..fe6f2109e6 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1529,6 +1529,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "vlan_protocol=%s", s); } + b = nm_setting_bridge_get_vlan_stats_enabled (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_VLAN_STATS_ENABLED)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "vlan_stats_enabled=%u", (guint) b); + } + if (opts->len) svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); From e01d3b4c2b899cc7e72b92f10e5afe6106fe40b2 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 26 Mar 2020 18:38:04 +0100 Subject: [PATCH 5/7] nm-setting-bridge: add 'multicast-router' bridge option Also add related unit test. https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 8 ++ clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 76 +++++++++++++++++++ libnm-core/nm-setting-bridge.h | 4 + libnm-core/tests/test-setting.c | 21 +++++ libnm/libnm.ver | 1 + src/devices/nm-device-bridge.c | 36 +++++++++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1 + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 7 ++ 9 files changed, 155 insertions(+) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 796ac00217..aefbfd3cdb 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4905,6 +4905,14 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { .prompt = N_("Enable IGMP snooping [no]"), .property_type = &_pt_gobject_bool, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_ROUTER, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = NM_MAKE_STRV ("auto", + "disabled", + "enabled"), + ), + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_VLAN_FILTERING, .property_type = &_pt_gobject_bool, ), diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index 7b35a05364..eb51af3d54 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -119,6 +119,7 @@ #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 02adcaccc2..9bb4303e50 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -44,6 +44,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_AGEING_TIME, PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, + PROP_MULTICAST_ROUTER, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, @@ -55,6 +56,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, typedef struct { GPtrArray *vlans; char * mac_address; + char * multicast_router; char * group_address; char * vlan_protocol; guint32 ageing_time; @@ -954,6 +956,21 @@ nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting) return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->vlan_stats_enabled; } +/** + * nm_setting_bridge_get_multicast_router: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-router property of the setting + * + * Since 1.24 + **/ +const char * +nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_router; +} /*****************************************************************************/ static gboolean @@ -1066,6 +1083,33 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if (priv->multicast_router) { + if (!NM_IN_STRSET (priv->multicast_router, + "auto", + "enabled", + "disabled")) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("is not a valid option")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_ROUTER); + return FALSE; + } + + if ( NM_IN_STRSET (priv->multicast_router, + "auto", + "enabled") + && !priv->multicast_snooping) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' option requires '%s' option to be enabled"), + NM_SETTING_BRIDGE_MULTICAST_ROUTER, NM_SETTING_BRIDGE_MULTICAST_SNOOPING); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_ROUTER); + return FALSE; + } + } + /* Failures from here on are NORMALIZABLE... */ if (!_nm_utils_bridge_vlan_verify_list (priv->vlans, @@ -1155,6 +1199,9 @@ get_property (GObject *object, guint prop_id, case PROP_MULTICAST_SNOOPING: g_value_set_boolean (value, priv->multicast_snooping); break; + case PROP_MULTICAST_ROUTER: + g_value_set_string (value, priv->multicast_router); + break; case PROP_VLAN_FILTERING: g_value_set_boolean (value, priv->vlan_filtering); break; @@ -1219,6 +1266,10 @@ set_property (GObject *object, guint prop_id, case PROP_MULTICAST_SNOOPING: priv->multicast_snooping = g_value_get_boolean (value); break; + case PROP_MULTICAST_ROUTER: + g_free (priv->multicast_router); + priv->multicast_router = g_value_dup_string (value); + break; case PROP_VLAN_FILTERING: priv->vlan_filtering = g_value_get_boolean (value); break; @@ -1283,6 +1334,7 @@ finalize (GObject *object) NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object); g_free (priv->mac_address); + g_free (priv->multicast_router); g_free (priv->group_address); g_free (priv->vlan_protocol); g_ptr_array_unref (priv->vlans); @@ -1663,6 +1715,30 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingBridge:multicast-router: + * + * Sets bridge's multicast router. + * multicast-snooping must be enabled for this option to work. + * + * Supported values are: 'auto', 'disabled', 'enabled'. + * If not specified the default value is 'auto'. + **/ + /* ---ifcfg-rh--- + * property: multicast-router + * variable: BRIDGING_OPTS: multicast_router= + * values: auto, enabled, disabled + * default: auto + * example: BRIDGING_OPTS="multicast_router=enabled" + * ---end--- + */ + obj_properties[PROP_MULTICAST_ROUTER] = + g_param_spec_string (NM_SETTING_BRIDGE_MULTICAST_ROUTER, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index 5c955fbefe..a1379693d0 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" #define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" #define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" +#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" #define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" #define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" #define NM_SETTING_BRIDGE_VLANS "vlans" @@ -128,6 +129,9 @@ const char * nm_setting_bridge_get_vlan_protocol (const NMSettingBridge *setti NM_AVAILABLE_IN_1_24 gboolean nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *setting); +NM_AVAILABLE_IN_1_24 +const char * nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 58e2bd5108..cb8f41fb03 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -1977,6 +1977,27 @@ test_bridge_verify (void) "vlan-protocol", "802.1Q"); test_verify_options_bridge (TRUE, "vlan-protocol", "802.1ad"); + /* multicast-router */ + test_verify_options_bridge (FALSE, + "multicast-router", "nonsense"); + test_verify_options_bridge (FALSE, + "multicast-snooping", "no", + "multicast-router", "auto"); + test_verify_options_bridge (FALSE, + "multicast-snooping", "no", + "multicast-router", "enabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "no", + "multicast-router", "disabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "enabled"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "auto"); + test_verify_options_bridge (TRUE, + "multicast-snooping", "yes", + "multicast-router", "disabled"); } /*****************************************************************************/ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 839272fefe..9231763adf 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1686,6 +1686,7 @@ global: nm_setting_802_1x_get_phase2_domain_match; nm_setting_bond_get_option_normalized; nm_setting_bridge_get_group_address; + nm_setting_bridge_get_multicast_router; nm_setting_bridge_get_vlan_protocol; nm_setting_bridge_get_vlan_stats_enabled; nm_setting_vrf_get_table; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 01ef1c4032..4a310650c7 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -198,6 +198,38 @@ to_sysfs_vlan_protocol (GValue *value) return "0x8100"; } +static const char * +to_sysfs_multicast_router (GValue *value) +{ + const char *str = g_value_get_string (value); + + if (nm_streq0 (str, "disabled")) + return "0"; + if (nm_streq0 (str, "auto")) + return "1"; + if (nm_streq0 (str, "enabled")) + return "2"; + + return "1"; +} + +static void +from_sysfs_multicast_router (const char *value, GValue *out) +{ + switch (_nm_utils_ascii_str_to_uint64 (value, 10, 0, G_MAXUINT, -1)) { + case 0: + g_value_set_string (out, "disabled"); + break; + case 2: + g_value_set_string (out, "enabled"); + break; + case 1: + default: + /* default value */ + break; + } +} + /*****************************************************************************/ typedef struct { @@ -246,6 +278,10 @@ static const Option master_options[] = { NULL, NULL, 0, 1, 1, FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_MULTICAST_ROUTER, "multicast_router", + to_sysfs_multicast_router, from_sysfs_multicast_router, + 0, 0, 0, + FALSE, FALSE, FALSE }, { NM_SETTING_BRIDGE_GROUP_ADDRESS, "group_addr", to_sysfs_group_address, from_sysfs_group_address, 0, 0, 0, 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 51d70c127e..35bd47b6e2 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5158,6 +5158,7 @@ handle_bridge_option (NMSetting *setting, { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_router", NM_SETTING_BRIDGE_MULTICAST_ROUTER, BRIDGE_OPT_TYPE_OPTION }, { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, 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 fe6f2109e6..1bce74fa99 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1508,6 +1508,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "multicast_snooping=%u", (guint32) b); } + s = nm_setting_bridge_get_multicast_router (s_bridge); + if (s) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_router=%s", s); + } + b = nm_setting_bridge_get_vlan_filtering (s_bridge); if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_VLAN_FILTERING)) { if (opts->len) From a685cce70ad89d68430b03e9b47e3eb487c15b49 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Fri, 27 Mar 2020 17:18:06 +0100 Subject: [PATCH 6/7] nm-setting-bridge: add 'multicast-query-use-ifaddr' bridge option https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 3 + clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 83 +++++++++++---- libnm-core/nm-setting-bridge.h | 36 ++++--- libnm/libnm.ver | 1 + src/devices/nm-device-bridge.c | 100 +++++++++--------- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 33 +++--- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 7 ++ 8 files changed, 166 insertions(+), 98 deletions(-) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index aefbfd3cdb..536a1506df 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4899,6 +4899,9 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { .prompt = N_("Group forward mask [0]"), .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, + .property_type = &_pt_gobject_bool, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_SNOOPING, .is_cli_option = TRUE, .property_alias = "multicast-snooping", diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index eb51af3d54..a3e7401282 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -119,6 +119,7 @@ #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR N_("If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_PRIORITY N_("Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are \"better\"; the lowest priority bridge will be elected the root bridge.") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 9bb4303e50..7ee8fe38c7 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -22,15 +22,16 @@ * necessary for bridging connections. **/ -#define BRIDGE_AGEING_TIME_DEFAULT 300 -#define BRIDGE_FORWARD_DELAY_DEFAULT 15 -#define BRIDGE_HELLO_TIME_DEFAULT 2 -#define BRIDGE_MAX_AGE_DEFAULT 20 -#define BRIDGE_MULTICAST_SNOOPING_DEFAULT TRUE -#define BRIDGE_PRIORITY_DEFAULT 0x8000 -#define BRIDGE_STP_DEFAULT TRUE -#define BRIDGE_VLAN_DEFAULT_PVID_DEFAULT 1 -#define BRIDGE_VLAN_STATS_ENABLED_DEFAULT FALSE +#define BRIDGE_AGEING_TIME_DEFAULT 300 +#define BRIDGE_FORWARD_DELAY_DEFAULT 15 +#define BRIDGE_HELLO_TIME_DEFAULT 2 +#define BRIDGE_MAX_AGE_DEFAULT 20 +#define BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT FALSE +#define BRIDGE_MULTICAST_SNOOPING_DEFAULT TRUE +#define BRIDGE_PRIORITY_DEFAULT 0x8000 +#define BRIDGE_STP_DEFAULT TRUE +#define BRIDGE_VLAN_DEFAULT_PVID_DEFAULT 1 +#define BRIDGE_VLAN_STATS_ENABLED_DEFAULT FALSE /*****************************************************************************/ @@ -45,6 +46,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, PROP_MULTICAST_ROUTER, + PROP_MULTICAST_QUERY_USE_IFADDR, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, @@ -70,6 +72,7 @@ typedef struct { bool vlan_filtering:1; bool stp:1; bool vlan_stats_enabled:1; + bool multicast_query_use_ifaddr:1; } NMSettingBridgePrivate; /** @@ -971,6 +974,22 @@ nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting) return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_router; } + +/** + * nm_setting_bridge_get_multicast_query_use_ifaddr: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_query_use_ifaddr; +} /*****************************************************************************/ static gboolean @@ -1202,6 +1221,9 @@ get_property (GObject *object, guint prop_id, case PROP_MULTICAST_ROUTER: g_value_set_string (value, priv->multicast_router); break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + g_value_set_boolean (value, priv->multicast_query_use_ifaddr); + break; case PROP_VLAN_FILTERING: g_value_set_boolean (value, priv->vlan_filtering); break; @@ -1270,6 +1292,9 @@ set_property (GObject *object, guint prop_id, g_free (priv->multicast_router); priv->multicast_router = g_value_dup_string (value); break; + case PROP_MULTICAST_QUERY_USE_IFADDR: + priv->multicast_query_use_ifaddr = g_value_get_boolean (value); + break; case PROP_VLAN_FILTERING: priv->vlan_filtering = g_value_get_boolean (value); break; @@ -1304,15 +1329,16 @@ nm_setting_bridge_init (NMSettingBridge *setting) priv->vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref); - priv->ageing_time = BRIDGE_AGEING_TIME_DEFAULT; - priv->forward_delay = BRIDGE_FORWARD_DELAY_DEFAULT; - priv->hello_time = BRIDGE_HELLO_TIME_DEFAULT; - priv->max_age = BRIDGE_MAX_AGE_DEFAULT; - priv->multicast_snooping = BRIDGE_MULTICAST_SNOOPING_DEFAULT; - priv->priority = BRIDGE_PRIORITY_DEFAULT; - priv->stp = BRIDGE_STP_DEFAULT; - priv->vlan_default_pvid = BRIDGE_VLAN_DEFAULT_PVID_DEFAULT; - priv->vlan_stats_enabled = BRIDGE_VLAN_STATS_ENABLED_DEFAULT; + priv->ageing_time = BRIDGE_AGEING_TIME_DEFAULT; + priv->forward_delay = BRIDGE_FORWARD_DELAY_DEFAULT; + priv->hello_time = BRIDGE_HELLO_TIME_DEFAULT; + priv->max_age = BRIDGE_MAX_AGE_DEFAULT; + priv->multicast_snooping = BRIDGE_MULTICAST_SNOOPING_DEFAULT; + priv->priority = BRIDGE_PRIORITY_DEFAULT; + priv->stp = BRIDGE_STP_DEFAULT; + priv->vlan_default_pvid = BRIDGE_VLAN_DEFAULT_PVID_DEFAULT; + priv->vlan_stats_enabled = BRIDGE_VLAN_STATS_ENABLED_DEFAULT; + priv->multicast_query_use_ifaddr = BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT; } /** @@ -1739,6 +1765,27 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingBridge:multicast-query-use-ifaddr: + * + * If enabled the bridge's own IP address is used as + * the source address for IGMP queries otherwise + * the default of 0.0.0.0 is used. + **/ + /* ---ifcfg-rh--- + * property: multicast-query-use-ifaddr + * variable: BRIDGING_OPTS: multicast_query_use_ifaddr= + * default: 0 + * example: BRIDGING_OPTS="multicast_query-use_ifaddr=1" + * ---end--- + */ + obj_properties[PROP_MULTICAST_QUERY_USE_IFADDR] = + g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, "", "", + BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index a1379693d0..fecd24aa52 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -23,22 +23,23 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_SETTING_NAME "bridge" -#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" -#define NM_SETTING_BRIDGE_STP "stp" -#define NM_SETTING_BRIDGE_PRIORITY "priority" -#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" -#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" -#define NM_SETTING_BRIDGE_MAX_AGE "max-age" -#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" -#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" -#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" -#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" -#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" -#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" -#define NM_SETTING_BRIDGE_VLANS "vlans" -#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" -#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" -#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" +#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address" +#define NM_SETTING_BRIDGE_STP "stp" +#define NM_SETTING_BRIDGE_PRIORITY "priority" +#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay" +#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" +#define NM_SETTING_BRIDGE_MAX_AGE "max-age" +#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" +#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" +#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" +#define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" +#define NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR "multicast-query-use-ifaddr" +#define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" +#define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" +#define NM_SETTING_BRIDGE_VLANS "vlans" +#define NM_SETTING_BRIDGE_GROUP_ADDRESS "group-address" +#define NM_SETTING_BRIDGE_VLAN_PROTOCOL "vlan-protocol" +#define NM_SETTING_BRIDGE_VLAN_STATS_ENABLED "vlan-stats-enabled" #define NM_BRIDGE_VLAN_VID_MIN 1 #define NM_BRIDGE_VLAN_VID_MAX 4094 @@ -132,6 +133,9 @@ gboolean nm_setting_bridge_get_vlan_stats_enabled (const NMSettingBridge *settin NM_AVAILABLE_IN_1_24 const char * nm_setting_bridge_get_multicast_router (const NMSettingBridge *setting); +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 9231763adf..f13dbb6ab3 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1686,6 +1686,7 @@ global: nm_setting_802_1x_get_phase2_domain_match; nm_setting_bond_get_option_normalized; nm_setting_bridge_get_group_address; + nm_setting_bridge_get_multicast_query_use_ifaddr; nm_setting_bridge_get_multicast_router; nm_setting_bridge_get_vlan_protocol; nm_setting_bridge_get_vlan_stats_enabled; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 4a310650c7..12448f4700 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -246,54 +246,58 @@ typedef struct { } Option; static const Option master_options[] = { - { NM_SETTING_BRIDGE_STP, "stp_state", /* this must stay as the first item */ - NULL, NULL, - 0, 1, 1, - FALSE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_PRIORITY, "priority", - NULL, NULL, - 0, G_MAXUINT16, 0x8000, - TRUE, FALSE, TRUE }, - { NM_SETTING_BRIDGE_FORWARD_DELAY, "forward_delay", - NULL, NULL, - 0, NM_BR_MAX_FORWARD_DELAY, 15, - TRUE, TRUE, TRUE}, - { NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", - NULL, NULL, - 0, NM_BR_MAX_HELLO_TIME, 2, - TRUE, TRUE, TRUE }, - { NM_SETTING_BRIDGE_MAX_AGE, "max_age", - NULL, NULL, - 0, NM_BR_MAX_MAX_AGE, 20, - TRUE, TRUE, TRUE }, - { NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", - NULL, NULL, - NM_BR_MIN_AGEING_TIME, NM_BR_MAX_AGEING_TIME, 300, - TRUE, TRUE, FALSE }, - { NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "group_fwd_mask", - NULL, NULL, - 0, 0xFFFF, 0, - TRUE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "multicast_snooping", - NULL, NULL, - 0, 1, 1, - FALSE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_MULTICAST_ROUTER, "multicast_router", - to_sysfs_multicast_router, from_sysfs_multicast_router, - 0, 0, 0, - FALSE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_GROUP_ADDRESS, "group_addr", - to_sysfs_group_address, from_sysfs_group_address, - 0, 0, 0, - FALSE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_VLAN_PROTOCOL, "vlan_protocol", - to_sysfs_vlan_protocol, from_sysfs_vlan_protocol, - 0, 0, 0, - FALSE, FALSE, FALSE }, - { NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "vlan_stats_enabled", - NULL, NULL, - 0, 1, 0, - FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_STP, "stp_state", /* this must stay as the first item */ + NULL, NULL, + 0, 1, 1, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_PRIORITY, "priority", + NULL, NULL, + 0, G_MAXUINT16, 0x8000, + TRUE, FALSE, TRUE }, + { NM_SETTING_BRIDGE_FORWARD_DELAY, "forward_delay", + NULL, NULL, + 0, NM_BR_MAX_FORWARD_DELAY, 15, + TRUE, TRUE, TRUE}, + { NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", + NULL, NULL, + 0, NM_BR_MAX_HELLO_TIME, 2, + TRUE, TRUE, TRUE }, + { NM_SETTING_BRIDGE_MAX_AGE, "max_age", + NULL, NULL, + 0, NM_BR_MAX_MAX_AGE, 20, + TRUE, TRUE, TRUE }, + { NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", + NULL, NULL, + NM_BR_MIN_AGEING_TIME, NM_BR_MAX_AGEING_TIME, 300, + TRUE, TRUE, FALSE }, + { NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "group_fwd_mask", + NULL, NULL, + 0, 0xFFFF, 0, + TRUE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, "multicast_query_use_ifaddr", + NULL, NULL, + 0, 1, 0, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "multicast_snooping", + NULL, NULL, + 0, 1, 1, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_MULTICAST_ROUTER, "multicast_router", + to_sysfs_multicast_router, from_sysfs_multicast_router, + 0, 0, 0, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_GROUP_ADDRESS, "group_addr", + to_sysfs_group_address, from_sysfs_group_address, + 0, 0, 0, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_VLAN_PROTOCOL, "vlan_protocol", + to_sysfs_vlan_protocol, from_sysfs_vlan_protocol, + 0, 0, 0, + FALSE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "vlan_stats_enabled", + NULL, NULL, + 0, 1, 0, + FALSE, FALSE, FALSE }, { NULL, NULL } }; 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 35bd47b6e2..7bc5517802 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5152,22 +5152,23 @@ handle_bridge_option (NMSetting *setting, gboolean only_with_stp; gboolean extended_bool; } m/*etadata*/[] = { - { "DELAY", NM_SETTING_BRIDGE_FORWARD_DELAY, BRIDGE_OPT_TYPE_MAIN, .only_with_stp = TRUE }, - { "priority", NM_SETTING_BRIDGE_PRIORITY, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, - { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, - { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, - { "multicast_router", NM_SETTING_BRIDGE_MULTICAST_ROUTER, BRIDGE_OPT_TYPE_OPTION }, - { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, - { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, - { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, - { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, - { "vlan_protocol", NM_SETTING_BRIDGE_VLAN_PROTOCOL, BRIDGE_OPT_TYPE_OPTION }, - { "vlan_stats_enabled", NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, BRIDGE_OPT_TYPE_OPTION }, - { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, - { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, - { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, + { "DELAY", NM_SETTING_BRIDGE_FORWARD_DELAY, BRIDGE_OPT_TYPE_MAIN, .only_with_stp = TRUE }, + { "priority", NM_SETTING_BRIDGE_PRIORITY, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_query_use_ifaddr", NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_router", NM_SETTING_BRIDGE_MULTICAST_ROUTER, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_filtering", NM_SETTING_BRIDGE_VLAN_FILTERING, BRIDGE_OPT_TYPE_OPTION }, + { "default_pvid", NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, BRIDGE_OPT_TYPE_OPTION }, + { "group_address", NM_SETTING_BRIDGE_GROUP_ADDRESS, BRIDGE_OPT_TYPE_OPTION }, + { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_protocol", NM_SETTING_BRIDGE_VLAN_PROTOCOL, BRIDGE_OPT_TYPE_OPTION }, + { "vlan_stats_enabled", NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, BRIDGE_OPT_TYPE_OPTION }, + { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, }; const char *error_message = NULL; int i; 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 1bce74fa99..504f10f364 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1501,6 +1501,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "group_fwd_mask=%u", i); } + b = nm_setting_bridge_get_multicast_query_use_ifaddr (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_query_use_ifaddr=%u", (guint) b); + } + b = nm_setting_bridge_get_multicast_snooping (s_bridge); if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_SNOOPING)) { if (opts->len) From ad052c3d672f9658c1d4cb47d58ec574a79ac716 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Mon, 30 Mar 2020 13:50:35 +0200 Subject: [PATCH 7/7] nm-setting-bridge: add 'multicast-querier' bridge option https://bugzilla.redhat.com/show_bug.cgi?id=1755768 --- clients/common/nm-meta-setting-desc.c | 3 ++ clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-bridge.c | 47 +++++++++++++++++++ libnm-core/nm-setting-bridge.h | 4 ++ libnm/libnm.ver | 1 + src/devices/nm-device-bridge.c | 4 ++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1 + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 7 +++ 8 files changed, 68 insertions(+) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 536a1506df..03f9b313ce 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4899,6 +4899,9 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { .prompt = N_("Group forward mask [0]"), .property_type = &_pt_gobject_int, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_QUERIER, + .property_type = &_pt_gobject_bool, + ), PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, .property_type = &_pt_gobject_bool, ), diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index a3e7401282..5cbef4285f 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -119,6 +119,7 @@ #define DESCRIBE_DOC_NM_SETTING_BRIDGE_HELLO_TIME N_("The Spanning Tree Protocol (STP) hello time, in seconds.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAC_ADDRESS N_("If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. If this field is left unspecified, the \"ethernet.cloned-mac-address\" is referred instead to generate the initial MAC address. Note that setting \"ethernet.cloned-mac-address\" anyway overwrites the MAC address of the bridge later while activating the bridge. Hence, this property is deprecated. Deprecated: 1") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MAX_AGE N_("The Spanning Tree Protocol (STP) maximum message age, in seconds.") +#define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERIER N_("Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR N_("If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_ROUTER N_("Sets bridge's multicast router. multicast-snooping must be enabled for this option to work. Supported values are: 'auto', 'disabled', 'enabled'. If not specified the default value is 'auto'.") #define DESCRIBE_DOC_NM_SETTING_BRIDGE_MULTICAST_SNOOPING N_("Controls whether IGMP snooping is enabled for this bridge. Note that if snooping was automatically disabled due to hash collisions, the system may refuse to enable the feature until the collisions are resolved.") diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 7ee8fe38c7..d800022168 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -26,6 +26,7 @@ #define BRIDGE_FORWARD_DELAY_DEFAULT 15 #define BRIDGE_HELLO_TIME_DEFAULT 2 #define BRIDGE_MAX_AGE_DEFAULT 20 +#define BRIDGE_MULTICAST_QUERIER_DEFAULT FALSE #define BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT FALSE #define BRIDGE_MULTICAST_SNOOPING_DEFAULT TRUE #define BRIDGE_PRIORITY_DEFAULT 0x8000 @@ -46,6 +47,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingBridge, PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, PROP_MULTICAST_ROUTER, + PROP_MULTICAST_QUERIER, PROP_MULTICAST_QUERY_USE_IFADDR, PROP_MULTICAST_SNOOPING, PROP_VLAN_FILTERING, @@ -73,6 +75,7 @@ typedef struct { bool stp:1; bool vlan_stats_enabled:1; bool multicast_query_use_ifaddr:1; + bool multicast_querier:1; } NMSettingBridgePrivate; /** @@ -990,6 +993,23 @@ nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_query_use_ifaddr; } + +/** + * nm_setting_bridge_get_multicast_querier: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:multicast-querier property of the setting + * + * Since 1.24 + **/ +gboolean +nm_setting_bridge_get_multicast_querier (const NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_querier; +} + /*****************************************************************************/ static gboolean @@ -1221,6 +1241,9 @@ get_property (GObject *object, guint prop_id, case PROP_MULTICAST_ROUTER: g_value_set_string (value, priv->multicast_router); break; + case PROP_MULTICAST_QUERIER: + g_value_set_boolean (value, priv->multicast_querier); + break; case PROP_MULTICAST_QUERY_USE_IFADDR: g_value_set_boolean (value, priv->multicast_query_use_ifaddr); break; @@ -1292,6 +1315,9 @@ set_property (GObject *object, guint prop_id, g_free (priv->multicast_router); priv->multicast_router = g_value_dup_string (value); break; + case PROP_MULTICAST_QUERIER: + priv->multicast_querier = g_value_get_boolean (value); + break; case PROP_MULTICAST_QUERY_USE_IFADDR: priv->multicast_query_use_ifaddr = g_value_get_boolean (value); break; @@ -1339,6 +1365,7 @@ nm_setting_bridge_init (NMSettingBridge *setting) priv->vlan_default_pvid = BRIDGE_VLAN_DEFAULT_PVID_DEFAULT; priv->vlan_stats_enabled = BRIDGE_VLAN_STATS_ENABLED_DEFAULT; priv->multicast_query_use_ifaddr = BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEFAULT; + priv->multicast_querier = BRIDGE_MULTICAST_QUERIER_DEFAULT; } /** @@ -1786,6 +1813,26 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingBridge:multicast-querier: + * + * Enable or disable sending of multicast queries by the bridge. + * If not specified the option is disabled. + **/ + /* ---ifcfg-rh--- + * property: multicast-querier + * variable: BRIDGING_OPTS: multicast_querier= + * default: 0 + * example: BRIDGING_OPTS="multicast_querier=1" + * ---end--- + */ + obj_properties[PROP_MULTICAST_QUERIER] = + g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_QUERIER, "", "", + BRIDGE_MULTICAST_QUERIER_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE, diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index fecd24aa52..6bd5100f26 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -33,6 +33,7 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" #define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" #define NM_SETTING_BRIDGE_MULTICAST_ROUTER "multicast-router" +#define NM_SETTING_BRIDGE_MULTICAST_QUERIER "multicast-querier" #define NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR "multicast-query-use-ifaddr" #define NM_SETTING_BRIDGE_VLAN_FILTERING "vlan-filtering" #define NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID "vlan-default-pvid" @@ -136,6 +137,9 @@ const char * nm_setting_bridge_get_multicast_router (const NMSettingBridge *se NM_AVAILABLE_IN_1_24 gboolean nm_setting_bridge_get_multicast_query_use_ifaddr (const NMSettingBridge *setting); +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_bridge_get_multicast_querier (const NMSettingBridge *setting); + G_END_DECLS #endif /* __NM_SETTING_BRIDGE_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index f13dbb6ab3..b5ce8c34a3 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1686,6 +1686,7 @@ global: nm_setting_802_1x_get_phase2_domain_match; nm_setting_bond_get_option_normalized; nm_setting_bridge_get_group_address; + nm_setting_bridge_get_multicast_querier; nm_setting_bridge_get_multicast_query_use_ifaddr; nm_setting_bridge_get_multicast_router; nm_setting_bridge_get_vlan_protocol; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index 12448f4700..6eb9850e45 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -274,6 +274,10 @@ static const Option master_options[] = { NULL, NULL, 0, 0xFFFF, 0, TRUE, FALSE, FALSE }, + { NM_SETTING_BRIDGE_MULTICAST_QUERIER, "multicast_querier", + NULL, NULL, + 0, 1, 0, + FALSE, FALSE, FALSE }, { NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, "multicast_query_use_ifaddr", NULL, NULL, 0, 1, 0, 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 7bc5517802..8e15341238 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5157,6 +5157,7 @@ handle_bridge_option (NMSetting *setting, { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_querier", NM_SETTING_BRIDGE_MULTICAST_QUERIER, BRIDGE_OPT_TYPE_OPTION }, { "multicast_query_use_ifaddr", NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, BRIDGE_OPT_TYPE_OPTION }, { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, { "multicast_router", NM_SETTING_BRIDGE_MULTICAST_ROUTER, BRIDGE_OPT_TYPE_OPTION }, 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 504f10f364..a0797fdc79 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1501,6 +1501,13 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire g_string_append_printf (opts, "group_fwd_mask=%u", i); } + b = nm_setting_bridge_get_multicast_querier (s_bridge); + if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_QUERIER)) { + if (opts->len) + g_string_append_c (opts, ' '); + g_string_append_printf (opts, "multicast_querier=%u", (guint) b); + } + b = nm_setting_bridge_get_multicast_query_use_ifaddr (s_bridge); if (b != get_setting_default_boolean (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR)) { if (opts->len)