/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2011 - 2017 Red Hat, Inc. */ #include "nm-default.h" #include "nm-setting-bridge.h" #include #include #include #include "nm-glib-aux/nm-str-buf.h" #include "nm-connection-private.h" #include "nm-utils.h" #include "nm-utils-private.h" /** * SECTION:nm-setting-bridge * @short_description: Describes connection properties for bridges * * The #NMSettingBridge object is a #NMSetting subclass that describes properties * necessary for bridging connections. **/ /*****************************************************************************/ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingBridge, PROP_MAC_ADDRESS, PROP_STP, PROP_PRIORITY, PROP_FORWARD_DELAY, PROP_HELLO_TIME, PROP_MAX_AGE, PROP_AGEING_TIME, PROP_GROUP_ADDRESS, PROP_GROUP_FORWARD_MASK, PROP_MULTICAST_HASH_MAX, PROP_MULTICAST_LAST_MEMBER_COUNT, PROP_MULTICAST_LAST_MEMBER_INTERVAL, PROP_MULTICAST_MEMBERSHIP_INTERVAL, PROP_MULTICAST_ROUTER, PROP_MULTICAST_QUERIER, PROP_MULTICAST_QUERIER_INTERVAL, PROP_MULTICAST_QUERY_INTERVAL, PROP_MULTICAST_QUERY_RESPONSE_INTERVAL, PROP_MULTICAST_QUERY_USE_IFADDR, PROP_MULTICAST_SNOOPING, PROP_MULTICAST_STARTUP_QUERY_COUNT, PROP_MULTICAST_STARTUP_QUERY_INTERVAL, PROP_VLAN_FILTERING, PROP_VLAN_DEFAULT_PVID, PROP_VLAN_PROTOCOL, PROP_VLAN_STATS_ENABLED, PROP_VLANS, ); typedef struct { GPtrArray *vlans; char * mac_address; char * multicast_router; char * group_address; char * vlan_protocol; guint64 multicast_last_member_interval; guint64 multicast_membership_interval; guint64 multicast_querier_interval; guint64 multicast_query_interval; guint64 multicast_query_response_interval; guint64 multicast_startup_query_interval; guint32 ageing_time; guint32 multicast_hash_max; guint32 multicast_last_member_count; guint32 multicast_startup_query_count; guint16 priority; guint16 forward_delay; guint16 hello_time; guint16 max_age; guint16 vlan_default_pvid; guint16 group_forward_mask; bool multicast_snooping : 1; bool vlan_filtering : 1; bool stp : 1; bool vlan_stats_enabled : 1; bool multicast_query_use_ifaddr : 1; bool multicast_querier : 1; } NMSettingBridgePrivate; /** * NMSettingBridge: * * Bridging Settings */ struct _NMSettingBridge { NMSetting parent; NMSettingBridgePrivate _priv; }; struct _NMSettingBridgeClass { NMSettingClass parent; }; G_DEFINE_TYPE(NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) #define NM_SETTING_BRIDGE_GET_PRIVATE(self) \ _NM_GET_PRIVATE(self, NMSettingBridge, NM_IS_SETTING_BRIDGE, NMSetting) /*****************************************************************************/ G_DEFINE_BOXED_TYPE(NMBridgeVlan, nm_bridge_vlan, _nm_bridge_vlan_dup, nm_bridge_vlan_unref) struct _NMBridgeVlan { guint refcount; guint16 vid_start; guint16 vid_end; bool untagged : 1; bool pvid : 1; bool sealed : 1; }; static gboolean NM_IS_BRIDGE_VLAN(const NMBridgeVlan *self, gboolean also_sealed) { return self && self->refcount > 0 && (also_sealed || !self->sealed); } /** * nm_bridge_vlan_new: * @vid_start: the start VLAN id, must be between 1 and 4094. * @vid_end: the end VLAN id, must be 0 or between @vid_start and 4094. * * Creates a new #NMBridgeVlan object for the given VLAN id range. * Setting @vid_end to 0 is equivalent to setting it to @vid_start * and creates a single-id VLAN. * * Returns: (transfer full): the new #NMBridgeVlan object. * * Since: 1.18 **/ NMBridgeVlan * nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end) { NMBridgeVlan *vlan; if (vid_end == 0) vid_end = vid_start; g_return_val_if_fail(vid_start >= NM_BRIDGE_VLAN_VID_MIN, NULL); g_return_val_if_fail(vid_end <= NM_BRIDGE_VLAN_VID_MAX, NULL); g_return_val_if_fail(vid_start <= vid_end, NULL); vlan = g_slice_new0(NMBridgeVlan); vlan->refcount = 1; vlan->vid_start = vid_start; vlan->vid_end = vid_end; return vlan; } /** * nm_bridge_vlan_ref: * @vlan: the #NMBridgeVlan * * Increases the reference count of the object. * * Returns: the input argument @vlan object. * * Since: 1.18 **/ NMBridgeVlan * nm_bridge_vlan_ref(NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); nm_assert(vlan->refcount < G_MAXUINT); vlan->refcount++; return vlan; } /** * nm_bridge_vlan_unref: * @vlan: the #NMBridgeVlan * * Decreases the reference count of the object. If the reference count * reaches zero the object will be destroyed. * * Since: 1.18 **/ void nm_bridge_vlan_unref(NMBridgeVlan *vlan) { g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); if (--vlan->refcount == 0) g_slice_free(NMBridgeVlan, vlan); } /** * nm_bridge_vlan_cmp: * @a: a #NMBridgeVlan * @b: another #NMBridgeVlan * * Compare two bridge VLAN objects. * * Returns: zero of the two instances are equivalent or * a non-zero integer otherwise. This defines a total ordering * over the VLANs. Whether a VLAN is sealed or not does not * affect the comparison. * * Since: 1.18 **/ int nm_bridge_vlan_cmp(const NMBridgeVlan *a, const NMBridgeVlan *b) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(a, TRUE), 0); g_return_val_if_fail(NM_IS_BRIDGE_VLAN(b, TRUE), 0); NM_CMP_SELF(a, b); NM_CMP_FIELD(a, b, vid_start); NM_CMP_FIELD(a, b, vid_end); NM_CMP_FIELD_BOOL(a, b, untagged); NM_CMP_FIELD_BOOL(a, b, pvid); return 0; } NMBridgeVlan * _nm_bridge_vlan_dup(const NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); if (vlan->sealed) { nm_bridge_vlan_ref((NMBridgeVlan *) vlan); return (NMBridgeVlan *) vlan; } return nm_bridge_vlan_new_clone(vlan); } NMBridgeVlan * _nm_bridge_vlan_dup_and_seal(const NMBridgeVlan *vlan) { NMBridgeVlan *new; g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); new = _nm_bridge_vlan_dup(vlan); nm_bridge_vlan_seal(new); return new; } /** * nm_bridge_vlan_get_vid_range: * @vlan: the #NMBridgeVlan * @vid_start: (out): location to store the VLAN id range start. * @vid_end: (out): location to store the VLAN id range end * * Gets the VLAN id range. * * Returns: %TRUE is the VLAN specifies a range, %FALSE if it is * a single-id VLAN. * * Since: 1.18 **/ gboolean nm_bridge_vlan_get_vid_range(const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end) { /* with LTO and optimization, the compiler complains that the * output variables are not initialized. In practice, the function * only sets the output on success. But make the compiler happy. */ NM_SET_OUT(vid_start, 0); NM_SET_OUT(vid_end, 0); g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), 0); NM_SET_OUT(vid_start, vlan->vid_start); NM_SET_OUT(vid_end, vlan->vid_end); return vlan->vid_start != vlan->vid_end; } /** * nm_bridge_vlan_is_untagged: * @vlan: the #NMBridgeVlan * * Returns whether the VLAN is untagged. * * Returns: %TRUE if the VLAN is untagged, %FALSE otherwise * * Since: 1.18 **/ gboolean nm_bridge_vlan_is_untagged(const NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); return vlan->untagged; } /** * nm_bridge_vlan_is_pvid: * @vlan: the #NMBridgeVlan * * Returns whether the VLAN is the PVID for the port. * * Returns: %TRUE if the VLAN is the PVID * * Since: 1.18 **/ gboolean nm_bridge_vlan_is_pvid(const NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); return vlan->pvid; } /** * nm_bridge_vlan_set_untagged: * @vlan: the #NMBridgeVlan * @value: the new value * * Change the value of the untagged property of the VLAN. * * Since: 1.18 **/ void nm_bridge_vlan_set_untagged(NMBridgeVlan *vlan, gboolean value) { g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); vlan->untagged = value; } /** * nm_bridge_vlan_set_pvid: * @vlan: the #NMBridgeVlan * @value: the new value * * Change the value of the PVID property of the VLAN. It * is invalid to set the value to %TRUE for non-single-id * VLANs. * * Since: 1.18 **/ void nm_bridge_vlan_set_pvid(NMBridgeVlan *vlan, gboolean value) { g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, FALSE)); g_return_if_fail(!value || vlan->vid_start == vlan->vid_end); vlan->pvid = value; } /** * nm_bridge_vlan_is_sealed: * @vlan: the #NMBridgeVlan instance * * Returns: whether @self is sealed or not. * * Since: 1.18 */ gboolean nm_bridge_vlan_is_sealed(const NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), FALSE); return vlan->sealed; } /** * nm_bridge_vlan_seal: * @vlan: the #NMBridgeVlan instance * * Seal the #NMBridgeVlan instance. Afterwards, it is a bug * to call all functions that modify the instance (except ref/unref). * A sealed instance cannot be unsealed again, but you can create * an unsealed copy with nm_bridge_vlan_new_clone(). * * Since: 1.18 */ void nm_bridge_vlan_seal(NMBridgeVlan *vlan) { g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); vlan->sealed = TRUE; } /** * nm_bridge_vlan_new_clone: * @vlan: the #NMBridgeVlan instance to copy * * Returns: (transfer full): a clone of @vlan. This instance * is always unsealed. * * Since: 1.18 */ NMBridgeVlan * nm_bridge_vlan_new_clone(const NMBridgeVlan *vlan) { NMBridgeVlan *copy; g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); copy = nm_bridge_vlan_new(vlan->vid_start, vlan->vid_end); copy->untagged = vlan->untagged; copy->pvid = vlan->pvid; return copy; } /** * nm_bridge_vlan_to_str: * @vlan: the %NMBridgeVlan * @error: location of the error * * Convert a %NMBridgeVlan to a string. * * Returns: formatted string or %NULL * * Since: 1.18 */ char * nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error) { NMStrBuf string; g_return_val_if_fail(vlan, NULL); g_return_val_if_fail(!error || !*error, NULL); /* The function never fails at the moment, but it might in the * future if more parameters are added to the object that could * make it invalid. */ nm_str_buf_init(&string, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); if (vlan->vid_start == vlan->vid_end) nm_str_buf_append_printf(&string, "%u", vlan->vid_start); else nm_str_buf_append_printf(&string, "%u-%u", vlan->vid_start, vlan->vid_end); if (nm_bridge_vlan_is_pvid(vlan)) nm_str_buf_append(&string, " pvid"); if (nm_bridge_vlan_is_untagged(vlan)) nm_str_buf_append(&string, " untagged"); return nm_str_buf_finalize(&string, NULL); } /** * nm_bridge_vlan_from_str: * @str: the string representation of a bridge VLAN * @error: location of the error * * Parses the string representation of the queueing * discipline to a %NMBridgeVlan instance. * * Returns: the %NMBridgeVlan or %NULL * * Since: 1.18 */ NMBridgeVlan * nm_bridge_vlan_from_str(const char *str, GError **error) { NMBridgeVlan * vlan = NULL; gs_free const char **tokens = NULL; guint i, vid_start, vid_end = 0; gboolean pvid = FALSE; gboolean untagged = FALSE; char * c; g_return_val_if_fail(str, NULL); g_return_val_if_fail(!error || !*error, NULL); tokens = nm_utils_escaped_tokens_split(str, NM_ASCII_SPACES); if (!tokens || !tokens[0]) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "missing VLAN id"); return NULL; } c = strchr(tokens[0], '-'); if (c) *c = '\0'; vid_start = _nm_utils_ascii_str_to_uint64(tokens[0], 10, NM_BRIDGE_VLAN_VID_MIN, NM_BRIDGE_VLAN_VID_MAX, G_MAXUINT); if (vid_start == G_MAXUINT) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "invalid VLAN id range start '%s', must be in [1,4094]", tokens[0]); return NULL; } if (c) { vid_end = _nm_utils_ascii_str_to_uint64(c + 1, 10, NM_BRIDGE_VLAN_VID_MIN, NM_BRIDGE_VLAN_VID_MAX, G_MAXUINT); if (vid_end == G_MAXUINT) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "invalid VLAN id range end '%s', must be in [1,4094]", c + 1); return NULL; } if (vid_end < vid_start) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "invalid VLAN id range %u-%u, start VLAN id must be less than end VLAN id", vid_start, vid_end); return NULL; } } else vid_end = vid_start; for (i = 1; tokens[i]; i++) { if (nm_streq(tokens[i], "pvid")) { if (vid_start != vid_end) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "a VLAN range can't be a PVID"); return NULL; } pvid = TRUE; } else if (nm_streq(tokens[i], "untagged")) untagged = TRUE; else { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, "invalid option '%s'", tokens[i]); return NULL; } } vlan = nm_bridge_vlan_new(vid_start, vid_end); nm_bridge_vlan_set_pvid(vlan, pvid); nm_bridge_vlan_set_untagged(vlan, untagged); return vlan; } /*****************************************************************************/ static int vlan_ptr_cmp(gconstpointer a, gconstpointer b) { const NMBridgeVlan *vlan_a = *(const NMBridgeVlan **) a; const NMBridgeVlan *vlan_b = *(const NMBridgeVlan **) b; return nm_bridge_vlan_cmp(vlan_a, vlan_b); } gboolean _nm_setting_bridge_sort_vlans(NMSettingBridge *setting) { NMSettingBridgePrivate *priv; gboolean need_sort = FALSE; guint i; priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); for (i = 1; i < priv->vlans->len; i++) { NMBridgeVlan *vlan_prev = priv->vlans->pdata[i - 1]; NMBridgeVlan *vlan = priv->vlans->pdata[i]; if (nm_bridge_vlan_cmp(vlan_prev, vlan) > 0) { need_sort = TRUE; break; } } if (need_sort) { g_ptr_array_sort(priv->vlans, vlan_ptr_cmp); _notify(setting, PROP_VLANS); } return need_sort; } /*****************************************************************************/ /** * nm_setting_bridge_get_mac_address: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:mac-address property of the setting **/ const char * nm_setting_bridge_get_mac_address(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->mac_address; } /** * nm_setting_bridge_get_stp: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:stp property of the setting **/ gboolean nm_setting_bridge_get_stp(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->stp; } /** * nm_setting_bridge_get_priority: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:priority property of the setting **/ guint16 nm_setting_bridge_get_priority(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->priority; } /** * nm_setting_bridge_get_forward_delay: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:forward-delay property of the setting **/ guint16 nm_setting_bridge_get_forward_delay(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->forward_delay; } /** * nm_setting_bridge_get_hello_time: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:hello-time property of the setting **/ guint16 nm_setting_bridge_get_hello_time(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->hello_time; } /** * nm_setting_bridge_get_max_age: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:max-age property of the setting **/ guint16 nm_setting_bridge_get_max_age(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->max_age; } /** * nm_setting_bridge_get_ageing_time: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:ageing-time property of the setting **/ guint nm_setting_bridge_get_ageing_time(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->ageing_time; } /** * nm_setting_bridge_get_group_forward_mask: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:group-forward-mask property of the setting * * Since: 1.10 **/ guint16 nm_setting_bridge_get_group_forward_mask(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_forward_mask; } /** * nm_setting_bridge_get_multicast_snooping: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-snooping property of the setting * * Since: 1.2 **/ gboolean nm_setting_bridge_get_multicast_snooping(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_snooping; } /** * nm_setting_bridge_get_vlan_filtering: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:vlan-filtering property of the setting * * Since: 1.18 **/ gboolean nm_setting_bridge_get_vlan_filtering(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_filtering; } /** * nm_setting_bridge_get_vlan_default_pvid: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:vlan-default-pvid property of the setting * * Since: 1.18 **/ guint16 nm_setting_bridge_get_vlan_default_pvid(NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 1); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_default_pvid; } /** * nm_setting_bridge_add_vlan: * @setting: the #NMSettingBridge * @vlan: the vlan to add * * Appends a new vlan and associated information to the setting. The * given vlan gets sealed and a reference to it is added. * * Since: 1.18 **/ void nm_setting_bridge_add_vlan(NMSettingBridge *setting, NMBridgeVlan *vlan) { NMSettingBridgePrivate *priv; g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); g_return_if_fail(vlan); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); nm_bridge_vlan_seal(vlan); nm_bridge_vlan_ref(vlan); g_ptr_array_add(priv->vlans, vlan); _notify(setting, PROP_VLANS); } /** * nm_setting_bridge_get_num_vlans: * @setting: the #NMSettingBridge * * Returns: the number of VLANs * * Since: 1.18 **/ guint nm_setting_bridge_get_num_vlans(NMSettingBridge *setting) { NMSettingBridgePrivate *priv; g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); return priv->vlans->len; } /** * nm_setting_bridge_get_vlan: * @setting: the #NMSettingBridge * @idx: index number of the VLAN to return * * Returns: (transfer none): the VLAN at index @idx * * Since: 1.18 **/ NMBridgeVlan * nm_setting_bridge_get_vlan(NMSettingBridge *setting, guint idx) { NMSettingBridgePrivate *priv; g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); g_return_val_if_fail(idx < priv->vlans->len, NULL); return priv->vlans->pdata[idx]; } /** * nm_setting_bridge_remove_vlan: * @setting: the #NMSettingBridge * @idx: index number of the VLAN. * * Removes the vlan at index @idx. * * Since: 1.18 **/ void nm_setting_bridge_remove_vlan(NMSettingBridge *setting, guint idx) { NMSettingBridgePrivate *priv; g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); g_return_if_fail(idx < priv->vlans->len); g_ptr_array_remove_index(priv->vlans, idx); _notify(setting, PROP_VLANS); } /** * nm_setting_bridge_remove_vlan_by_vid: * @setting: the #NMSettingBridge * @vid_start: the vlan start index * @vid_end: the vlan end index * * Remove the VLAN with range @vid_start to @vid_end. * If @vid_end is zero, it is assumed to be equal to @vid_start * and so the single-id VLAN with id @vid_start is removed. * * Returns: %TRUE if the vlan was found and removed; %FALSE otherwise * * Since: 1.18 **/ gboolean nm_setting_bridge_remove_vlan_by_vid(NMSettingBridge *setting, guint16 vid_start, guint16 vid_end) { NMSettingBridgePrivate *priv; NMBridgeVlan * vlan; guint i; g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); if (vid_end == 0) vid_end = vid_start; for (i = 0; i < priv->vlans->len; i++) { vlan = (NMBridgeVlan *) priv->vlans->pdata[i]; if (vlan->vid_start == vid_start && vlan->vid_end == vid_end) { g_ptr_array_remove_index(priv->vlans, i); _notify(setting, PROP_VLANS); return TRUE; } } return FALSE; } /** * nm_setting_bridge_clear_vlans: * @setting: the #NMSettingBridge * * Removes all configured VLANs. * * Since: 1.18 **/ void nm_setting_bridge_clear_vlans(NMSettingBridge *setting) { NMSettingBridgePrivate *priv; g_return_if_fail(NM_IS_SETTING_BRIDGE(setting)); priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); if (priv->vlans->len != 0) { g_ptr_array_set_size(priv->vlans, 0); _notify(setting, PROP_VLANS); } } /** * nm_setting_bridge_get_group_address: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:group-address property of the setting * * Since 1.24 **/ const char * nm_setting_bridge_get_group_address(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->group_address; } /** * nm_setting_bridge_get_vlan_protocol: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:vlan-protocol property of the setting * * Since 1.24 **/ const char * nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_protocol; } /** * nm_setting_bridge_get_vlan_stats_enabled: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting * * Since 1.24 **/ gboolean nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->vlan_stats_enabled; } /** * nm_setting_bridge_get_multicast_router: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-router property of the setting * * Since 1.24 **/ const char * nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), NULL); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_router; } /** * nm_setting_bridge_get_multicast_query_use_ifaddr: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting * * Since 1.24 **/ gboolean nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_use_ifaddr; } /** * nm_setting_bridge_get_multicast_querier: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-querier property of the setting * * Since 1.24 **/ gboolean nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), FALSE); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier; } /** * nm_setting_bridge_get_multicast_hash_max: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-hash-max property of the setting * * Since 1.26 **/ guint32 nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_hash_max; } /** * nm_setting_bridge_get_multicast_last_member_count: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-last-member-count property of the setting * * Since 1.26 **/ guint32 nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_count; } /** * nm_setting_bridge_get_multicast_last_member_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-last-member-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_last_member_interval; } /** * nm_setting_bridge_get_multicast_membership_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-membership-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_membership_interval; } /** * nm_setting_bridge_get_multicast_querier_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-querier-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_querier_interval; } /** * nm_setting_bridge_get_multicast_query_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-query-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_interval; } /** * nm_setting_bridge_get_multicast_query_response_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_query_response_interval; } /** * nm_setting_bridge_get_multicast_startup_query_count: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting * * Since 1.26 **/ guint32 nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_count; } /** * nm_setting_bridge_get_multicast_startup_query_interval: * @setting: the #NMSettingBridge * * Returns: the #NMSettingBridge:multicast-startup-query-interval property of the setting * * Since 1.26 **/ guint64 nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting) { g_return_val_if_fail(NM_IS_SETTING_BRIDGE(setting), 0); return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->multicast_startup_query_interval; } /*****************************************************************************/ static gboolean check_range(guint32 val, guint32 min, guint32 max, gboolean zero, const char *prop, GError **error) { if (zero && val == 0) return TRUE; if (val < min || val > max) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("value '%d' is out of range <%d-%d>"), val, min, max); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop); return FALSE; } return TRUE; } static gboolean verify(NMSetting *setting, NMConnection *connection, GError **error) { NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); if (priv->mac_address && !nm_utils_hwaddr_valid(priv->mac_address, ETH_ALEN)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("is not a valid MAC address")); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MAC_ADDRESS); return FALSE; } if (!check_range(priv->forward_delay, NM_BRIDGE_FORWARD_DELAY_MIN, NM_BRIDGE_FORWARD_DELAY_MAX, !priv->stp, NM_SETTING_BRIDGE_FORWARD_DELAY, error)) return FALSE; if (!check_range(priv->hello_time, NM_BRIDGE_HELLO_TIME_MIN, NM_BRIDGE_HELLO_TIME_MAX, !priv->stp, NM_SETTING_BRIDGE_HELLO_TIME, error)) return FALSE; if (!check_range(priv->max_age, NM_BRIDGE_MAX_AGE_MIN, NM_BRIDGE_MAX_AGE_MAX, !priv->stp, NM_SETTING_BRIDGE_MAX_AGE, error)) return FALSE; if (!check_range(priv->ageing_time, NM_BRIDGE_AGEING_TIME_MIN, NM_BRIDGE_AGEING_TIME_MAX, !priv->stp, NM_SETTING_BRIDGE_AGEING_TIME, error)) return FALSE; if (priv->group_forward_mask & 7) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("the mask can't contain bits 0 (STP), 1 (MAC) or 2 (LACP)")); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_GROUP_FORWARD_MASK); return FALSE; } if (!_nm_connection_verify_required_interface_name(connection, error)) return FALSE; if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, FALSE, error, NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_VLANS)) return FALSE; if (priv->group_address && !_nm_utils_hwaddr_link_local_valid(priv->group_address)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("is not a valid link local MAC address")); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_GROUP_ADDRESS); return FALSE; } if (priv->vlan_protocol && !NM_IN_STRSET(priv->vlan_protocol, "802.1Q", "802.1ad")) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("is not a valid VLAN filtering protocol")); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_VLAN_PROTOCOL); return FALSE; } if (!NM_IN_STRSET(priv->multicast_router, NULL, "auto", "enabled", "disabled")) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("is not a valid option")); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_ROUTER); return FALSE; } if (!nm_utils_is_power_of_two(priv->multicast_hash_max)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option must be a power of 2"), NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); g_prefix_error(error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MULTICAST_HASH_MAX); return FALSE; } /* Failures from here on are NORMALIZABLE... */ if (!_nm_utils_bridge_vlan_verify_list(priv->vlans, TRUE, error, NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_VLANS)) return NM_SETTING_VERIFY_NORMALIZABLE; return TRUE; } static NMTernary compare_property(const NMSettInfoSetting *sett_info, guint property_idx, NMConnection * con_a, NMSetting * set_a, NMConnection * con_b, NMSetting * set_b, NMSettingCompareFlags flags) { NMSettingBridgePrivate *priv_a; NMSettingBridgePrivate *priv_b; guint i; if (nm_streq(sett_info->property_infos[property_idx].name, NM_SETTING_BRIDGE_VLANS)) { if (set_b) { priv_a = NM_SETTING_BRIDGE_GET_PRIVATE(set_a); priv_b = NM_SETTING_BRIDGE_GET_PRIVATE(set_b); if (priv_a->vlans->len != priv_b->vlans->len) return FALSE; for (i = 0; i < priv_a->vlans->len; i++) { if (nm_bridge_vlan_cmp(priv_a->vlans->pdata[i], priv_b->vlans->pdata[i])) return FALSE; } } return TRUE; } return NM_SETTING_CLASS(nm_setting_bridge_parent_class) ->compare_property(sett_info, property_idx, con_a, set_a, con_b, set_b, flags); } /*****************************************************************************/ static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); NMSettingBridge * setting = NM_SETTING_BRIDGE(object); switch (prop_id) { case PROP_MAC_ADDRESS: g_value_set_string(value, nm_setting_bridge_get_mac_address(setting)); break; case PROP_STP: g_value_set_boolean(value, priv->stp); break; case PROP_PRIORITY: g_value_set_uint(value, priv->priority); break; case PROP_FORWARD_DELAY: g_value_set_uint(value, priv->forward_delay); break; case PROP_HELLO_TIME: g_value_set_uint(value, priv->hello_time); break; case PROP_MAX_AGE: g_value_set_uint(value, priv->max_age); break; case PROP_AGEING_TIME: g_value_set_uint(value, priv->ageing_time); break; case PROP_GROUP_ADDRESS: g_value_set_string(value, priv->group_address); break; case PROP_GROUP_FORWARD_MASK: g_value_set_uint(value, priv->group_forward_mask); break; case PROP_MULTICAST_HASH_MAX: g_value_set_uint(value, priv->multicast_hash_max); break; case PROP_MULTICAST_LAST_MEMBER_COUNT: g_value_set_uint(value, priv->multicast_last_member_count); break; case PROP_MULTICAST_LAST_MEMBER_INTERVAL: g_value_set_uint64(value, priv->multicast_last_member_interval); break; case PROP_MULTICAST_MEMBERSHIP_INTERVAL: g_value_set_uint64(value, priv->multicast_membership_interval); break; case PROP_MULTICAST_SNOOPING: g_value_set_boolean(value, priv->multicast_snooping); break; case PROP_MULTICAST_ROUTER: g_value_set_string(value, priv->multicast_router); break; case PROP_MULTICAST_QUERIER: g_value_set_boolean(value, priv->multicast_querier); break; case PROP_MULTICAST_QUERIER_INTERVAL: g_value_set_uint64(value, priv->multicast_querier_interval); break; case PROP_MULTICAST_QUERY_INTERVAL: g_value_set_uint64(value, priv->multicast_query_interval); break; case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: g_value_set_uint64(value, priv->multicast_query_response_interval); break; case PROP_MULTICAST_QUERY_USE_IFADDR: g_value_set_boolean(value, priv->multicast_query_use_ifaddr); break; case PROP_MULTICAST_STARTUP_QUERY_COUNT: g_value_set_uint(value, priv->multicast_startup_query_count); break; case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: g_value_set_uint64(value, priv->multicast_startup_query_interval); break; case PROP_VLAN_FILTERING: g_value_set_boolean(value, priv->vlan_filtering); break; case PROP_VLAN_DEFAULT_PVID: g_value_set_uint(value, priv->vlan_default_pvid); break; case PROP_VLAN_PROTOCOL: g_value_set_string(value, priv->vlan_protocol); break; case PROP_VLAN_STATS_ENABLED: g_value_set_boolean(value, priv->vlan_stats_enabled); break; case PROP_VLANS: g_value_take_boxed(value, _nm_utils_copy_array(priv->vlans, (NMUtilsCopyFunc) nm_bridge_vlan_ref, (GDestroyNotify) nm_bridge_vlan_unref)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); switch (prop_id) { case PROP_MAC_ADDRESS: g_free(priv->mac_address); priv->mac_address = _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); break; case PROP_STP: priv->stp = g_value_get_boolean(value); break; case PROP_PRIORITY: priv->priority = (guint16) g_value_get_uint(value); break; case PROP_FORWARD_DELAY: priv->forward_delay = (guint16) g_value_get_uint(value); break; case PROP_HELLO_TIME: priv->hello_time = (guint16) g_value_get_uint(value); break; case PROP_MAX_AGE: priv->max_age = (guint16) g_value_get_uint(value); break; case PROP_AGEING_TIME: priv->ageing_time = g_value_get_uint(value); break; case PROP_GROUP_ADDRESS: g_free(priv->group_address); priv->group_address = _nm_utils_hwaddr_canonical_or_invalid(g_value_get_string(value), ETH_ALEN); break; case PROP_GROUP_FORWARD_MASK: priv->group_forward_mask = (guint16) g_value_get_uint(value); break; case PROP_MULTICAST_HASH_MAX: priv->multicast_hash_max = g_value_get_uint(value); break; case PROP_MULTICAST_LAST_MEMBER_COUNT: priv->multicast_last_member_count = g_value_get_uint(value); break; case PROP_MULTICAST_LAST_MEMBER_INTERVAL: priv->multicast_last_member_interval = g_value_get_uint64(value); break; case PROP_MULTICAST_MEMBERSHIP_INTERVAL: priv->multicast_membership_interval = g_value_get_uint64(value); break; case PROP_MULTICAST_SNOOPING: priv->multicast_snooping = g_value_get_boolean(value); break; case PROP_MULTICAST_ROUTER: g_free(priv->multicast_router); priv->multicast_router = g_value_dup_string(value); break; case PROP_MULTICAST_QUERIER: priv->multicast_querier = g_value_get_boolean(value); break; case PROP_MULTICAST_QUERIER_INTERVAL: priv->multicast_querier_interval = g_value_get_uint64(value); break; case PROP_MULTICAST_QUERY_INTERVAL: priv->multicast_query_interval = g_value_get_uint64(value); break; case PROP_MULTICAST_QUERY_RESPONSE_INTERVAL: priv->multicast_query_response_interval = g_value_get_uint64(value); break; case PROP_MULTICAST_QUERY_USE_IFADDR: priv->multicast_query_use_ifaddr = g_value_get_boolean(value); break; case PROP_MULTICAST_STARTUP_QUERY_COUNT: priv->multicast_startup_query_count = g_value_get_uint(value); break; case PROP_MULTICAST_STARTUP_QUERY_INTERVAL: priv->multicast_startup_query_interval = g_value_get_uint64(value); break; case PROP_VLAN_FILTERING: priv->vlan_filtering = g_value_get_boolean(value); break; case PROP_VLAN_DEFAULT_PVID: priv->vlan_default_pvid = g_value_get_uint(value); break; case PROP_VLAN_PROTOCOL: g_free(priv->vlan_protocol); priv->vlan_protocol = g_value_dup_string(value); break; case PROP_VLAN_STATS_ENABLED: priv->vlan_stats_enabled = g_value_get_boolean(value); break; case PROP_VLANS: g_ptr_array_unref(priv->vlans); priv->vlans = _nm_utils_copy_array(g_value_get_boxed(value), (NMUtilsCopyFunc) _nm_bridge_vlan_dup_and_seal, (GDestroyNotify) nm_bridge_vlan_unref); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /*****************************************************************************/ static void nm_setting_bridge_init(NMSettingBridge *setting) { NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(setting); priv->vlans = g_ptr_array_new_with_free_func((GDestroyNotify) nm_bridge_vlan_unref); priv->ageing_time = NM_BRIDGE_AGEING_TIME_DEF; priv->forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF; priv->hello_time = NM_BRIDGE_HELLO_TIME_DEF; priv->max_age = NM_BRIDGE_MAX_AGE_DEF; priv->multicast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF; priv->multicast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF; priv->multicast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF; priv->multicast_hash_max = NM_BRIDGE_MULTICAST_HASH_MAX_DEF; priv->multicast_snooping = NM_BRIDGE_MULTICAST_SNOOPING_DEF; priv->priority = NM_BRIDGE_PRIORITY_DEF; priv->stp = NM_BRIDGE_STP_DEF; priv->vlan_default_pvid = NM_BRIDGE_VLAN_DEFAULT_PVID_DEF; priv->multicast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF; priv->multicast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF; priv->multicast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF; priv->multicast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF; priv->multicast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF; nm_assert(priv->multicast_querier == NM_BRIDGE_MULTICAST_QUERIER_DEF); nm_assert(priv->multicast_query_use_ifaddr == NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF); nm_assert(priv->vlan_stats_enabled == NM_BRIDGE_VLAN_STATS_ENABLED_DEF); } /** * nm_setting_bridge_new: * * Creates a new #NMSettingBridge object with default values. * * Returns: (transfer full): the new empty #NMSettingBridge object **/ NMSetting * nm_setting_bridge_new(void) { return g_object_new(NM_TYPE_SETTING_BRIDGE, NULL); } static void finalize(GObject *object) { NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object); g_free(priv->mac_address); g_free(priv->multicast_router); g_free(priv->group_address); g_free(priv->vlan_protocol); g_ptr_array_unref(priv->vlans); G_OBJECT_CLASS(nm_setting_bridge_parent_class)->finalize(object); } static void nm_setting_bridge_class_init(NMSettingBridgeClass *klass) { GObjectClass * object_class = G_OBJECT_CLASS(klass); NMSettingClass *setting_class = NM_SETTING_CLASS(klass); GArray * properties_override = _nm_sett_info_property_override_create_array(); object_class->get_property = get_property; object_class->set_property = set_property; object_class->finalize = finalize; setting_class->compare_property = compare_property; setting_class->verify = verify; /** * NMSettingBridge:mac-address: * * If specified, the MAC address of bridge. When creating a new bridge, this * MAC address will be set. * * If this field is left unspecified, the "ethernet.cloned-mac-address" is * referred instead to generate the initial MAC address. Note that setting * "ethernet.cloned-mac-address" anyway overwrites the MAC address of * the bridge later while activating the bridge. Hence, this property * is deprecated. * * Deprecated: 1.12: Use the ethernet.cloned-mac-address property instead. **/ /* ---keyfile--- * property: mac-address * format: usual hex-digits-and-colons notation * description: MAC address in traditional hex-digits-and-colons notation, * or semicolon separated list of 6 decimal bytes (obsolete) * example: mac-address=00:22:68:12:79:A2 * mac-address=0;34;104;18;121;162; * ---end--- * ---ifcfg-rh--- * property: mac-address * variable: BRIDGE_MACADDR(+) * description: MAC address of the bridge. Note that this requires a recent * kernel support, originally introduced in 3.15 upstream kernel) * BRIDGE_MACADDR for bridges is an NM extension. * ---end--- */ obj_properties[PROP_MAC_ADDRESS] = g_param_spec_string( NM_SETTING_BRIDGE_MAC_ADDRESS, "", "", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj(properties_override, obj_properties[PROP_MAC_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingBridge:stp: * * Controls whether Spanning Tree Protocol (STP) is enabled for this bridge. **/ /* ---ifcfg-rh--- * property: stp * variable: STP * default: no * description: Span tree protocol participation. * ---end--- */ obj_properties[PROP_STP] = g_param_spec_boolean(NM_SETTING_BRIDGE_STP, "", "", NM_BRIDGE_STP_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:priority: * * Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower * values are "better"; the lowest priority bridge will be elected the root * bridge. **/ /* ---ifcfg-rh--- * property: priority * variable: BRIDGING_OPTS: priority= * values: 0 - 32768 * default: 32768 * description: STP priority. * ---end--- */ obj_properties[PROP_PRIORITY] = g_param_spec_uint(NM_SETTING_BRIDGE_PRIORITY, "", "", NM_BRIDGE_PRIORITY_MIN, NM_BRIDGE_PRIORITY_MAX, NM_BRIDGE_PRIORITY_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:forward-delay: * * The Spanning Tree Protocol (STP) forwarding delay, in seconds. **/ /* ---ifcfg-rh--- * property: forward-delay * variable: DELAY * values: 2 - 30 * default: 15 * description: STP forwarding delay. * ---end--- */ obj_properties[PROP_FORWARD_DELAY] = g_param_spec_uint(NM_SETTING_BRIDGE_FORWARD_DELAY, "", "", 0, NM_BRIDGE_FORWARD_DELAY_MAX, NM_BRIDGE_FORWARD_DELAY_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:hello-time: * * The Spanning Tree Protocol (STP) hello time, in seconds. **/ /* ---ifcfg-rh--- * property: hello-time * variable: BRIDGING_OPTS: hello_time= * values: 1 - 10 * default: 2 * description: STP hello time. * ---end--- */ obj_properties[PROP_HELLO_TIME] = g_param_spec_uint(NM_SETTING_BRIDGE_HELLO_TIME, "", "", 0, NM_BRIDGE_HELLO_TIME_MAX, NM_BRIDGE_HELLO_TIME_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:max-age: * * The Spanning Tree Protocol (STP) maximum message age, in seconds. **/ /* ---ifcfg-rh--- * property: max-age * variable: BRIDGING_OPTS: max_age= * values: 6 - 40 * default: 20 * description: STP maximum message age. * ---end--- */ obj_properties[PROP_MAX_AGE] = g_param_spec_uint(NM_SETTING_BRIDGE_MAX_AGE, "", "", 0, NM_BRIDGE_MAX_AGE_MAX, NM_BRIDGE_MAX_AGE_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:ageing-time: * * The Ethernet MAC address aging time, in seconds. **/ /* ---ifcfg-rh--- * property: ageing-time * variable: BRIDGING_OPTS: ageing_time= * values: 0 - 1000000 * default: 300 * description: Ethernet MAC ageing time. * ---end--- */ obj_properties[PROP_AGEING_TIME] = g_param_spec_uint(NM_SETTING_BRIDGE_AGEING_TIME, "", "", NM_BRIDGE_AGEING_TIME_MIN, NM_BRIDGE_AGEING_TIME_MAX, NM_BRIDGE_AGEING_TIME_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:group-forward-mask: * * A mask of group addresses to forward. Usually, group addresses in * the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not * forwarded according to standards. This property is a mask of 16 bits, * each corresponding to a group address in that range that must be * forwarded. The mask can't have bits 0, 1 or 2 set because they are * used for STP, MAC pause frames and LACP. * * Since: 1.10 **/ obj_properties[PROP_GROUP_FORWARD_MASK] = g_param_spec_uint(NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "", "", 0, 0xFFFF, 0, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-snooping: * * Controls whether IGMP snooping is enabled for this bridge. * Note that if snooping was automatically disabled due to hash collisions, * the system may refuse to enable the feature until the collisions are * resolved. * * Since: 1.2 **/ /* ---ifcfg-rh--- * property: multicast-snooping * variable: BRIDGING_OPTS: multicast_snooping= * values: 0 or 1 * default: 1 * description: IGMP snooping support. * ---end--- */ obj_properties[PROP_MULTICAST_SNOOPING] = g_param_spec_boolean( NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "", "", NM_BRIDGE_MULTICAST_SNOOPING_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:vlan-filtering: * * Control whether VLAN filtering is enabled on the bridge. * * Since: 1.18 **/ /* ---ifcfg-rh--- * property: vlan-filtering * variable: BRIDGING_OPTS: vlan_filtering= * values: 0 or 1 * default: 0 * description: VLAN filtering support. * ---end--- */ obj_properties[PROP_VLAN_FILTERING] = g_param_spec_boolean( NM_SETTING_BRIDGE_VLAN_FILTERING, "", "", FALSE, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:vlan-default-pvid: * * The default PVID for the ports of the bridge, that is the VLAN id * assigned to incoming untagged frames. * * Since: 1.18 **/ /* ---ifcfg-rh--- * property: vlan-default-pvid * variable: BRIDGING_OPTS: default_pvid= * values: 0 - 4094 * default: 1 * description: default VLAN PVID. * ---end--- */ obj_properties[PROP_VLAN_DEFAULT_PVID] = g_param_spec_uint(NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, "", "", 0, NM_BRIDGE_VLAN_VID_MAX, NM_BRIDGE_VLAN_DEFAULT_PVID_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:vlans: (type GPtrArray(NMBridgeVlan)) * * Array of bridge VLAN objects. In addition to the VLANs * specified here, the bridge will also have the default-pvid * VLAN configured by the bridge.vlan-default-pvid property. * * In nmcli the VLAN list can be specified with the following * syntax: * * $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... * * where $vid is either a single id between 1 and 4094 or a * range, represented as a couple of ids separated by a dash. * * Since: 1.18 **/ /* ---ifcfg-rh--- * property: vlans * variable: BRIDGE_VLANS * description: List of VLANs on the bridge * example: BRIDGE_VLANS="1 pvid untagged,20,300-400 untagged" * ---end--- */ obj_properties[PROP_VLANS] = g_param_spec_boxed(NM_SETTING_BRIDGE_VLANS, "", "", G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj(properties_override, obj_properties[PROP_VLANS], &nm_sett_info_propert_type_bridge_vlans); /* ---dbus--- * property: interface-name * format: string * description: Deprecated in favor of connection.interface-name, but can * be used for backward-compatibility with older daemons, to set the * bridge's interface name. * ---end--- */ _nm_properties_override_dbus(properties_override, "interface-name", &nm_sett_info_propert_type_deprecated_interface_name); /** * NMSettingBridge:group-address: * * If specified, The MAC address of the multicast group this bridge uses for STP. * * The address must be a link-local address in standard Ethernet MAC address format, * ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. * If not specified the default value is 01:80:C2:00:00:00. * * Since: 1.24 **/ /* ---ifcfg-rh--- * property: group-address * variable: BRIDGING_OPTS: group_address= * description: STP group address. * example: BRIDGING_OPTS="group_address=01:80:C2:00:00:0A" * ---end--- */ obj_properties[PROP_GROUP_ADDRESS] = g_param_spec_string( NM_SETTING_BRIDGE_GROUP_ADDRESS, "", "", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); _nm_properties_override_gobj(properties_override, obj_properties[PROP_GROUP_ADDRESS], &nm_sett_info_propert_type_mac_address); /** * NMSettingBridge:vlan-protocol: * * If specified, the protocol used for VLAN filtering. * * Supported values are: '802.1Q', '802.1ad'. * If not specified the default value is '802.1Q'. * * Since: 1.24 **/ /* ---ifcfg-rh--- * property: vlan-protocol * variable: BRIDGING_OPTS: vlan_protocol= * description: VLAN filtering protocol. * example: BRIDGING_OPTS="vlan_protocol=802.1Q" * ---end--- * * Since: 1.24 */ obj_properties[PROP_VLAN_PROTOCOL] = g_param_spec_string( NM_SETTING_BRIDGE_VLAN_PROTOCOL, "", "", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:vlan-stats-enabled: * * Controls whether per-VLAN stats accounting is enabled. **/ /* ---ifcfg-rh--- * property: vlan-stats-enabled * variable: BRIDGING_OPTS: vlan_stats_enabled= * default: 0 * example: BRIDGING_OPTS="vlan_stats_enabled=1" * ---end--- * * Since: 1.24 */ obj_properties[PROP_VLAN_STATS_ENABLED] = g_param_spec_boolean( NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, "", "", NM_BRIDGE_VLAN_STATS_ENABLED_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-router: * * Sets bridge's multicast router. Multicast-snooping must be enabled * for this option to work. * * Supported values are: 'auto', 'disabled', 'enabled' to which kernel * assigns the numbers 1, 0, and 2, respectively. * If not specified the default value is 'auto' (1). **/ /* ---ifcfg-rh--- * property: multicast-router * variable: BRIDGING_OPTS: multicast_router= * values: auto, enabled, disabled * default: auto * example: BRIDGING_OPTS="multicast_router=enabled" * ---end--- * * Since: 1.24 */ obj_properties[PROP_MULTICAST_ROUTER] = g_param_spec_string( NM_SETTING_BRIDGE_MULTICAST_ROUTER, "", "", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-query-use-ifaddr: * * If enabled the bridge's own IP address is used as * the source address for IGMP queries otherwise * the default of 0.0.0.0 is used. **/ /* ---ifcfg-rh--- * property: multicast-query-use-ifaddr * variable: BRIDGING_OPTS: multicast_query_use_ifaddr= * default: 0 * example: BRIDGING_OPTS="multicast_query-use_ifaddr=1" * ---end--- * * Since: 1.24 */ obj_properties[PROP_MULTICAST_QUERY_USE_IFADDR] = g_param_spec_boolean( NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, "", "", NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-querier: * * Enable or disable sending of multicast queries by the bridge. * If not specified the option is disabled. **/ /* ---ifcfg-rh--- * property: multicast-querier * variable: BRIDGING_OPTS: multicast_querier= * default: 0 * example: BRIDGING_OPTS="multicast_querier=1" * ---end--- * * Since: 1.24 */ obj_properties[PROP_MULTICAST_QUERIER] = g_param_spec_boolean( NM_SETTING_BRIDGE_MULTICAST_QUERIER, "", "", NM_BRIDGE_MULTICAST_QUERIER_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-hash-max: * * Set maximum size of multicast hash table (value must be a power of 2). **/ /* ---ifcfg-rh--- * property: multicast-hash-max * variable: BRIDGING_OPTS: multicast_hash_max= * default: 4096 * example: BRIDGING_OPTS="multicast_hash_max=8192" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_HASH_MAX] = g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, "", "", NM_BRIDGE_MULTICAST_HASH_MAX_MIN, NM_BRIDGE_MULTICAST_HASH_MAX_MAX, NM_BRIDGE_MULTICAST_HASH_MAX_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-last-member-count: * * Set the number of queries the bridge will send before * stopping forwarding a multicast group after a "leave" * message has been received. **/ /* ---ifcfg-rh--- * property: multicast-last-member-count * variable: BRIDGING_OPTS: multicast_last_member_count= * default: 2 * example: BRIDGING_OPTS="multicast_last_member_count=4" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_LAST_MEMBER_COUNT] = g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT, "", "", NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MIN, NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_MAX, NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-last-member-interval: * * Set interval (in deciseconds) between queries to find remaining * members of a group, after a "leave" message is received. **/ /* ---ifcfg-rh--- * property: multicast-last-member-interval * variable: BRIDGING_OPTS: multicast_last_member_interval= * default: 100 * example: BRIDGING_OPTS="multicast_last_member_interval=200" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_LAST_MEMBER_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL, "", "", NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MIN, NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_MAX, NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-membership-interval: * * Set delay (in deciseconds) after which the bridge will * leave a group, if no membership reports for this * group are received. **/ /* ---ifcfg-rh--- * property: multicast-membership-interval * variable: BRIDGING_OPTS: multicast_membership_interval= * default: 26000 * example: BRIDGING_OPTS="multicast_membership_interval=16000" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_MEMBERSHIP_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL, "", "", NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN, NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX, NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-querier-interval: * * If no queries are seen after this delay (in deciseconds) has passed, * the bridge will start to send its own queries. **/ /* ---ifcfg-rh--- * property: multicast-querier-interval * variable: BRIDGING_OPTS: multicast_querier_interval= * default: 25500 * example: BRIDGING_OPTS="multicast_querier_interval=20000" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_QUERIER_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL, "", "", NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN, NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX, NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-query-interval: * * Interval (in deciseconds) between queries sent * by the bridge after the end of the startup phase. **/ /* ---ifcfg-rh--- * property: multicast-query-interval * variable: BRIDGING_OPTS: multicast_query_interval= * default: 12500 * example: BRIDGING_OPTS="multicast_query_interval=22500" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_QUERY_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL, "", "", NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN, NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX, NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-query-response-interval: * * Set the Max Response Time/Max Response Delay * (in deciseconds) for IGMP/MLD queries sent by the bridge. **/ /* ---ifcfg-rh--- * property: multicast-query-response-interval * variable: BRIDGING_OPTS: multicast_query_response_interval= * default: 1000 * example: BRIDGING_OPTS="multicast_query_response_interval=2000" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_QUERY_RESPONSE_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL, "", "", NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MIN, NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_MAX, NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-startup-query-count: * * Set the number of IGMP queries to send during startup phase. **/ /* ---ifcfg-rh--- * property: multicast-startup-query-count * variable: BRIDGING_OPTS: multicast_startup_query_count= * default: 2 * example: BRIDGING_OPTS="multicast_startup_query_count=4" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_STARTUP_QUERY_COUNT] = g_param_spec_uint(NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT, "", "", NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MIN, NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_MAX, NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** * NMSettingBridge:multicast-startup-query-interval: * * Sets the time (in deciseconds) between queries sent out * at startup to determine membership information. **/ /* ---ifcfg-rh--- * property: multicast-startup-query-interval * variable: BRIDGING_OPTS: multicast_startup_query_interval= * default: 3125 * example: BRIDGING_OPTS="multicast_startup_query_interval=4000" * ---end--- * * Since: 1.26 */ obj_properties[PROP_MULTICAST_STARTUP_QUERY_INTERVAL] = g_param_spec_uint64( NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL, "", "", NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MIN, NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_MAX, NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit_full(setting_class, NM_META_SETTING_TYPE_BRIDGE, NULL, properties_override); }