Files
NetworkManager/src/libnm-core-impl/nm-setting-bridge.c
Thomas Haller 71454ae4cd libnm: make ref counting of immutable types thread safe
The types NMBridgeVlan, NMIPRoutingRule, NMRange, NMWireGuardPeer
are immutable (or immutable, after the seal() function is called).

Immutable types are great, as it means a reference to them can be shared
without doing a full clone. Hence the G_DEFINE_BOXED_TYPE() for these
types prefers to take a reference instead of cloning the objects. Except
for sealable types, where it will prefer to clone unsealed values.
Likewise, nm_simple_connection_new_clone() probably will just take
another reference to the value, instead of doing a deep clone.

libnm is not a thread-safe library in the sense that you could pass a
NMConnection or NMClient instance to multiple threads and access them
without your own synchronization. However, it should be possible that
multiple threads access (seemingly) distinct objects.

As the copy function of these boxed types (and nm_simple_connection_new_clone()
and similar) prefers to share the references to immutable types, it is important
that the ref function is thread-safe too. Otherwise you cannot just clone a
NMConnection on thread1, hand the clone to thread2 and operate on the
clone and the original independently. If you do before this patch, you would
hit a subtle race condition.

Avoid that. While atomic operations have a runtime overhead, being safe
is more important. Also, we already save a full malloc()/free() by
having immutable, ref-counted types. We just need to make it safe to use
in order to fully benefit from it.
2022-12-20 10:35:02 +01:00

2158 lines
71 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2011 - 2017 Red Hat, Inc.
*/
#include "libnm-core-impl/nm-default-libnm-core.h"
#include "nm-setting-bridge.h"
#include <ctype.h>
#include <stdlib.h>
#include <linux/if_ether.h>
#include "libnm-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;
guint32 priority;
guint32 forward_delay;
guint32 hello_time;
guint32 max_age;
guint32 group_forward_mask;
guint32 vlan_default_pvid;
bool stp;
bool multicast_snooping;
bool vlan_filtering;
bool vlan_stats_enabled;
bool multicast_query_use_ifaddr;
bool multicast_querier;
} 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 {
int 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.
*
* Since 1.42, ref-counting of #NMBridgeVlan is thread-safe.
*
* 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_new(NMBridgeVlan);
*vlan = (NMBridgeVlan){
.refcount = 1,
.vid_start = vid_start,
.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.42, ref-counting of #NMBridgeVlan is thread-safe.
*
* 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_MAXINT);
g_atomic_int_inc(&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.42, ref-counting of #NMBridgeVlan is thread-safe.
*
* Since: 1.18
**/
void
nm_bridge_vlan_unref(NMBridgeVlan *vlan)
{
g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE));
if (g_atomic_int_dec_and_test(&vlan->refcount))
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. */
string = NM_STR_BUF_INIT(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);
}
}
GPtrArray *
_nm_setting_bridge_get_vlans(NMSettingBridge *setting)
{
nm_assert(NM_IS_SETTING_BRIDGE(setting));
return NM_SETTING_BRIDGE_GET_PRIVATE(setting)->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 & 7u) {
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;
if (connection && !nm_connection_get_setting_wired(connection)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
_("bridge connection should have a ethernet setting as well"));
g_prefix_error(error, "%s: ", NM_SETTING_BRIDGE_SETTING_NAME);
return NM_SETTING_VERIFY_NORMALIZABLE;
}
return TRUE;
}
static NMTernary
compare_fcn_vlans(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil)
{
if (set_b) {
return _nm_utils_bridge_compare_vlans(NM_SETTING_BRIDGE_GET_PRIVATE(set_a)->vlans,
NM_SETTING_BRIDGE_GET_PRIVATE(set_b)->vlans);
}
return TRUE;
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE(object);
switch (prop_id) {
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:
_nm_setting_property_get_property_direct(object, prop_id, value, 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_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:
_nm_setting_property_set_property_direct(object, prop_id, value, 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);
}
/**
* 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_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->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.
*
* Deprecated: 1.12: Use the #NMSettingWired: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---
*/
_nm_setting_property_define_direct_mac_address(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MAC_ADDRESS,
PROP_MAC_ADDRESS,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.mac_address,
.direct_set_string_mac_address_len = ETH_ALEN,
.is_deprecated = TRUE, );
/**
* 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---
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_STP,
PROP_STP,
NM_BRIDGE_STP_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.stp);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_PRIORITY,
PROP_PRIORITY,
NM_BRIDGE_PRIORITY_MIN,
NM_BRIDGE_PRIORITY_MAX,
NM_BRIDGE_PRIORITY_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.priority);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_FORWARD_DELAY,
PROP_FORWARD_DELAY,
0,
NM_BRIDGE_FORWARD_DELAY_MAX,
NM_BRIDGE_FORWARD_DELAY_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.forward_delay);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_HELLO_TIME,
PROP_HELLO_TIME,
0,
NM_BRIDGE_HELLO_TIME_MAX,
NM_BRIDGE_HELLO_TIME_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.hello_time);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MAX_AGE,
PROP_MAX_AGE,
0,
NM_BRIDGE_MAX_AGE_MAX,
NM_BRIDGE_MAX_AGE_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.max_age);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_AGEING_TIME,
PROP_AGEING_TIME,
NM_BRIDGE_AGEING_TIME_MIN,
NM_BRIDGE_AGEING_TIME_MAX,
NM_BRIDGE_AGEING_TIME_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.ageing_time);
/**
* 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
**/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_GROUP_FORWARD_MASK,
PROP_GROUP_FORWARD_MASK,
0,
0xFFFF,
0,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.group_forward_mask);
/**
* 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---
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_SNOOPING,
PROP_MULTICAST_SNOOPING,
NM_BRIDGE_MULTICAST_SNOOPING_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_snooping);
/**
* 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---
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_VLAN_FILTERING,
PROP_VLAN_FILTERING,
FALSE,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.vlan_filtering);
/**
* 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---
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID,
PROP_VLAN_DEFAULT_PVID,
0,
NM_BRIDGE_VLAN_VID_MAX,
NM_BRIDGE_VLAN_DEFAULT_PVID_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.vlan_default_pvid);
/**
* 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_DBUS(NM_G_VARIANT_TYPE("aa{sv}"),
.to_dbus_fcn = _nm_utils_bridge_vlans_to_dbus,
.compare_fcn = compare_fcn_vlans,
.from_dbus_fcn = _nm_utils_bridge_vlans_from_dbus, ));
/* ---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,
.dbus_deprecated = TRUE, );
/**
* 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---
*/
_nm_setting_property_define_direct_mac_address(properties_override,
obj_properties,
NM_SETTING_BRIDGE_GROUP_ADDRESS,
PROP_GROUP_ADDRESS,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.group_address,
.direct_set_string_mac_address_len = ETH_ALEN);
/**
* 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
*/
_nm_setting_property_define_direct_string(properties_override,
obj_properties,
NM_SETTING_BRIDGE_VLAN_PROTOCOL,
PROP_VLAN_PROTOCOL,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.vlan_protocol);
/**
* 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
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_VLAN_STATS_ENABLED,
PROP_VLAN_STATS_ENABLED,
NM_BRIDGE_VLAN_STATS_ENABLED_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.vlan_stats_enabled);
/**
* 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
*/
_nm_setting_property_define_direct_string(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_ROUTER,
PROP_MULTICAST_ROUTER,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_router);
/**
* 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
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR,
PROP_MULTICAST_QUERY_USE_IFADDR,
NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_query_use_ifaddr);
/**
* 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
*/
_nm_setting_property_define_direct_boolean(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_QUERIER,
PROP_MULTICAST_QUERIER,
NM_BRIDGE_MULTICAST_QUERIER_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_querier);
/**
* 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
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_HASH_MAX,
PROP_MULTICAST_HASH_MAX,
NM_BRIDGE_MULTICAST_HASH_MAX_MIN,
NM_BRIDGE_MULTICAST_HASH_MAX_MAX,
NM_BRIDGE_MULTICAST_HASH_MAX_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_hash_max);
/**
* 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
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT,
PROP_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,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_last_member_count);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL,
PROP_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,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_last_member_interval);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL,
PROP_MULTICAST_MEMBERSHIP_INTERVAL,
NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MIN,
NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_MAX,
NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_membership_interval);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL,
PROP_MULTICAST_QUERIER_INTERVAL,
NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MIN,
NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_MAX,
NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_querier_interval);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL,
PROP_MULTICAST_QUERY_INTERVAL,
NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MIN,
NM_BRIDGE_MULTICAST_QUERY_INTERVAL_MAX,
NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_query_interval);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL,
PROP_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,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_query_response_interval);
/**
* 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
*/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT,
PROP_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,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_startup_query_count);
/**
* 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
*/
_nm_setting_property_define_direct_uint64(properties_override,
obj_properties,
NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL,
PROP_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,
NM_SETTING_PARAM_INFERRABLE,
NMSettingBridge,
_priv.multicast_startup_query_interval);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit(setting_class,
NM_META_SETTING_TYPE_BRIDGE,
NULL,
properties_override,
0);
}