diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index c252832d35..25969cd1f1 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -3672,85 +3672,6 @@ _validate_fcn_team_config (const char *value, char **out_to_free, GError **error RETURN_STR_TO_FREE (json); } -static void -_multilist_clear_all_fcn_team_runner_tx_hash (NMSetting *setting) -{ - /* Workaround libnm bug (confirmed against version 1.16.0). - * We need to both clear the GObject property and call the libnm API. - * - * This workaround was added in nmcli as [1]. This needs fixing in libnm. - * - * Without this, CI test "team_abs_set_runner_tx_hash" fails. - * Try (without the following workaround): */ -#if 0 - $ (nmcli connection delete team0 ; :); \ - nmcli connection add type team con-name team0 ifname team0 autoconnect no \ - team.runner lacp && \ - echo ">>> FIRST:" && \ - PAGER= nmcli -o connection show team0 && \ - nmcli connection modify team0 team.runner-tx-hash l3 && \ - echo ">>> AFTER:" && \ - PAGER= nmcli -o connection show team0 -#endif - /* See also: - * - * - https://github.com/NetworkManager/NetworkManager/pull/318 - * - https://bugzilla.redhat.com/show_bug.cgi?id=1691619 - * - * [1] https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=350dbb55abf3a80267c398e6f64c2cee4645475a - */ - - /* it appears, we don't really need _gobject_property_reset(). Just to be sure - * also call it. */ - _gobject_property_reset (setting, NM_SETTING_TEAM_RUNNER_TX_HASH, FALSE); - while (nm_setting_team_get_num_runner_tx_hash (NM_SETTING_TEAM (setting))) - nm_setting_team_remove_runner_tx_hash (NM_SETTING_TEAM (setting), 0); -} - -static void -_objlist_clear_all_fcn_team_link_watchers (NMSetting *setting) -{ - /* the same workaround as _multilist_clear_all_fcn_team_runner_tx_hash() above. - * - * Reproduce with: */ -#if 0 - $ (nmcli connection delete team0 ; :); \ - nmcli connection add type team con-name team0 ifname team0 autoconnect no \ - team.link-watchers 'name=arp_ping source-host=172.16.1.1 target-host=172.16.1.254, name=ethtool delay-up=3' && \ - echo ">>> FIRST:" && \ - PAGER= nmcli -o connection show team0 && \ - nmcli connection modify team0 team.link-watchers 'name=ethtool delay-up=4' && \ - echo ">>> AFTER:" && \ - PAGER= nmcli -o connection show team0 - - (nmcli connection delete team0-slave ; :); \ - nmcli connection add type ethernet con-name team0-slave master team0 slave-type team ifname eth0 autoconnect no \ - team-port.link-watchers 'name=arp_ping source-host=172.16.1.1 target-host=172.16.1.254, name=ethtool delay-up=3' && \ - echo ">>> FIRST:" && \ - PAGER= nmcli -o connection show team0-slave && \ - nmcli connection modify team0-slave team.link-watchers 'name=ethtool delay-up=4' && \ - echo ">>> AFTER:" && \ - PAGER= nmcli -o connection show team0-slave -#endif - /* See also: - * - * - https://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=72bf38cad6ca6033d0117bf67b0e726001922d8f - * - https://github.com/NetworkManager/NetworkManager/pull/318 - * - https://bugzilla.redhat.com/show_bug.cgi?id=1691619 - */ - - /* In this case, it appears both GObject reset and nm_setting_team*_clear_link_watchers() - * work (on their own). So, we might not need the workaround. - * Just to be sure, as something is not right with libnm here. */ - if (NM_IS_SETTING_TEAM (setting)) { - _gobject_property_reset (setting, NM_SETTING_TEAM_LINK_WATCHERS, FALSE); - nm_setting_team_clear_link_watchers (NM_SETTING_TEAM (setting)); - } else { - _gobject_property_reset (setting, NM_SETTING_TEAM_PORT_LINK_WATCHERS, FALSE); - nm_setting_team_port_clear_link_watchers (NM_SETTING_TEAM_PORT (setting)); - } -} - static void _objlist_obj_to_str_fcn_team_link_watchers (NMMetaAccessorGetType get_type, NMSetting *setting, @@ -6513,6 +6434,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "disabled", @@ -6524,6 +6449,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "default", @@ -6535,6 +6464,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "disabled", @@ -6546,6 +6479,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "default", @@ -6577,7 +6514,6 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( PROPERTY_TYP_DATA_SUBTYPE (multilist, .get_num_fcn_u = MULTILIST_GET_NUM_FCN_U (NMSettingTeam, nm_setting_team_get_num_runner_tx_hash), - .clear_all_fcn = _multilist_clear_all_fcn_team_runner_tx_hash, .add_fcn = MULTILIST_ADD_FCN (NMSettingTeam, nm_setting_team_add_runner_tx_hash), .remove_by_idx_fcn_u = MULTILIST_REMOVE_BY_IDX_FCN_U (NMSettingTeam, nm_setting_team_remove_runner_tx_hash), .remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingTeam, nm_setting_team_remove_runner_tx_hash_by_value), @@ -6597,6 +6533,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, .nick = "default", @@ -6614,6 +6554,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT, .nick = "default", @@ -6625,6 +6569,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "default", @@ -6648,7 +6596,6 @@ static const NMMetaPropertyInfo *const property_infos_TEAM[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( PROPERTY_TYP_DATA_SUBTYPE (objlist, .get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingTeam, nm_setting_team_get_num_link_watchers), - .clear_all_fcn = _objlist_clear_all_fcn_team_link_watchers, .obj_to_str_fcn = _objlist_obj_to_str_fcn_team_link_watchers, .set_fcn = _objlist_set_fcn_team_link_watchers, .remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingTeam, nm_setting_team_remove_link_watcher), @@ -6676,7 +6623,11 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( { - .value.i64 = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT, + .value.i64 = -1, + .nick = "unset", + }, + { + .value.i64 = 0, .nick = "default", }, ), @@ -6686,6 +6637,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = 0, + .nick = "unset", + }, { .value.i64 = 0, .nick = "default", @@ -6700,6 +6655,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT, .nick = "default", @@ -6711,6 +6670,10 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { .property_type = &_pt_gobject_int, .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, .value_infos = INT_VALUE_INFOS ( + { + .value.i64 = -1, + .nick = "unset", + }, { .value.i64 = 0, .nick = "default", @@ -6724,7 +6687,6 @@ static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( PROPERTY_TYP_DATA_SUBTYPE (objlist, .get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingTeamPort, nm_setting_team_port_get_num_link_watchers), - .clear_all_fcn = _objlist_clear_all_fcn_team_link_watchers, .obj_to_str_fcn = _objlist_obj_to_str_fcn_team_link_watchers, .set_fcn = _objlist_set_fcn_team_link_watchers, .remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingTeamPort, nm_setting_team_port_remove_link_watcher), diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index 22cbdb6703..c0d78a7044 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -54,6 +54,14 @@ G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING) /*****************************************************************************/ +NMTeamSetting * +_nm_setting_team_port_get_team_setting (NMSettingTeamPort *setting) +{ + return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->team_setting; +} + +/*****************************************************************************/ + #define _maybe_changed(self, changed) \ nm_team_setting_maybe_changed (NM_SETTING (_NM_ENSURE_TYPE (NMSettingTeamPort *, self)), (const GParamSpec *const*) obj_properties, (changed)) @@ -289,19 +297,6 @@ nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting) 0)); } -static GVariant * -team_link_watchers_to_dbus (const GValue *prop_value) -{ - return _nm_utils_team_link_watchers_to_variant (g_value_get_boxed (prop_value)); -} - -static void -team_link_watchers_from_dbus (GVariant *dbus_value, - GValue *prop_value) -{ - g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value, FALSE, NULL)); -} - static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { @@ -556,6 +551,13 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) setting_class->duplicate_copy_properties = duplicate_copy_properties; setting_class->init_from_dbus = init_from_dbus; +#define _property_override(_properties_override, _param_spec, _variant_type, _is_link_watcher) \ + _properties_override_add ((_properties_override), \ + .param_spec = (_param_spec), \ + .dbus_type = G_VARIANT_TYPE (""_variant_type""), \ + .to_dbus_fcn = _nm_team_settings_property_to_dbus, \ + .gprop_from_dbus_fcn = ((_is_link_watcher) ? _nm_team_settings_property_from_dbus_link_watchers : NULL)) + /** * NMSettingTeamPort:config: * @@ -576,6 +578,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], "s", FALSE); /** * NMSettingTeamPort:queue-id: @@ -587,9 +590,10 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID] = g_param_spec_int (NM_SETTING_TEAM_PORT_QUEUE_ID, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID], "i", FALSE); /** * NMSettingTeamPort:prio: @@ -603,6 +607,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) G_MININT32, G_MAXINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_PORT_PRIO], "i", FALSE); /** * NMSettingTeamPort:sticky: @@ -616,6 +621,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_PORT_STICKY], "b", FALSE); /** * NMSettingTeamPort:lacp-prio: @@ -626,9 +632,10 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO] = g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_PRIO, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO], "i", FALSE); /** * NMSettingTeamPort:lacp-key: @@ -639,9 +646,10 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY] = g_param_spec_int (NM_SETTING_TEAM_PORT_LACP_KEY, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_PORT_LACP_KEY], "i", FALSE); /** * NMSettingTeamPort:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) @@ -662,12 +670,7 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - _properties_override_add_transform (properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], "aa{sv}", TRUE); g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_properties), obj_properties); diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index a478b802b1..3e057c5451 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -734,6 +734,14 @@ G_DEFINE_TYPE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING) /*****************************************************************************/ +NMTeamSetting * +_nm_setting_team_get_team_setting (NMSettingTeam *setting) +{ + return NM_SETTING_TEAM_GET_PRIVATE (setting)->team_setting; +} + +/*****************************************************************************/ + #define _maybe_changed(self, changed) \ nm_team_setting_maybe_changed (NM_SETTING (_NM_ENSURE_TYPE (NMSettingTeam *, self)), (const GParamSpec *const*) obj_properties, (changed)) @@ -1223,19 +1231,6 @@ nm_setting_team_clear_link_watchers (NMSettingTeam *setting) 0)); } -static GVariant * -team_link_watchers_to_dbus (const GValue *prop_value) -{ - return _nm_utils_team_link_watchers_to_variant (g_value_get_boxed (prop_value)); -} - -static void -team_link_watchers_from_dbus (GVariant *dbus_value, - GValue *prop_value) -{ - g_value_take_boxed (prop_value, _nm_utils_team_link_watchers_from_variant (dbus_value, FALSE, NULL)); -} - static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { @@ -1503,6 +1498,13 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) setting_class->duplicate_copy_properties = duplicate_copy_properties; setting_class->init_from_dbus = init_from_dbus; +#define _property_override(_properties_override, _param_spec, _variant_type, _is_link_watcher) \ + _properties_override_add ((_properties_override), \ + .param_spec = (_param_spec), \ + .dbus_type = G_VARIANT_TYPE (""_variant_type""), \ + .to_dbus_fcn = _nm_team_settings_property_to_dbus, \ + .gprop_from_dbus_fcn = ((_is_link_watcher) ? _nm_team_settings_property_from_dbus_link_watchers : NULL)) + /** * NMSettingTeam:config: * @@ -1523,6 +1525,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_CONFIG], "s", FALSE); /** * NMSettingTeam:notify-peers-count: @@ -1533,9 +1536,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT] = g_param_spec_int (NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT], "i", FALSE); /** * NMSettingTeam:notify-peers-interval: @@ -1546,9 +1550,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL] = g_param_spec_int (NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL], "i", FALSE); /** * NMSettingTeam:mcast-rejoin-count: @@ -1559,9 +1564,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT] = g_param_spec_int (NM_SETTING_TEAM_MCAST_REJOIN_COUNT, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT], "i", FALSE); /** * NMSettingTeam:mcast-rejoin-interval: @@ -1572,9 +1578,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL] = g_param_spec_int (NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL], "i", FALSE); /** * NMSettingTeam:runner: @@ -1590,6 +1597,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER], "s", FALSE); /** * NMSettingTeam:runner-hwaddr-policy: @@ -1603,6 +1611,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY], "s", FALSE); /** * NMSettingTeam:runner-tx-hash: @@ -1617,6 +1626,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH], "as", FALSE); /** * NMSettingTeam:runner-tx-balancer: @@ -1630,6 +1640,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER], "s", FALSE); /** * NMSettingTeam:runner-tx-balancer-interval: @@ -1640,9 +1651,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL] = g_param_spec_int (NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL], "i", FALSE); /** * NMSettingTeam:runner-active: @@ -1653,9 +1665,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE] = g_param_spec_boolean (NM_SETTING_TEAM_RUNNER_ACTIVE, "", "", - FALSE, + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE], "b", FALSE); /** * NMSettingTeam:runner-fast-rate: @@ -1669,6 +1682,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE], "b", FALSE); /** * NMSettingTeam:runner-sys-prio: @@ -1679,9 +1693,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO] = g_param_spec_int (NM_SETTING_TEAM_RUNNER_SYS_PRIO, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO], "i", FALSE); /** * NMSettingTeam:runner-min-ports: @@ -1692,9 +1707,10 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) **/ obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS] = g_param_spec_int (NM_SETTING_TEAM_RUNNER_MIN_PORTS, "", "", - G_MININT32, G_MAXINT32, 0, + G_MININT32, G_MAXINT32, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS], "i", FALSE); /** * NMSettingTeam:runner-agg-select-policy: @@ -1708,6 +1724,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY], "s", FALSE); /** * NMSettingTeam:link-watchers: (type GPtrArray(NMTeamLinkWatcher)) @@ -1728,12 +1745,7 @@ nm_setting_team_class_init (NMSettingTeamClass *klass) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - _properties_override_add_transform (properties_override, - obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - G_VARIANT_TYPE ("aa{sv}"), - team_link_watchers_to_dbus, - team_link_watchers_from_dbus); + _property_override (properties_override, obj_properties[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], "aa{sv}", TRUE); /* ---dbus--- * property: interface-name diff --git a/libnm-core/nm-team-utils.c b/libnm-core/nm-team-utils.c index 814fd5369a..7346c1d03e 100644 --- a/libnm-core/nm-team-utils.c +++ b/libnm-core/nm-team-utils.c @@ -33,21 +33,115 @@ /*****************************************************************************/ +typedef enum { + SET_FIELD_MODE_UNSET = 0, + SET_FIELD_MODE_SET = 1, + + /* Sets the field as set, unless the field is at the default. + * This is the case for API that is called from NMSettingTeam/NMSettingTeamPort. + * This means, using libnm API to reset the value of a NMSetting to the default, + * will mark the field as unset. + * This is different from initializing the field when parsing JSON/GVariant. In + * that case an explicitly set field (even set to the default value) will be remembered + * to be set. */ + SET_FIELD_MODE_SET_UNLESS_DEFAULT = 2, +} SetFieldModeEnum; + +typedef enum { + RESET_JSON_NO = FALSE, + RESET_JSON_YES = TRUE, +} ResetJsonEnum; + /* we rely on "config" being the first. At various places we iterate over attribute types, * starting after "config".*/ G_STATIC_ASSERT (_NM_TEAM_ATTRIBUTE_0 == 0); G_STATIC_ASSERT (NM_TEAM_ATTRIBUTE_CONFIG == 1); +static const char *const _valid_names_runner[] = { + NM_SETTING_TEAM_RUNNER_BROADCAST, + NM_SETTING_TEAM_RUNNER_ROUNDROBIN, + NM_SETTING_TEAM_RUNNER_RANDOM, + NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, + NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP, + NULL, +}; + +static const char *const _valid_names_runner_hwaddr_policy[] = { + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_SAME_ALL, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_BY_ACTIVE, + NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_ONLY_ACTIVE, + NULL, +}; + +static const char *const _valid_names_runner_tx_balancer[] = { + "basic", + NULL, +}; + +static const char *const _valid_names_runner_tx_hash[] = { + "eth", + "vlan", + "ipv4", + "ipv6", + "ip", + "l3", + "l4", + "tcp", + "udp", + "sctp", + NULL, +}; + +static const char *const _valid_names_runner_agg_select_policy[] = { + "lacp_prio", + "lacp_prio_stable", + "bandwidth", + "count", + "port_config", + NULL, +}; + +typedef struct { + NMTeamAttribute team_attr; + const char *const*valid_runners; +} RunnerCompatElem; + +static const RunnerCompatElem _runner_compat_lst[] = { + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LOADBALANCE, + NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LACP), }, + { NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, NM_MAKE_STRV (NM_SETTING_TEAM_RUNNER_LACP), }, +}; + typedef struct { const char *const*js_keys; - const char *dbus_name; + const char *property_name; NMValueTypUnion default_val; + union { + struct { + gint32 min; + gint32 max; + } r_int32; + struct { + const char *const*valid_names; + } r_string; + } range; NMTeamAttribute team_attr; NMValueType value_type; guint8 field_offset; guint8 js_keys_len; bool for_master:1; bool for_port:1; + bool has_range:1; } TeamAttrData; #define TEAM_ATTR_IDX(_is_port, _team_attr) \ @@ -63,60 +157,81 @@ static const TeamAttrData team_attr_datas[] = { .js_keys = NM_MAKE_STRV (__VA_ARGS__), \ .js_keys_len = NM_NARG (__VA_ARGS__) -#define _INIT(_is_port, _team_attr, field, _value_type, _dbus_name, ...) \ +#define _VAL_BOOL(_default) \ + .default_val.v_bool = (_default) + +#define _VAL_INT32(_default) \ + .default_val.v_int32 = (_default) + +#define _VAL_INT32_RANGE(_default, _min,_max) \ + _VAL_INT32 (_default), \ + .has_range = TRUE, \ + .range.r_int32 = { .min = _min, .max = _max, } + +#define _VAL_STRING() \ + .default_val.v_string = NULL + +#define _VAL_STRING_RANGE(_valid_names) \ + _VAL_STRING (), \ + .has_range = TRUE, \ + .range.r_string = { .valid_names = (_valid_names), } + +#define _VAL_UNSPEC() \ + .default_val.v_string = (NULL) + +#define _INIT(_is_port, _team_attr, field, _value_type, _property_name, ...) \ [TEAM_ATTR_IDX (_is_port, _team_attr)] = { \ .for_master = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || !(_is_port), \ .for_port = (_team_attr) < _NM_TEAM_ATTRIBUTE_START || (_is_port), \ .team_attr = (_team_attr), \ .field_offset = G_STRUCT_OFFSET (NMTeamSetting, _data_priv.field), \ .value_type = (_value_type), \ - .dbus_name = ""_dbus_name"", \ + .property_name = ""_property_name"", \ __VA_ARGS__ \ } - _INIT (0, NM_TEAM_ATTRIBUTE_CONFIG, _js_str, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_CONFIG, ), + _INIT (0, NM_TEAM_ATTRIBUTE_CONFIG, _js_str, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_CONFIG, ), - _INIT (0, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, link_watchers, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_LINK_WATCHERS, _JS_KEYS ("link_watch"), ), + _INIT (0, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, link_watchers, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_LINK_WATCHERS, _JS_KEYS ("link_watch"), _VAL_UNSPEC (), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, master.notify_peers_count, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, _JS_KEYS ("notify_peers", "count"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, master.notify_peers_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, _JS_KEYS ("notify_peers", "interval"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, master.mcast_rejoin_count, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_MCAST_REJOIN_COUNT, _JS_KEYS ("mcast_rejoin", "count"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, master.mcast_rejoin_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, _JS_KEYS ("mcast_rejoin", "interval"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER, master.runner, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER, _JS_KEYS ("runner", "name"), .default_val.v_string = NM_SETTING_TEAM_RUNNER_DEFAULT, ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, master.runner_hwaddr_policy, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, _JS_KEYS ("runner", "hwaddr_policy"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, master.runner_tx_hash, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_RUNNER_TX_HASH, _JS_KEYS ("runner", "tx_hash"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, master.runner_tx_balancer, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_TX_BALANCER, _JS_KEYS ("runner", "tx_balancer", "name"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, master.runner_tx_balancer_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, _JS_KEYS ("runner", "tx_balancer", "balancing_interval"), .default_val.v_int32 = -1 ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, master.runner_active, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_RUNNER_ACTIVE, _JS_KEYS ("runner", "active"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, master.runner_fast_rate, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_RUNNER_FAST_RATE, _JS_KEYS ("runner", "fast_rate"), ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, master.runner_sys_prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_SYS_PRIO, _JS_KEYS ("runner", "sys_prio"), .default_val.v_int32 = -1, ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, master.runner_min_ports, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_MIN_PORTS, _JS_KEYS ("runner", "min_ports"), .default_val.v_int32 = -1, ), - _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, master.runner_agg_select_policy, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, _JS_KEYS ("runner", "agg_select_policy"), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, master.notify_peers_count, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_NOTIFY_PEERS_COUNT, _JS_KEYS ("notify_peers", "count"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, master.notify_peers_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_NOTIFY_PEERS_INTERVAL, _JS_KEYS ("notify_peers", "interval"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, master.mcast_rejoin_count, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_MCAST_REJOIN_COUNT, _JS_KEYS ("mcast_rejoin", "count"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, master.mcast_rejoin_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_MCAST_REJOIN_INTERVAL, _JS_KEYS ("mcast_rejoin", "interval"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER, master.runner, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER, _JS_KEYS ("runner", "name"), _VAL_STRING_RANGE (_valid_names_runner), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, master.runner_hwaddr_policy, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_HWADDR_POLICY, _JS_KEYS ("runner", "hwaddr_policy"), _VAL_STRING_RANGE (_valid_names_runner_hwaddr_policy), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, master.runner_tx_hash, NM_VALUE_TYPE_UNSPEC, NM_SETTING_TEAM_RUNNER_TX_HASH, _JS_KEYS ("runner", "tx_hash"), _VAL_UNSPEC (), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, master.runner_tx_balancer, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_TX_BALANCER, _JS_KEYS ("runner", "tx_balancer", "name"), _VAL_STRING_RANGE (_valid_names_runner_tx_balancer), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, master.runner_tx_balancer_interval, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL, _JS_KEYS ("runner", "tx_balancer", "balancing_interval"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, master.runner_active, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_RUNNER_ACTIVE, _JS_KEYS ("runner", "active"), _VAL_BOOL (TRUE), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, master.runner_fast_rate, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_RUNNER_FAST_RATE, _JS_KEYS ("runner", "fast_rate"), _VAL_BOOL (FALSE), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, master.runner_sys_prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_SYS_PRIO, _JS_KEYS ("runner", "sys_prio"), _VAL_INT32_RANGE (-1, 0, USHRT_MAX + 1), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, master.runner_min_ports, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_RUNNER_MIN_PORTS, _JS_KEYS ("runner", "min_ports"), _VAL_INT32_RANGE (-1, 1, UCHAR_MAX + 1), ), + _INIT (0, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, master.runner_agg_select_policy, NM_VALUE_TYPE_STRING, NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY, _JS_KEYS ("runner", "agg_select_policy"), _VAL_STRING_RANGE (_valid_names_runner_agg_select_policy), ), - _INIT (1, NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, port.queue_id, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_QUEUE_ID, _JS_KEYS ("queue_id"), .default_val.v_int32 = NM_SETTING_TEAM_PORT_QUEUE_ID_DEFAULT, ), - _INIT (1, NM_TEAM_ATTRIBUTE_PORT_PRIO, port.prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_PRIO, _JS_KEYS ("prio"), ), - _INIT (1, NM_TEAM_ATTRIBUTE_PORT_STICKY, port.sticky, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_PORT_STICKY, _JS_KEYS ("sticky"), ), - _INIT (1, NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, port.lacp_prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_LACP_PRIO, _JS_KEYS ("lacp_prio"), .default_val.v_int32 = NM_SETTING_TEAM_PORT_LACP_PRIO_DEFAULT, ), - _INIT (1, NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, port.lacp_key, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_LACP_KEY, _JS_KEYS ("lacp_key"), ), + _INIT (1, NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, port.queue_id, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_QUEUE_ID, _JS_KEYS ("queue_id"), _VAL_INT32_RANGE (-1, 0, G_MAXINT32), ), + _INIT (1, NM_TEAM_ATTRIBUTE_PORT_PRIO, port.prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_PRIO, _JS_KEYS ("prio"), _VAL_INT32 (0), ), + _INIT (1, NM_TEAM_ATTRIBUTE_PORT_STICKY, port.sticky, NM_VALUE_TYPE_BOOL, NM_SETTING_TEAM_PORT_STICKY, _JS_KEYS ("sticky"), _VAL_BOOL (FALSE), ), + _INIT (1, NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, port.lacp_prio, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_LACP_PRIO, _JS_KEYS ("lacp_prio"), _VAL_INT32_RANGE (-1, 0, USHRT_MAX + 1), ), + _INIT (1, NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, port.lacp_key, NM_VALUE_TYPE_INT32, NM_SETTING_TEAM_PORT_LACP_KEY, _JS_KEYS ("lacp_key"), _VAL_INT32_RANGE (-1, 0, USHRT_MAX + 1), ), #undef _INIT - }; /*****************************************************************************/ typedef enum { LINK_WATCHER_ATTRIBUTE_NAME, - LINK_WATCHER_ATTRIBUTE_TARGET_HOST, - LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, LINK_WATCHER_ATTRIBUTE_DELAY_UP, LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_INTERVAL, + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, LINK_WATCHER_ATTRIBUTE_MISSED_MAX, - LINK_WATCHER_ATTRIBUTE_VLANID, + LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, + LINK_WATCHER_ATTRIBUTE_TARGET_HOST, LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, + LINK_WATCHER_ATTRIBUTE_VLANID, LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, } LinkWatcherAttribute; @@ -124,19 +239,19 @@ typedef enum { LINK_WATCHER_ATTRIBUTE_DELAY_UP, \ LINK_WATCHER_ATTRIBUTE_DELAY_DOWN #define _EXPECTED_LINK_WATCHER_ATTRIBUTES_NSNA_PING LINK_WATCHER_ATTRIBUTE_NAME, \ - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, \ LINK_WATCHER_ATTRIBUTE_INTERVAL, \ + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, \ LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ LINK_WATCHER_ATTRIBUTE_TARGET_HOST #define _EXPECTED_LINK_WATCHER_ATTRIBUTES_ARP_PING LINK_WATCHER_ATTRIBUTE_NAME, \ - LINK_WATCHER_ATTRIBUTE_INIT_WAIT, \ LINK_WATCHER_ATTRIBUTE_INTERVAL, \ + LINK_WATCHER_ATTRIBUTE_INIT_WAIT, \ LINK_WATCHER_ATTRIBUTE_MISSED_MAX, \ - LINK_WATCHER_ATTRIBUTE_VLANID, \ - LINK_WATCHER_ATTRIBUTE_TARGET_HOST, \ LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, \ + LINK_WATCHER_ATTRIBUTE_TARGET_HOST, \ LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, \ LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, \ + LINK_WATCHER_ATTRIBUTE_VLANID, \ LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS typedef struct { @@ -157,16 +272,16 @@ static const LinkWatcherAttrData link_watcher_attr_datas[] = { __VA_ARGS__ \ } _INIT (LINK_WATCHER_ATTRIBUTE_NAME, "name", "name", NM_VALUE_TYPE_STRING, ), - _INIT (LINK_WATCHER_ATTRIBUTE_TARGET_HOST, "target_host", "target-host", NM_VALUE_TYPE_STRING, ), - _INIT (LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, "source_host", "source-host", NM_VALUE_TYPE_STRING, ), _INIT (LINK_WATCHER_ATTRIBUTE_DELAY_UP, "delay_up", "delay-up", NM_VALUE_TYPE_INT, ), _INIT (LINK_WATCHER_ATTRIBUTE_DELAY_DOWN, "delay_down", "delay-down", NM_VALUE_TYPE_INT, ), - _INIT (LINK_WATCHER_ATTRIBUTE_INIT_WAIT, "init_wait", "init-wait", NM_VALUE_TYPE_INT, ), _INIT (LINK_WATCHER_ATTRIBUTE_INTERVAL, "interval", "interval", NM_VALUE_TYPE_INT, ), + _INIT (LINK_WATCHER_ATTRIBUTE_INIT_WAIT, "init_wait", "init-wait", NM_VALUE_TYPE_INT, ), _INIT (LINK_WATCHER_ATTRIBUTE_MISSED_MAX, "missed_max", "missed-max", NM_VALUE_TYPE_INT, .default_val.v_int = 3, ), - _INIT (LINK_WATCHER_ATTRIBUTE_VLANID, "vlanid", "vlanid", NM_VALUE_TYPE_INT, .default_val.v_int = -1, ), + _INIT (LINK_WATCHER_ATTRIBUTE_SOURCE_HOST, "source_host", "source-host", NM_VALUE_TYPE_STRING, ), + _INIT (LINK_WATCHER_ATTRIBUTE_TARGET_HOST, "target_host", "target-host", NM_VALUE_TYPE_STRING, ), _INIT (LINK_WATCHER_ATTRIBUTE_VALIDATE_ACTIVE, "validate_active", "validate-active", NM_VALUE_TYPE_BOOL, ), _INIT (LINK_WATCHER_ATTRIBUTE_VALIDATE_INACTIVE, "validate_inactive", "validate-inactive", NM_VALUE_TYPE_BOOL, ), + _INIT (LINK_WATCHER_ATTRIBUTE_VLANID, "vlanid", "vlanid", NM_VALUE_TYPE_INT, .default_val.v_int = -1, ), _INIT (LINK_WATCHER_ATTRIBUTE_SEND_ALWAYS, "send_always", "send-always", NM_VALUE_TYPE_BOOL, ), #undef _INIT }; @@ -177,8 +292,6 @@ static const TeamAttrData *_team_attr_data_get (gboolean is_port, NMTeamAttribute team_attr); static gpointer _team_setting_get_field (const NMTeamSetting *self, const TeamAttrData *attr_data); -static gboolean _team_setting_verify (const NMTeamSetting *self, - GError **error); static void _link_watcher_to_json (const NMTeamLinkWatcher *link_watcher, GString *gstr); @@ -197,7 +310,7 @@ _team_attr_data_ASSERT (const TeamAttrData *attr_data) nm_assert (attr_data->value_type > 0); nm_assert (attr_data->field_offset < sizeof (NMTeamSetting)); nm_assert (attr_data->js_keys_len == NM_PTRARRAY_LEN (attr_data->js_keys)); - nm_assert (attr_data->dbus_name); + nm_assert (attr_data->property_name); { static int checked = 0; @@ -235,124 +348,19 @@ _team_attr_data_get (gboolean is_port, } static const TeamAttrData * -_team_attr_data_find_for_dbus_name (gboolean is_port, - const char *dbus_name) +_team_attr_data_find_for_property_name (gboolean is_port, + const char *property_name) { const TeamAttrData *attr_data; for (attr_data = team_attr_datas; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { if ( _team_attr_data_is_relevant (attr_data, is_port) - && nm_streq (dbus_name, attr_data->dbus_name)) + && nm_streq (property_name, attr_data->property_name)) return attr_data; } return NULL; } -static const NMValueTypUnion * -_team_attr_data_get_default (const TeamAttrData *attr_data, - gboolean is_port, - const char *v_master_runner, - NMValueTypUnion *value_tmp) -{ - GPtrArray *v_ptrarray; - - /* unfortunately, the default certain values depends on other values :( - * - * For examle, master attributes depend on the "runner" setting. - * and port settings default to the ethtool link-watcher. */ - - if (is_port) { - - switch (attr_data->team_attr) { - case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: { - static GPtrArray *volatile gl_arr = NULL; - -again_port_link_watchers: - v_ptrarray = g_atomic_pointer_get (&gl_arr); - if (G_UNLIKELY (!v_ptrarray)) { - v_ptrarray = g_ptr_array_new_full (1, (GDestroyNotify) nm_team_link_watcher_unref); - g_ptr_array_add (v_ptrarray, nm_team_link_watcher_new_ethtool (0, 0, NULL)); - if (!g_atomic_pointer_compare_and_exchange (&gl_arr, NULL, v_ptrarray)) { - g_ptr_array_unref (v_ptrarray); - goto again_port_link_watchers; - } - } - return NM_VALUE_TYP_UNION_SET (value_tmp, v_ptrarray, v_ptrarray); - } - default: - break; - } - - } else { - - if (NM_IN_STRSET (v_master_runner, NULL, - NM_SETTING_TEAM_RUNNER_DEFAULT)) { - /* a runner %NULL is the same as NM_SETTING_TEAM_RUNNER_DEFAULT ("roundrobin"). - * In this case, the settings in attr_data are accurate. */ - return &attr_data->default_val; - } - - switch (attr_data->team_attr) { - case NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_int32, NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT); - break; - case NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_int32, NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_string, "same_all"); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: - if (NM_IN_STRSET (v_master_runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NM_SETTING_TEAM_RUNNER_LACP)) { - static GPtrArray *volatile gl_arr = NULL; - -again_master_runner_tx_hash: - v_ptrarray = g_atomic_pointer_get (&gl_arr); - if (G_UNLIKELY (!v_ptrarray)) { - v_ptrarray = g_ptr_array_sized_new (3); - g_ptr_array_add (v_ptrarray, "eth"); - g_ptr_array_add (v_ptrarray, "ipv4"); - g_ptr_array_add (v_ptrarray, "ipv6"); - if (!g_atomic_pointer_compare_and_exchange (&gl_arr, NULL, v_ptrarray)) { - g_ptr_array_unref (v_ptrarray); - goto again_master_runner_tx_hash; - } - } - return NM_VALUE_TYP_UNION_SET (value_tmp, v_ptrarray, v_ptrarray); - } - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL: - if (NM_IN_STRSET (v_master_runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE, - NM_SETTING_TEAM_RUNNER_LACP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_int32, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_LACP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_bool, TRUE); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_LACP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_int32, NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_LACP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_int32, 0); - break; - case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY: - if (nm_streq (v_master_runner, NM_SETTING_TEAM_RUNNER_LACP)) - return NM_VALUE_TYP_UNION_SET (value_tmp, v_string, NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT); - break; - default: - break; - } - } - - return &attr_data->default_val; -} static int _team_attr_data_cmp (const TeamAttrData *attr_data, gboolean is_port, @@ -455,44 +463,6 @@ _team_attr_data_copy (const TeamAttrData *attr_data, nm_assert_not_reached (); } -static gboolean -_team_attr_data_is_default (const TeamAttrData *attr_data, - gboolean is_port, - const char *v_master_runner, - gconstpointer p_field) -{ - const NMValueTypUnion *default_value; - NMValueTypUnion value_tmp; - - _team_attr_data_ASSERT (attr_data); - nm_assert (p_field); - - default_value = _team_attr_data_get_default (attr_data, - is_port, - v_master_runner, - &value_tmp); - if (_team_attr_data_equal (attr_data, - is_port, - default_value, - p_field)) - return TRUE; - - if ( attr_data->value_type == NM_VALUE_TYPE_STRING - && default_value->v_string) { - const char *str0 = NULL; - - /* this is a string value, whose default is not NULL. In such a case, - * NULL is also treated like the default. */ - if (_team_attr_data_equal (attr_data, - is_port, - &str0, - p_field)) - return TRUE; - } - - return FALSE; -} - static void _team_attr_data_to_json (const TeamAttrData *attr_data, gboolean is_port, @@ -574,6 +544,64 @@ _team_setting_ASSERT (const NMTeamSetting *self) #endif } +static gboolean +_team_setting_has_field (const NMTeamSetting *self, + const TeamAttrData *attr_data) +{ + _team_setting_ASSERT (self); + return NM_FLAGS_ALL (self->d.has_fields_mask, nm_team_attribute_to_flags (attr_data->team_attr)); +} + +static gboolean +_team_setting_has_fields_any_v (const NMTeamSetting *self, + const NMTeamAttribute *team_attrs, + gsize n_team_attrs) +{ + gsize i; + + for (i = 0; i < n_team_attrs; i++) { + const TeamAttrData *attr_data = _team_attr_data_get (self->d.is_port, team_attrs[i]); + + if (_team_setting_has_field (self, attr_data)) + return TRUE; + } + return FALSE; +} + +#define _team_setting_has_fields_any(self, ...) \ + _team_setting_has_fields_any_v ((self), ((const NMTeamAttribute []) { __VA_ARGS__ }), NM_NARG (__VA_ARGS__)) + +static void +_team_setting_has_field_set (NMTeamSetting *self, + const TeamAttrData *attr_data, + SetFieldModeEnum set_field_mode) +{ + guint32 mask = nm_team_attribute_to_flags (attr_data->team_attr); + + _team_setting_ASSERT (self); + + switch (set_field_mode) { + case SET_FIELD_MODE_UNSET: + goto do_unset; + case SET_FIELD_MODE_SET: + goto do_set; + case SET_FIELD_MODE_SET_UNLESS_DEFAULT: + if (_team_attr_data_equal (attr_data, + self->d.is_port, + _team_setting_get_field (self, attr_data), + &attr_data->default_val)) + goto do_unset; + goto do_set; + } + nm_assert_not_reached (); + +do_unset: + self->_data_priv.has_fields_mask &= ~mask; + return; +do_set: + self->_data_priv.has_fields_mask |= mask; +} + static gpointer _team_setting_get_field (const NMTeamSetting *self, const TeamAttrData *attr_data) @@ -593,12 +621,20 @@ _team_setting_get_field (const NMTeamSetting *self, static guint32 _team_setting_attribute_changed (NMTeamSetting *self, - NMTeamAttribute team_attr, - gboolean changed) + const TeamAttrData *attr_data, + gboolean changed, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) { guint32 changed_flags; - nm_assert (_team_attr_data_get (self->d.is_port, team_attr)); + _team_setting_has_field_set (self, attr_data, set_field_mode); + + if (!reset_json) { + return changed + ? nm_team_attribute_to_flags (attr_data->team_attr) + : 0u; + } if (!changed) { /* a regular attribute was set, but the value did not change. @@ -614,7 +650,7 @@ _team_setting_attribute_changed (NMTeamSetting *self, return 0; changed_flags = nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); } else { - changed_flags = nm_team_attribute_to_flags (team_attr) + changed_flags = nm_team_attribute_to_flags (attr_data->team_attr) | nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); } @@ -625,13 +661,28 @@ _team_setting_attribute_changed (NMTeamSetting *self, return changed_flags; } -static void +static guint32 +_team_setting_attribute_changed_attr (NMTeamSetting *self, + NMTeamAttribute team_attr, + gboolean changed, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + return _team_setting_attribute_changed (self, + _team_attr_data_get (self->d.is_port, team_attr), + changed, + set_field_mode, + reset_json); +} + +static gboolean _team_setting_field_to_json (const NMTeamSetting *self, GString *gstr, gboolean prepend_delimiter, - NMTeamAttribute team_attr) + const TeamAttrData *attr_data) { - const TeamAttrData *attr_data = _team_attr_data_get (self->d.is_port, team_attr); + if (!_team_setting_has_field (self, attr_data)) + return FALSE; if (prepend_delimiter) nm_json_aux_gstr_append_delimiter (gstr); @@ -639,13 +690,13 @@ _team_setting_field_to_json (const NMTeamSetting *self, self->d.is_port, gstr, _team_setting_get_field (self, attr_data)); + return TRUE; } static gboolean _team_setting_fields_to_json_maybe (const NMTeamSetting *self, GString *gstr, gboolean prepend_delimiter, - const bool is_default_lst[static _NM_TEAM_ATTRIBUTE_NUM], const NMTeamAttribute *team_attrs_lst, gsize team_attrs_lst_len) { @@ -653,14 +704,13 @@ _team_setting_fields_to_json_maybe (const NMTeamSetting *self, gboolean any_added = FALSE; for (i = 0; i < team_attrs_lst_len; i++) { - NMTeamAttribute team_attr = team_attrs_lst[i]; - - if (is_default_lst[team_attr]) - continue; - - _team_setting_field_to_json (self, gstr, prepend_delimiter, team_attr); - any_added = TRUE; - prepend_delimiter = TRUE; + if (_team_setting_field_to_json (self, + gstr, + prepend_delimiter, + _team_attr_data_get (self->d.is_port, team_attrs_lst[i]))) { + any_added = TRUE; + prepend_delimiter = TRUE; + } } return any_added; } @@ -673,39 +723,22 @@ _team_setting_set (NMTeamSetting *self, { guint32 changed_flags = 0; const TeamAttrData *attr_data; - const char *v_master_runner; nm_assert ((!has_lst) == (!val_lst)); - if (!self->d.is_port) { - if ( has_lst - && has_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER]) - v_master_runner = val_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER].v_string; - else { - nm_assert (nm_streq0 (_team_attr_data_get (FALSE, NM_TEAM_ATTRIBUTE_MASTER_RUNNER)->default_val.v_string, - NM_SETTING_TEAM_RUNNER_DEFAULT)); - v_master_runner = NM_SETTING_TEAM_RUNNER_DEFAULT; - } - } else - v_master_runner = NULL; - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { - NMValueTypUnion value_tmp; const NMValueTypUnion *p_val; gconstpointer p_field; + gboolean has_field; if (!_team_attr_data_is_relevant (attr_data, self->d.is_port)) continue; - if ( has_lst - && has_lst[attr_data->team_attr]) - p_val = &val_lst[attr_data->team_attr]; - else { - p_val = _team_attr_data_get_default (attr_data, - self->d.is_port, - v_master_runner, - &value_tmp); - } + has_field = (has_lst && has_lst[attr_data->team_attr]); + + p_val = has_field + ? &val_lst[attr_data->team_attr] + : &attr_data->default_val; p_field = _team_setting_get_field (self, attr_data); @@ -721,6 +754,14 @@ _team_setting_set (NMTeamSetting *self, } changed_flags |= nm_team_attribute_to_flags (attr_data->team_attr); } + + if (modify) { + _team_setting_has_field_set (self, + attr_data, + has_field + ? SET_FIELD_MODE_SET + : SET_FIELD_MODE_UNSET); + } } return changed_flags; @@ -749,31 +790,54 @@ _nm_team_setting_value_get (const NMTeamSetting *self, nm_assert (value_type == attr_data->value_type); + nm_assert ( _team_setting_has_field (self, attr_data) + || _team_attr_data_equal (attr_data, + self->d.is_port, + _team_setting_get_field (self, attr_data), + &attr_data->default_val)); return _team_setting_get_field (self, attr_data); } static guint32 _team_setting_value_set (NMTeamSetting *self, - NMTeamAttribute team_attr, - NMValueType value_type, - gconstpointer val) + const TeamAttrData *attr_data, + gconstpointer val, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) +{ + gpointer p_field; + gboolean changed; + + nm_assert (self); + _team_attr_data_ASSERT (attr_data); + nm_assert (val); + + p_field = _team_setting_get_field (self, attr_data); + + changed = !_team_attr_data_equal (attr_data, self->d.is_port, p_field, val); + if (changed) + nm_value_type_copy (attr_data->value_type, p_field, val); + return _team_setting_attribute_changed (self, attr_data, changed, set_field_mode, reset_json); +} + +guint32 +nm_team_setting_value_reset (NMTeamSetting *self, + NMTeamAttribute team_attr, + gboolean to_default /* or else unset */) { const TeamAttrData *attr_data; - gpointer p_field; nm_assert (self); attr_data = _team_attr_data_get (self->d.is_port, team_attr); - nm_assert (val); - nm_assert (value_type == attr_data->value_type); - - p_field = _team_setting_get_field (self, attr_data); - - if (nm_value_type_equal (attr_data->value_type, p_field, val)) - return 0u; - nm_value_type_copy (attr_data->value_type, p_field, val); - return nm_team_attribute_to_flags (team_attr); + return _team_setting_value_set (self, + attr_data, + &attr_data->default_val, + to_default + ? SET_FIELD_MODE_SET + : SET_FIELD_MODE_UNSET, + RESET_JSON_YES); } guint32 @@ -782,12 +846,19 @@ _nm_team_setting_value_set (NMTeamSetting *self, NMValueType value_type, gconstpointer val) { - return _team_setting_attribute_changed (self, - team_attr, - (_team_setting_value_set (self, - team_attr, - value_type, - val) != 0u)); + const TeamAttrData *attr_data; + + nm_assert (self); + + attr_data = _team_attr_data_get (self->d.is_port, team_attr); + + nm_assert (value_type == attr_data->value_type); + + return _team_setting_value_set (self, + attr_data, + val, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); } guint32 @@ -795,14 +866,19 @@ nm_team_setting_value_link_watchers_add (NMTeamSetting *self, const NMTeamLinkWatcher *link_watcher) { guint i; + gboolean changed; for (i = 0; i < self->d.link_watchers->len; i++) { - if (nm_team_link_watcher_equal (self->d.link_watchers->pdata[i], link_watcher)) - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, FALSE); + if (nm_team_link_watcher_equal (self->d.link_watchers->pdata[i], link_watcher)) { + changed = FALSE; + goto out; + } } + changed = TRUE; g_ptr_array_add ((GPtrArray *) self->d.link_watchers, _nm_team_link_watcher_ref ((NMTeamLinkWatcher *) link_watcher)); - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, TRUE); +out: + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, changed, SET_FIELD_MODE_SET_UNLESS_DEFAULT, RESET_JSON_YES); } guint32 @@ -816,7 +892,7 @@ nm_team_setting_value_link_watchers_remove_by_value (NMTeamSetting *self, link_watcher)) return nm_team_setting_value_link_watchers_remove (self, i); } - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, FALSE); + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, FALSE, SET_FIELD_MODE_SET_UNLESS_DEFAULT, RESET_JSON_YES); } guint32 @@ -824,21 +900,28 @@ nm_team_setting_value_link_watchers_remove (NMTeamSetting *self, guint idx) { g_ptr_array_remove_index ((GPtrArray *) self->d.link_watchers, idx); - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, TRUE); + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, TRUE, SET_FIELD_MODE_SET_UNLESS_DEFAULT, RESET_JSON_YES); } static guint32 _team_setting_value_link_watchers_set_list (NMTeamSetting *self, const NMTeamLinkWatcher *const*arr, - guint len) + guint len, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) { + gboolean changed; + if ( self->d.link_watchers->len == len && nm_team_link_watchers_cmp ((const NMTeamLinkWatcher *const*) self->d.link_watchers->pdata, arr, len, - FALSE) == 0) - return 0; + FALSE) == 0) { + changed = FALSE; + goto out; + } + changed = TRUE; if (len == 0) g_ptr_array_set_size ((GPtrArray *) self->d.link_watchers, 0); else { @@ -857,7 +940,8 @@ _team_setting_value_link_watchers_set_list (NMTeamSetting *self, } } - return nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_LINK_WATCHERS); +out: + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_LINK_WATCHERS, changed, set_field_mode, reset_json); } guint32 @@ -865,11 +949,11 @@ nm_team_setting_value_link_watchers_set_list (NMTeamSetting *self, const NMTeamLinkWatcher *const*arr, guint len) { - return _team_setting_attribute_changed (self, - NM_TEAM_ATTRIBUTE_LINK_WATCHERS, - (_team_setting_value_link_watchers_set_list (self, - arr, - len) != 0u)); + return _team_setting_value_link_watchers_set_list (self, + arr, + len, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); } /*****************************************************************************/ @@ -878,18 +962,23 @@ guint32 nm_team_setting_value_master_runner_tx_hash_add (NMTeamSetting *self, const char *txhash) { + gboolean changed; guint i; if (!self->d.master.runner_tx_hash) self->_data_priv.master.runner_tx_hash = g_ptr_array_new_with_free_func (g_free); else { for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { - if (nm_streq (txhash, self->d.master.runner_tx_hash->pdata[i])) - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, FALSE); + if (nm_streq (txhash, self->d.master.runner_tx_hash->pdata[i])) { + changed = FALSE; + goto out; + } } } + changed = TRUE; g_ptr_array_add ((GPtrArray *) self->d.master.runner_tx_hash, g_strdup (txhash)); - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, TRUE); +out: + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, changed, SET_FIELD_MODE_SET_UNLESS_DEFAULT, RESET_JSON_YES); } guint32 @@ -897,22 +986,29 @@ nm_team_setting_value_master_runner_tx_hash_remove (NMTeamSetting *self, guint idx) { g_ptr_array_remove_index ((GPtrArray *) self->d.master.runner_tx_hash, idx); - return _team_setting_attribute_changed (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, TRUE); + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, TRUE, SET_FIELD_MODE_SET_UNLESS_DEFAULT, RESET_JSON_YES); } static guint32 _team_setting_value_master_runner_tx_hash_set_list (NMTeamSetting *self, const char *const*arr, - guint len) + guint len, + SetFieldModeEnum set_field_mode, + ResetJsonEnum reset_json) { _nm_unused gs_unref_ptrarray GPtrArray *old_val_destroy = NULL; + gboolean changed; guint i; if (_nm_utils_strv_cmp_n (self->d.master.runner_tx_hash ? (const char *const*) self->d.master.runner_tx_hash->pdata : NULL, self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len : 0u, arr, - len) == 0) - return 0u; + len) == 0) { + changed = FALSE; + goto out; + } + + changed = TRUE; old_val_destroy = (GPtrArray *) g_steal_pointer (&self->_data_priv.master.runner_tx_hash); @@ -924,7 +1020,8 @@ _team_setting_value_master_runner_tx_hash_set_list (NMTeamSetting *self, g_ptr_array_add ((GPtrArray *) self->d.master.runner_tx_hash, g_strdup (arr[i])); } - return nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH); +out: + return _team_setting_attribute_changed_attr (self, NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, changed, set_field_mode, reset_json); } guint32 @@ -932,11 +1029,11 @@ nm_team_setting_value_master_runner_tx_hash_set_list (NMTeamSetting *self, const char *const*arr, guint len) { - return _team_setting_attribute_changed (self, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - (_team_setting_value_master_runner_tx_hash_set_list (self, - arr, - len) != 0u)); + return _team_setting_value_master_runner_tx_hash_set_list (self, + arr, + len, + SET_FIELD_MODE_SET_UNLESS_DEFAULT, + RESET_JSON_YES); } /*****************************************************************************/ @@ -1030,7 +1127,7 @@ _link_watcher_to_json (const NMTeamLinkWatcher *link_watcher, nm_value_type_to_json (attr_data->value_type, gstr, &p_val->val); } - g_string_append (gstr, "}"); + g_string_append (gstr, " }"); } #if WITH_JSON_VALIDATION @@ -1361,7 +1458,7 @@ _link_watcher_from_variant (GVariant *watcher_var, * Returns: (transfer full): a new floating #GVariant representing link watchers. **/ GVariant * -_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers) +_nm_utils_team_link_watchers_to_variant (const GPtrArray *link_watchers) { GVariantBuilder builder; guint i; @@ -1441,29 +1538,13 @@ nm_team_setting_config_get (const NMTeamSetting *self) * Nothing to do. */ js_str = NULL; } else { - const TeamAttrData *attr_data; - GString *gstr; - bool is_default_lst[_NM_TEAM_ATTRIBUTE_NUM] = { FALSE, }; gboolean list_is_empty = TRUE; - const char *v_master_runner; + GString *gstr; gstr = g_string_new (NULL); g_string_append (gstr, "{ "); - v_master_runner = self->d.is_port - ? NULL - : self->d.master.runner; - - for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { - if (_team_attr_data_is_relevant (attr_data, self->d.is_port)) { - is_default_lst[attr_data->team_attr] = _team_attr_data_is_default (attr_data, - self->d.is_port, - v_master_runner, - _team_setting_get_field (self, attr_data)); - } - } - if (self->d.is_port) { static const NMTeamAttribute attr_lst_port[] = { NM_TEAM_ATTRIBUTE_PORT_QUEUE_ID, @@ -1473,57 +1554,57 @@ nm_team_setting_config_get (const NMTeamSetting *self) NM_TEAM_ATTRIBUTE_PORT_LACP_KEY, }; - if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty, is_default_lst, attr_lst_port, G_N_ELEMENTS (attr_lst_port))) + if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty, attr_lst_port, G_N_ELEMENTS (attr_lst_port))) list_is_empty = FALSE; } else { + static const NMTeamAttribute attr_lst_runner_pt1[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, + }; + static const NMTeamAttribute attr_lst_runner_pt2[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, + }; + static const NMTeamAttribute attr_lst_runner_pt3[] = { + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, + NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, + }; + static const NMTeamAttribute attr_lst_notify_peers[] = { + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, + NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, + }; + static const NMTeamAttribute attr_lst_mcast_rejoin[] = { + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, + NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, + }; - if ( !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY]) { - static const NMTeamAttribute attr_lst_runner_pt1[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_HWADDR_POLICY, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH, - }; - static const NMTeamAttribute attr_lst_runner_pt2[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL, - }; - static const NMTeamAttribute attr_lst_runner_pt3[] = { - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_ACTIVE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_FAST_RATE, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_SYS_PRIO, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_MIN_PORTS, - NM_TEAM_ATTRIBUTE_MASTER_RUNNER_AGG_SELECT_POLICY, - }; + if ( _team_setting_has_fields_any_v (self, attr_lst_runner_pt1, G_N_ELEMENTS (attr_lst_runner_pt1)) + || _team_setting_has_fields_any_v (self, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2)) + || _team_setting_has_fields_any_v (self, attr_lst_runner_pt3, G_N_ELEMENTS (attr_lst_runner_pt3))) { gboolean list_is_empty2 = TRUE; if (!list_is_empty) nm_json_aux_gstr_append_delimiter (gstr); nm_json_aux_gstr_append_obj_name (gstr, "runner", '{'); - if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty2, is_default_lst, attr_lst_runner_pt1, G_N_ELEMENTS (attr_lst_runner_pt1))) + if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty2, attr_lst_runner_pt1, G_N_ELEMENTS (attr_lst_runner_pt1))) list_is_empty2 = FALSE; - if ( !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_BALANCER_INTERVAL]) { + if (_team_setting_has_fields_any_v (self, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2))) { if (!list_is_empty2) nm_json_aux_gstr_append_delimiter (gstr); nm_json_aux_gstr_append_obj_name (gstr, "tx_balancer", '{'); - if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, is_default_lst, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2))) + if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2))) nm_assert_not_reached (); g_string_append (gstr, " }"); list_is_empty2 = FALSE; } - if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty2, is_default_lst, attr_lst_runner_pt3, G_N_ELEMENTS (attr_lst_runner_pt3))) + if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty2, attr_lst_runner_pt3, G_N_ELEMENTS (attr_lst_runner_pt3))) list_is_empty2 = FALSE; nm_assert (!list_is_empty2); @@ -1531,43 +1612,33 @@ nm_team_setting_config_get (const NMTeamSetting *self) list_is_empty = FALSE; } - if ( !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL]) { - static const NMTeamAttribute attr_lst_notify_peers[] = { - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_COUNT, - NM_TEAM_ATTRIBUTE_MASTER_NOTIFY_PEERS_INTERVAL, - }; - + if (_team_setting_has_fields_any_v (self, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers))) { if (!list_is_empty) nm_json_aux_gstr_append_delimiter (gstr); nm_json_aux_gstr_append_obj_name (gstr, "notify_peers", '{'); - if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, is_default_lst, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers))) + if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers))) nm_assert_not_reached (); g_string_append (gstr, " }"); list_is_empty = FALSE; } - if ( !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT] - || !is_default_lst[NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL]) { - static const NMTeamAttribute attr_lst_notify_peers[] = { - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_COUNT, - NM_TEAM_ATTRIBUTE_MASTER_MCAST_REJOIN_INTERVAL, - }; - + if (_team_setting_has_fields_any_v (self, attr_lst_mcast_rejoin, G_N_ELEMENTS (attr_lst_mcast_rejoin))) { if (!list_is_empty) nm_json_aux_gstr_append_delimiter (gstr); nm_json_aux_gstr_append_obj_name (gstr, "mcast_rejoin", '{'); - if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, is_default_lst, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers))) + if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_mcast_rejoin, G_N_ELEMENTS (attr_lst_mcast_rejoin))) nm_assert_not_reached (); g_string_append (gstr, " }"); list_is_empty = FALSE; } } - if (!is_default_lst[NM_TEAM_ATTRIBUTE_LINK_WATCHERS]) { - _team_setting_field_to_json (self, gstr, !list_is_empty, NM_TEAM_ATTRIBUTE_LINK_WATCHERS); + if (_team_setting_field_to_json (self, + gstr, + !list_is_empty, + _team_attr_data_get (self->d.is_port, NM_TEAM_ATTRIBUTE_LINK_WATCHERS))) list_is_empty = FALSE; - } + if (!list_is_empty) g_string_append (gstr, " }"); @@ -1782,7 +1853,6 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str) { guint32 changed_flags = 0; gboolean do_set_default = TRUE; - gboolean new_strict_validated = FALSE; gboolean new_js_str_invalid = FALSE; _team_setting_ASSERT (self); @@ -1844,13 +1914,6 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str) TRUE, has_lst, val_lst); - - if ( !unrecognized_content - && _team_setting_verify (self, NULL)) { - /* if we could parse everything without unexpected/unknown data, - * we switch into strictly validating mode. */ - new_strict_validated = TRUE; - } } } @@ -1859,7 +1922,7 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str) if (do_set_default) changed_flags |= _team_setting_set_default (self); - self->_data_priv.strict_validated = new_strict_validated; + self->_data_priv.strict_validated = FALSE; self->_data_priv._js_str_need_synthetize = FALSE; self->_data_priv.js_str_invalid = new_js_str_invalid; g_free ((char *) self->_data_priv._js_str); @@ -1870,104 +1933,166 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str) /*****************************************************************************/ +static void +_team_setting_prefix_error_plain (gboolean is_port, + const char *property_name, + GError **error) +{ + g_prefix_error (error, + "%s.%s: ", + is_port + ? NM_SETTING_TEAM_PORT_SETTING_NAME + : NM_SETTING_TEAM_SETTING_NAME, + property_name); +} + static void _team_setting_prefix_error (const NMTeamSetting *self, - GError **error, const char *prop_name_master, - const char *prop_name_port) + const char *prop_name_port, + GError **error) { _team_setting_ASSERT (self); nm_assert ( self->d.is_port ? (!!prop_name_port) : (!!prop_name_master)); - g_prefix_error (error, - "%s.%s: ", - self->d.is_port - ? NM_SETTING_TEAM_PORT_SETTING_NAME - : NM_SETTING_TEAM_SETTING_NAME, - self->d.is_port - ? prop_name_master - : prop_name_port); + _team_setting_prefix_error_plain (self->d.is_port, + self->d.is_port + ? prop_name_port + : prop_name_master, + error); } static gboolean -_team_setting_verify (const NMTeamSetting *self, - GError **error) +_team_setting_verify_properties (const NMTeamSetting *self, + GError **error) { + const TeamAttrData *attr_data; guint i; - const char *js_str; - if (!self->d.is_port) { - if (!self->d.master.runner) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, - _("missing runner")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_RUNNER, NULL); - return FALSE; - } - if ( self->d.master.runner - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_BROADCAST) != 0 - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_ROUNDROBIN) != 0 - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_RANDOM) != 0 - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP) != 0 - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_LOADBALANCE) != 0 - && g_ascii_strcasecmp (self->d.master.runner, NM_SETTING_TEAM_RUNNER_LACP) != 0) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, - _("invalid runner \"%s\""), self->d.master.runner); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_RUNNER, NULL); - return FALSE; - } + for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { - if (self->d.master.runner_tx_hash) { - for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { - const char *val = self->d.master.runner_tx_hash->pdata[i]; + if (!_team_attr_data_is_relevant (attr_data, self->d.is_port)) + continue; + if (!_team_setting_has_field (self, attr_data)) + continue; - if (!val[0]) { + if (attr_data->has_range) { + gconstpointer p_field; + + p_field = _team_setting_get_field (self, attr_data); + if (attr_data->value_type == NM_VALUE_TYPE_INT32) { + gint32 v = *((const gint32 *) p_field); + + if ( v < attr_data->range.r_int32.min + || v > attr_data->range.r_int32.max) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, - _("invalid runner.tx-hash")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_RUNNER_TX_HASH, NULL); + _("value out or range")); + _team_setting_prefix_error_plain (self->d.is_port, attr_data->property_name, error); return FALSE; } + } else if (attr_data->value_type == NM_VALUE_TYPE_STRING) { + const char *v = *((const char *const*) p_field); + + if (nm_utils_strv_find_first ((char **) attr_data->range.r_string.valid_names, + -1, + v) < 0) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("invalid value")); + _team_setting_prefix_error_plain (self->d.is_port, attr_data->property_name, error); + return FALSE; + } + } else + nm_assert_not_reached (); + } + + if ( !self->d.is_port + && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + if (self->d.master.runner_tx_hash) { + for (i = 0; i < self->d.master.runner_tx_hash->len; i++) { + const char *val = self->d.master.runner_tx_hash->pdata[i]; + + if ( !val + || (nm_utils_strv_find_first ((char **) _valid_names_runner_tx_hash, + -1, + val) < 0)) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("invalid runner-tx-hash")); + _team_setting_prefix_error_plain (self->d.is_port, NM_SETTING_TEAM_RUNNER_TX_HASH, error); + return FALSE; + } + } } } } - for (i = 0; i < self->d.link_watchers->len; i++) { - NMTeamLinkWatcher *link_watcher = self->d.link_watchers->pdata[i]; - const char *name = nm_team_link_watcher_get_name (link_watcher); + if (!self->d.is_port) { - if (!NM_IN_STRSET (name, - NM_TEAM_LINK_WATCHER_ETHTOOL, - NM_TEAM_LINK_WATCHER_ARP_PING, - NM_TEAM_LINK_WATCHER_NSNA_PING)) { - if (!name) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing link watcher name")); - } else { + for (i = 0; i < G_N_ELEMENTS (_runner_compat_lst); i++) { + const RunnerCompatElem *e = &_runner_compat_lst[i]; + + nm_assert (NM_PTRARRAY_LEN (e->valid_runners) > 0); + + attr_data = _team_attr_data_get (FALSE, e->team_attr); + + if (!_team_setting_has_field (self, attr_data)) + continue; + if ( self->d.master.runner + && (nm_utils_strv_find_first ((char **) e->valid_runners, + -1, + self->d.master.runner) >= 0)) + continue; + if (e->valid_runners[1] == NULL) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, - _("unknown link watcher \"%s\""), name); - } - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_LINK_WATCHERS, NM_SETTING_TEAM_PORT_LINK_WATCHERS); - return FALSE; - } + _("%s is only allowed for runner %s"), + attr_data->property_name, + e->valid_runners[0]); + } else { + gs_free char *s = NULL; - if ( NM_IN_STRSET (name, - NM_TEAM_LINK_WATCHER_ARP_PING, - NM_TEAM_LINK_WATCHER_NSNA_PING) - && !nm_team_link_watcher_get_target_host (link_watcher)) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing target host")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_LINK_WATCHERS, NM_SETTING_TEAM_PORT_LINK_WATCHERS); + s = g_strjoinv (",", (char **) e->valid_runners); + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("%s is only allowed for runners %s"), + attr_data->property_name, + s); + } + _team_setting_prefix_error_plain (self->d.is_port, NM_SETTING_TEAM_RUNNER, error); return FALSE; } - if ( nm_streq (name, NM_TEAM_LINK_WATCHER_ARP_PING) - && !nm_team_link_watcher_get_source_host (link_watcher)) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, - _("missing source address")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_LINK_WATCHERS, NM_SETTING_TEAM_PORT_LINK_WATCHERS); + } else { + gboolean has_lacp_attrs; + gboolean has_activebackup_attrs; + + has_lacp_attrs = _team_setting_has_fields_any (self, NM_TEAM_ATTRIBUTE_PORT_LACP_PRIO, + NM_TEAM_ATTRIBUTE_PORT_LACP_KEY); + has_activebackup_attrs = _team_setting_has_fields_any (self, NM_TEAM_ATTRIBUTE_PORT_PRIO, + NM_TEAM_ATTRIBUTE_PORT_STICKY); + if (has_lacp_attrs && has_activebackup_attrs) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("cannot set parameters for lacp and activebackup runners together")); + _team_setting_prefix_error (self, NM_SETTING_TEAM_LINK_WATCHERS, NM_SETTING_TEAM_PORT_LINK_WATCHERS, error); return FALSE; } } + for (i = 0; i < self->d.link_watchers->len; i++) { + if (!self->d.link_watchers->pdata[i]) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("missing link watcher")); + _team_setting_prefix_error (self, NM_SETTING_TEAM_LINK_WATCHERS, NM_SETTING_TEAM_PORT_LINK_WATCHERS, error); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +_team_setting_verify_config (const NMTeamSetting *self, + GError **error) +{ + const char *js_str; + /* we always materialize the JSON string. That is because we want to validate the * string length of the resulting JSON. */ js_str = nm_team_setting_config_get (self); @@ -1976,19 +2101,19 @@ _team_setting_verify (const NMTeamSetting *self, if (strlen (js_str) > 1*1024*1024) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("team config exceeds size limit")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG); + _team_setting_prefix_error (self, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG, error); return FALSE; } if (!g_utf8_validate (js_str, -1, NULL)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("team config is not valid UTF-8")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG); + _team_setting_prefix_error (self, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG, error); return FALSE; } if (self->d.js_str_invalid) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("invalid json")); - _team_setting_prefix_error (self, error, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG); + _team_setting_prefix_error (self, NM_SETTING_TEAM_CONFIG, NM_SETTING_TEAM_PORT_CONFIG, error); return FALSE; } } @@ -2000,7 +2125,11 @@ gboolean nm_team_setting_verify (const NMTeamSetting *self, GError **error) { - return _team_setting_verify (self, error); + if (self->d.strict_validated) { + if (!_team_setting_verify_properties (self, error)) + return FALSE; + } + return _team_setting_verify_config (self, error); } /*****************************************************************************/ @@ -2017,12 +2146,13 @@ nm_team_setting_cmp (const NMTeamSetting *self_a, NM_CMP_FIELD_UNSAFE (self_a, self_b, d.is_port); for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { - if (_team_attr_data_is_relevant (attr_data, self_a->d.is_port)) { - NM_CMP_RETURN (_team_attr_data_cmp (attr_data, - self_a->d.is_port, - _team_setting_get_field (self_a, attr_data), - _team_setting_get_field (self_b, attr_data))); - } + if (!_team_attr_data_is_relevant (attr_data, self_a->d.is_port)) + continue; + + NM_CMP_RETURN (_team_attr_data_cmp (attr_data, + self_a->d.is_port, + _team_setting_get_field (self_a, attr_data), + _team_setting_get_field (self_b, attr_data))); } if (!ignore_js_str) { @@ -2038,7 +2168,7 @@ nm_team_setting_reset (NMTeamSetting *self, const NMTeamSetting *src) { const TeamAttrData *attr_data; - guint32 changed; + guint32 changed_flags; _team_setting_ASSERT (self); _team_setting_ASSERT (src); @@ -2047,7 +2177,7 @@ nm_team_setting_reset (NMTeamSetting *self, if (self == src) return 0; - changed = 0; + changed_flags = 0; for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { if (!_team_attr_data_is_relevant (attr_data, self->d.is_port)) @@ -2061,21 +2191,23 @@ nm_team_setting_reset (NMTeamSetting *self, self->d.is_port, _team_setting_get_field (self, attr_data), _team_setting_get_field (src, attr_data)); - changed |= nm_team_attribute_to_flags (attr_data->team_attr); + changed_flags |= nm_team_attribute_to_flags (attr_data->team_attr); } + self->_data_priv.has_fields_mask = src->d.has_fields_mask; + if (!nm_streq0 (self->d._js_str, src->d._js_str)) { g_free ((char *) self->_data_priv._js_str); self->_data_priv._js_str = g_strdup (src->d._js_str); - changed |= nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); - } else if (changed != 0) - changed |= nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); + changed_flags |= nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); + } else if (changed_flags != 0) + changed_flags |= nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG); self->_data_priv._js_str_need_synthetize = src->d._js_str_need_synthetize; self->_data_priv.strict_validated = src->d.strict_validated; self->_data_priv.js_str_invalid = src->d.js_str_invalid; - return changed; + return changed_flags; } static void @@ -2109,7 +2241,7 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, _nm_unused gs_unref_variant GVariant *v_val_free = v_val; const GVariantType *variant_type = NULL; - attr_data = _team_attr_data_find_for_dbus_name (self->d.is_port, v_key); + attr_data = _team_attr_data_find_for_property_name (self->d.is_port, v_key); if (!attr_data) { /* _nm_setting_new_from_dbus() already checks for unknown keys. Don't * do that here. */ @@ -2136,10 +2268,9 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("invalid D-Bus type \"%s\""), g_variant_get_type_string (v_val)); - _team_setting_prefix_error (self, - error, - attr_data->dbus_name, - attr_data->dbus_name); + _team_setting_prefix_error_plain (self->d.is_port, + attr_data->property_name, + error); return FALSE; } continue; @@ -2152,20 +2283,36 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, } if (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS]) { - gs_free_error GError *local = NULL; - v_link_watchers = _nm_utils_team_link_watchers_from_variant (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], - NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), - &local); - if (local) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid link-watchers: %s"), - local->message); - _team_setting_prefix_error (self, - error, - NM_SETTING_TEAM_LINK_WATCHERS, - NM_SETTING_TEAM_PORT_LINK_WATCHERS); - return FALSE; + if ( variants[NM_TEAM_ATTRIBUTE_CONFIG] + && WITH_JSON_VALIDATION + && !NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + /* we don't require the content of the "link-watchers" and we also + * don't perform strict validation. No need to parse it. */ + } else { + gs_free_error GError *local = NULL; + + /* We might need the parsed v_link_watchers array below (because there is no JSON + * "config" present or because we don't build WITH_JSON_VALIDATION). + * + * Or we might run with NM_SETTING_PARSE_FLAGS_STRICT. In that mode, we may not necessarily + * require that the entire setting as a whole validates (if a JSON config is present and + * we are not "strict_validated") , but we require that we can at least parse the link watchers + * on their own. */ + v_link_watchers = _nm_utils_team_link_watchers_from_variant (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS], + NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT), + &local); + if ( local + && NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid link-watchers: %s"), + local->message); + _team_setting_prefix_error (self, + NM_SETTING_TEAM_LINK_WATCHERS, + NM_SETTING_TEAM_PORT_LINK_WATCHERS, + error); + return FALSE; + } } } @@ -2174,8 +2321,8 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, ? g_variant_get_string (variants[NM_TEAM_ATTRIBUTE_CONFIG], NULL) : NULL); - if ( variants[NM_TEAM_ATTRIBUTE_CONFIG] - && WITH_JSON_VALIDATION) { + if ( WITH_JSON_VALIDATION + && variants[NM_TEAM_ATTRIBUTE_CONFIG]) { /* for team settings, the JSON must be able to express all possible options. That means, * if the GVariant contains both the JSON "config" and other options, then the other options * are silently ignored. */ @@ -2184,7 +2331,7 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) { NMValueTypUnion val; - guint32 changed = 0u; + guint32 changed_flags = 0u; if (!_team_attr_data_is_relevant (attr_data, self->d.is_port)) continue; @@ -2193,31 +2340,35 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self, if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { nm_value_type_get_from_variant (attr_data->value_type, &val, variants[attr_data->team_attr], FALSE); - changed = _team_setting_value_set (self, - attr_data->team_attr, - attr_data->value_type, - &val); + changed_flags = _team_setting_value_set (self, + attr_data, + &val, + SET_FIELD_MODE_SET, + RESET_JSON_NO); } else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) { - changed = _team_setting_value_link_watchers_set_list (self, - v_link_watchers ? (const NMTeamLinkWatcher *const *) v_link_watchers->pdata : NULL, - v_link_watchers ? v_link_watchers->len : 0u); + changed_flags = _team_setting_value_link_watchers_set_list (self, + v_link_watchers ? (const NMTeamLinkWatcher *const *) v_link_watchers->pdata : NULL, + v_link_watchers ? v_link_watchers->len : 0u, + SET_FIELD_MODE_SET, + RESET_JSON_NO); } else if ( !self->d.is_port && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { gs_free const char **strv = NULL; gsize len; strv = g_variant_get_strv (variants[attr_data->team_attr], &len); - changed = _team_setting_value_master_runner_tx_hash_set_list (self, - strv, - NM_MIN (len, (gsize) G_MAXUINT)); + changed_flags = _team_setting_value_master_runner_tx_hash_set_list (self, + strv, + NM_MIN (len, (gsize) G_MAXUINT), + SET_FIELD_MODE_SET, + RESET_JSON_NO); } else nm_assert_not_reached (); - extra_changed |= changed; + extra_changed |= changed_flags; } - if ( !variants[NM_TEAM_ATTRIBUTE_CONFIG] - && extra_changed) { + if (!variants[NM_TEAM_ATTRIBUTE_CONFIG]) { /* clear the JSON string so it can be regenerated. But only if we didn't set * it above. */ self->_data_priv.strict_validated = TRUE; @@ -2272,6 +2423,70 @@ nm_team_setting_maybe_changed (NMSetting *source, /*****************************************************************************/ +NMTeamSetting * +_nm_setting_get_team_setting (struct _NMSetting *setting) +{ + if (NM_IS_SETTING_TEAM (setting)) + return _nm_setting_team_get_team_setting (NM_SETTING_TEAM (setting)); + return _nm_setting_team_port_get_team_setting (NM_SETTING_TEAM_PORT (setting)); +} + +GVariant * +_nm_team_settings_property_to_dbus (const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection *connection, + NMSetting *setting, + NMConnectionSerializationFlags flags) +{ + NMTeamSetting *self = _nm_setting_get_team_setting (setting); + const TeamAttrData *attr_data = _team_attr_data_get (self->d.is_port, sett_info->property_infos[property_idx].param_spec->param_id); + + if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_CONFIG) { + const char *config; + + if ( self->d.strict_validated + && !_nm_utils_is_manager_process) { + /* if we are in strict validating mode on the client side, the JSON is generated + * artificially. In this case, don't send the config via D-Bus to the server. + * + * This also will cause NetworkManager to strictly validate the settings. + * If a JSON "config" is present, strict validation won't be performed. */ + return NULL; + } + + config = nm_team_setting_config_get (self); + return config ? g_variant_new_string (config) : NULL; + } + + if (!_team_setting_has_field (self, attr_data)) + return NULL; + + if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) { + return nm_value_type_to_variant (attr_data->value_type, + _team_setting_get_field (self, attr_data)); + } + if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) + return _nm_utils_team_link_watchers_to_variant (self->d.link_watchers); + if ( !self->d.is_port + && attr_data->team_attr == NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH) { + return g_variant_new_strv (self->d.master.runner_tx_hash ? (const char *const*) self->d.master.runner_tx_hash->pdata : NULL, + self->d.master.runner_tx_hash ? self->d.master.runner_tx_hash->len : 0u); + } + + nm_assert_not_reached (); + return NULL; +} + +void +_nm_team_settings_property_from_dbus_link_watchers (GVariant *dbus_value, + GValue *prop_value) +{ + g_value_take_boxed (prop_value, + _nm_utils_team_link_watchers_from_variant (dbus_value, FALSE, NULL)); +} + +/*****************************************************************************/ + NMTeamSetting * nm_team_setting_new (gboolean is_port, const char *js_str) diff --git a/libnm-core/nm-team-utils.h b/libnm-core/nm-team-utils.h index e443b27dd3..0e897da96a 100644 --- a/libnm-core/nm-team-utils.h +++ b/libnm-core/nm-team-utils.h @@ -96,6 +96,8 @@ struct _NMTeamSettingData { bool is_port:1; + guint32 has_fields_mask; + union { struct { const GPtrArray *runner_tx_hash; @@ -185,6 +187,10 @@ nm_team_setting_value_get_string (const NMTeamSetting *self, /*****************************************************************************/ +guint32 nm_team_setting_value_reset (NMTeamSetting *self, + NMTeamAttribute team_attr, + gboolean to_default /* or else unset */); + guint32 _nm_team_setting_value_set (NMTeamSetting *self, NMTeamAttribute team_attr, NMValueType value_type, @@ -269,7 +275,7 @@ gboolean nm_team_setting_reset_from_dbus (NMTeamSetting *self, GPtrArray *_nm_utils_team_link_watchers_from_variant (GVariant *value, gboolean strict_parsing, GError **error); -GVariant *_nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers); +GVariant *_nm_utils_team_link_watchers_to_variant (const GPtrArray *link_watchers); /*****************************************************************************/ @@ -277,4 +283,24 @@ gboolean nm_team_setting_maybe_changed (struct _NMSetting *source, const GParamSpec *const*obj_properties, guint32 changed); +struct _NMSettingTeam; +struct _NMSettingTeamPort; +NMTeamSetting *_nm_setting_team_get_team_setting (struct _NMSettingTeam *setting); +NMTeamSetting *_nm_setting_team_port_get_team_setting (struct _NMSettingTeamPort *setting); +NMTeamSetting *_nm_setting_get_team_setting (struct _NMSetting *setting); + +/*****************************************************************************/ + +#include "nm-connection.h" +#include "nm-core-internal.h" + +GVariant *_nm_team_settings_property_to_dbus (const NMSettInfoSetting *sett_info, + guint property_idx, + NMConnection *connection, + NMSetting *setting, + NMConnectionSerializationFlags flags); + +void _nm_team_settings_property_from_dbus_link_watchers (GVariant *dbus_value, + GValue *prop_value); + #endif /* __NM_TEAM_UITLS_H__ */ diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index a8d182c457..1c023b65bd 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -6862,10 +6862,6 @@ test_nm_utils_team_config_equal (void) TRUE); /* team config */ - _team_config_equal_check ("{ }", - "{ \"runner\" : { \"name\" : \"roundrobin\"} }", - FALSE, - TRUE); _team_config_equal_check ("{ }", "{ \"runner\" : { \"name\" : \"random\"} }", FALSE, @@ -6889,7 +6885,7 @@ test_nm_utils_team_config_equal (void) _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }", "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }", FALSE, - TRUE); + !WITH_JSON_VALIDATION); _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }", "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }", FALSE, @@ -6903,7 +6899,7 @@ test_nm_utils_team_config_equal (void) _team_config_equal_check ("{ }", "{ \"link_watch\" : { \"name\" : \"ethtool\"} }", TRUE, - TRUE); + !WITH_JSON_VALIDATION); _team_config_equal_check ("{ }", "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", TRUE, @@ -6911,7 +6907,7 @@ test_nm_utils_team_config_equal (void) _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }", "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", TRUE, - TRUE); + !WITH_JSON_VALIDATION); _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", TRUE, diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index a3be0bc8fa..5c0b731137 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -1057,11 +1057,11 @@ static void test_runner_roundrobin_sync_from_config (void) { _test_team_config_sync ("", - 0, 0, 0, 0, - NM_SETTING_TEAM_RUNNER_ROUNDROBIN, + -1, -1, -1, -1, + NULL, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, NULL); } @@ -1069,11 +1069,11 @@ static void test_runner_broadcast_sync_from_config (void) { _test_team_config_sync ("{\"runner\": {\"name\": \"broadcast\"}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_BROADCAST, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, NULL); } @@ -1081,11 +1081,11 @@ static void test_runner_random_sync_from_config (void) { _test_team_config_sync ("{\"runner\": {\"name\": \"random\"}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_RANDOM, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, NULL); } @@ -1093,12 +1093,11 @@ static void test_runner_activebackup_sync_from_config (void) { _test_team_config_sync ("{\"runner\": {\"name\": \"activebackup\"}}", - NM_SETTING_TEAM_NOTIFY_PEERS_COUNT_ACTIVEBACKUP_DEFAULT, 0, - NM_SETTING_TEAM_NOTIFY_MCAST_COUNT_ACTIVEBACKUP_DEFAULT, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_ACTIVEBACKUP, - NM_SETTING_TEAM_RUNNER_HWADDR_POLICY_DEFAULT, + NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, NULL); } @@ -1113,29 +1112,29 @@ test_runner_loadbalance_sync_from_config (void) g_ptr_array_add (tx_hash, g_strdup ("ipv6")); _test_team_config_sync ("{\"runner\": {\"name\": \"loadbalance\"}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_LOADBALANCE, NULL, - tx_hash, NULL, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, - FALSE, FALSE, -1, -1, NULL, + NULL, NULL, -1, + TRUE, FALSE, -1, -1, NULL, NULL); _test_team_config_sync ("{\"runner\": {\"name\": \"loadbalance\", " "\"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_LOADBALANCE, NULL, - tx_hash, NULL, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, - FALSE, FALSE, -1, -1, NULL, + tx_hash, NULL, -1, + TRUE, FALSE, -1, -1, NULL, NULL); _test_team_config_sync ("{\"runner\": {\"name\": \"loadbalance\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " "\"tx_balancer\": {\"name\": \"basic\", \"balancing_interval\": 30}}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_LOADBALANCE, NULL, tx_hash, "basic", 30, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, NULL); } @@ -1150,21 +1149,21 @@ test_runner_lacp_sync_from_config (void) g_ptr_array_add (tx_hash, g_strdup ("ipv6")); _test_team_config_sync ("{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"]}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_LACP, NULL, - tx_hash, NULL, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, - TRUE, FALSE, NM_SETTING_TEAM_RUNNER_SYS_PRIO_DEFAULT, 0, - NM_SETTING_TEAM_RUNNER_AGG_SELECT_POLICY_DEFAULT, + tx_hash, NULL, -1, + TRUE, FALSE, -1, -1, + NULL, NULL); _test_team_config_sync ("{\"runner\": {\"name\": \"lacp\", \"tx_hash\": [\"eth\", \"ipv4\", \"ipv6\"], " "\"active\": false, \"fast_rate\": true, \"sys_prio\": 10, \"min_ports\": 5, " "\"agg_select_policy\": \"port_config\"}}", - 0, 0, 0, 0, + -1, -1, -1, -1, NM_SETTING_TEAM_RUNNER_LACP, NULL, - tx_hash, NULL, NM_SETTING_TEAM_RUNNER_TX_BALANCER_INTERVAL_DEFAULT, + tx_hash, NULL, -1, FALSE, TRUE, 10, 5, "port_config", NULL); } @@ -1177,11 +1176,11 @@ test_watcher_ethtool_sync_from_config (void) link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref); g_ptr_array_add (link_watchers, nm_team_link_watcher_new_ethtool (0, 0, NULL)); _test_team_config_sync ("{\"link_watch\": {\"name\": \"ethtool\"}}", - 0, 0, 0, 0, - "roundrobin", + -1, -1, -1, -1, + NULL, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, link_watchers); } @@ -1193,11 +1192,11 @@ test_watcher_nsna_ping_sync_from_config (void) link_watchers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_team_link_watcher_unref); g_ptr_array_add (link_watchers, nm_team_link_watcher_new_nsna_ping (0, 0, 3, "target.host", NULL)); _test_team_config_sync ("{\"link_watch\": {\"name\": \"nsna_ping\", \"target_host\": \"target.host\"}}", - 0, 0, 0, 0, - "roundrobin", + -1, -1, -1, -1, + NULL, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, link_watchers); } @@ -1211,11 +1210,11 @@ test_watcher_arp_ping_sync_from_config (void) nm_team_link_watcher_new_arp_ping (0, 0, 3, "target.host", "source.host", 0, NULL)); _test_team_config_sync ("{\"link_watch\": {\"name\": \"arp_ping\", \"target_host\": \"target.host\", " "\"source_host\": \"source.host\"}}", - 0, 0, 0, 0, - "roundrobin", + -1, -1, -1, -1, + NULL, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, link_watchers); } @@ -1240,11 +1239,11 @@ test_multiple_watchers_sync_from_config (void) "\"validate_active\": true, \"validate_inactive\": true, \"send_always\": true}, " "{\"name\": \"nsna_ping\", \"init_wait\": 3, \"interval\": 6, \"missed_max\": 9, " "\"target_host\": \"target.host\"}]}", - 0, 0, 0, 0, - "roundrobin", + -1, -1, -1, -1, + NULL, NULL, NULL, NULL, -1, - FALSE, FALSE, -1, -1, NULL, + TRUE, FALSE, -1, -1, NULL, link_watchers); } @@ -1300,52 +1299,52 @@ _test_team_port_config_sync (const char *team_port_config, static void test_team_port_default (void) { - _test_team_port_config_sync ("", -1, 0, FALSE, 255, 0, NULL); + _test_team_port_config_sync ("", -1, 0, FALSE, -1, -1, NULL); } static void test_team_port_queue_id (void) { _test_team_port_config_sync ("{\"queue_id\": 3}", - 3, 0, FALSE, 255, 0, NULL); + 3, 0, FALSE, -1, -1, NULL); _test_team_port_config_sync ("{\"queue_id\": 0}", - 0, 0, FALSE, 255, 0, NULL); + 0, 0, FALSE, -1, -1, NULL); } static void test_team_port_prio (void) { _test_team_port_config_sync ("{\"prio\": 6}", - -1, 6, FALSE, 255, 0, NULL); + -1, 6, FALSE, -1, -1, NULL); _test_team_port_config_sync ("{\"prio\": 0}", - -1, 0, FALSE, 255, 0, NULL); + -1, 0, FALSE, -1, -1, NULL); } static void test_team_port_sticky (void) { _test_team_port_config_sync ("{\"sticky\": true}", - -1, 0, TRUE, 255, 0, NULL); + -1, 0, TRUE, -1, -1, NULL); _test_team_port_config_sync ("{\"sticky\": false}", - -1, 0, FALSE, 255, 0, NULL); + -1, 0, FALSE, -1, -1, NULL); } static void test_team_port_lacp_prio (void) { _test_team_port_config_sync ("{\"lacp_prio\": 9}", - -1, 0, FALSE, 9, 0, NULL); + -1, 0, FALSE, 9, -1, NULL); _test_team_port_config_sync ("{\"lacp_prio\": 0}", - -1, 0, FALSE, 0, 0, NULL); + -1, 0, FALSE, 0, -1, NULL); } static void test_team_port_lacp_key (void) { _test_team_port_config_sync ("{\"lacp_key\": 12}", - -1, 0, FALSE, 255, 12, NULL); + -1, 0, FALSE, -1, 12, NULL); _test_team_port_config_sync ("{\"lacp_key\": 0}", - -1, 0, FALSE, 255, 0, NULL); + -1, 0, FALSE, -1, 0, NULL); } static void @@ -1386,20 +1385,6 @@ _check_team_setting (NMSetting *setting) g_assert (NM_IS_SETTING_TEAM (setting) || is_port); - setting_clone = nm_setting_duplicate (setting); - - if (!is_port) { - if (nm_setting_team_get_runner (NM_SETTING_TEAM (setting)) == NULL) { - /* such a setting is invalid. We must first coerce it so that it becomes - * valid. */ - setting = setting_clone; - g_object_set (setting, - NM_SETTING_TEAM_RUNNER, - NM_SETTING_TEAM_RUNNER_DEFAULT, - NULL); - } - } - setting2 = g_object_new (G_OBJECT_TYPE (setting), is_port ? NM_SETTING_TEAM_PORT_CONFIG @@ -1420,6 +1405,7 @@ _check_team_setting (NMSetting *setting) * For that, we have to "drop" the JSON and we do that by resetting the property. * This causes JSON to be regenerated and it's in a normalized form that will compare * equal. */ + setting_clone = nm_setting_duplicate (setting); setting = setting_clone; if (is_port) { g_object_set (setting, @@ -1469,7 +1455,7 @@ test_team_setting (void) _check_team_setting (setting); g_assert_cmpint (nm_setting_team_get_num_link_watchers (NM_SETTING_TEAM (setting)), ==, 1); - g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"ethtool\"} }"); + g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"ethtool\" } }"); nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0); @@ -1479,11 +1465,11 @@ test_team_setting (void) nm_setting_team_add_link_watcher (NM_SETTING_TEAM (setting), watcher1); _check_team_setting (setting); - g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"nsna_ping\", \"target_host\": \"bbb\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4} }"); + g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": { \"name\": \"nsna_ping\", \"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" } }"); nm_setting_team_add_link_watcher (NM_SETTING_TEAM (setting), watcher2); _check_team_setting (setting); - g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": [ { \"name\": \"nsna_ping\", \"target_host\": \"bbb\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4}, { \"name\": \"arp_ping\", \"target_host\": \"ccc\", \"source_host\": \"ddd\", \"init_wait\": 1, \"interval\": 3, \"missed_max\": 4} ] }"); + g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"sys_prio\": 10 }, \"link_watch\": [ { \"name\": \"nsna_ping\", \"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"target_host\": \"bbb\" }, { \"name\": \"arp_ping\", \"interval\": 3, \"init_wait\": 1, \"missed_max\": 4, \"source_host\": \"ddd\", \"target_host\": \"ccc\" } ] }"); nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0); nm_setting_team_remove_link_watcher (NM_SETTING_TEAM (setting), 0); @@ -1499,6 +1485,12 @@ test_team_setting (void) NULL); _check_team_setting (setting); g_assert_cmpstr (nm_setting_team_get_config (NM_SETTING_TEAM (setting)), ==, "{ \"runner\": { \"tx_balancer\": { \"balancing_interval\": 5 }, \"sys_prio\": 10 } }"); + + g_object_set (setting, + NM_SETTING_TEAM_CONFIG, + "{ \"runner\": { \"tx_hash\": [ \"eth\", \"l3\" ] } }", + NULL); + _check_team_setting (setting); } /*****************************************************************************/