mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 18:50:07 +01:00
bridge: merge branch 'bg/bridge-vlan-ranges'
In some cases it is convenient to specify ranges of bridge vlans, as already supported by iproute2 and natively by kernel. https://bugzilla.redhat.com/show_bug.cgi?id=1652910 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/114
This commit is contained in:
commit
693252d049
19 changed files with 342 additions and 185 deletions
|
|
@ -167,8 +167,8 @@ _value_str_as_index_list (const char *value, gsize *out_len)
|
|||
|
||||
#define MULTILIST_WITH_ESCAPE_CHARS NM_ASCII_SPACES","
|
||||
|
||||
#define ESCAPED_TOKENS_DELIMTER ','
|
||||
#define ESCAPED_TOKENS_DELIMTERS ","
|
||||
#define ESCAPED_TOKENS_DELIMITER ','
|
||||
#define ESCAPED_TOKENS_DELIMITERS ","
|
||||
|
||||
typedef enum {
|
||||
VALUE_STRSPLIT_MODE_STRIPPED,
|
||||
|
|
@ -216,7 +216,7 @@ _value_strsplit (const char *value,
|
|||
strv = nm_utils_strsplit_set_full (value, MULTILIST_WITH_ESCAPE_CHARS, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
|
||||
break;
|
||||
case VALUE_STRSPLIT_MODE_ESCAPED_TOKENS:
|
||||
strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_DELIMTERS);
|
||||
strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_DELIMITERS);
|
||||
NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv));
|
||||
return g_steal_pointer (&strv);
|
||||
default:
|
||||
|
|
@ -3072,7 +3072,7 @@ _get_fcn_objlist (ARGS_GET_FCN)
|
|||
&& property_info->property_typ_data->subtype.objlist.delimit_pretty_with_semicolon)
|
||||
g_string_append (str, "; ");
|
||||
else {
|
||||
G_STATIC_ASSERT_EXPR (ESCAPED_TOKENS_DELIMTER == ',');
|
||||
G_STATIC_ASSERT_EXPR (ESCAPED_TOKENS_DELIMITER == ',');
|
||||
g_string_append (str, ", ");
|
||||
}
|
||||
}
|
||||
|
|
@ -3400,7 +3400,7 @@ _objlist_obj_to_str_fcn_ip_config_routing_rules (NMMetaAccessorGetType get_type,
|
|||
NULL,
|
||||
NULL);
|
||||
if (s)
|
||||
nm_utils_escaped_tokens_escape_gstr (s, ESCAPED_TOKENS_DELIMTERS, str);
|
||||
nm_utils_escaped_tokens_escape_gstr (s, ESCAPED_TOKENS_DELIMITERS, str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -3559,7 +3559,7 @@ _objlist_obj_to_str_fcn_bridge_vlans (NMMetaAccessorGetType get_type,
|
|||
|
||||
s = nm_bridge_vlan_to_str (vlan, NULL);
|
||||
if (s)
|
||||
g_string_append (str, s);
|
||||
nm_utils_escaped_tokens_escape_gstr_assert (s, ESCAPED_TOKENS_DELIMITERS, str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -3618,13 +3618,14 @@ _objlist_set_fcn_bridge_vlans (NMSetting *setting,
|
|||
{
|
||||
nm_auto_unref_bridge_vlan NMBridgeVlan *vlan = NULL;
|
||||
gs_free_error GError *local = NULL;
|
||||
guint16 vid_start, vid_end;
|
||||
|
||||
vlan = nm_bridge_vlan_from_str (value, &local);
|
||||
if (!vlan) {
|
||||
nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
"%s. %s",
|
||||
local->message,
|
||||
_("The valid syntax is: '<vid> [pvid] [untagged]"));
|
||||
_("The valid syntax is: '<vid>[-<vid>] [pvid] [untagged]'"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -3632,15 +3633,18 @@ _objlist_set_fcn_bridge_vlans (NMSetting *setting,
|
|||
if (do_add)
|
||||
nm_setting_bridge_add_vlan (NM_SETTING_BRIDGE (setting), vlan);
|
||||
else {
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
nm_setting_bridge_remove_vlan_by_vid (NM_SETTING_BRIDGE (setting),
|
||||
nm_bridge_vlan_get_vid (vlan));
|
||||
vid_start, vid_end);
|
||||
}
|
||||
} else {
|
||||
if (do_add)
|
||||
nm_setting_bridge_port_add_vlan (NM_SETTING_BRIDGE_PORT (setting), vlan);
|
||||
else {
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
nm_setting_bridge_port_remove_vlan_by_vid (NM_SETTING_BRIDGE_PORT (setting),
|
||||
nm_bridge_vlan_get_vid (vlan));
|
||||
vid_start,
|
||||
vid_end);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4987,6 +4991,7 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = {
|
|||
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingBridge, nm_setting_bridge_clear_vlans),
|
||||
.obj_to_str_fcn = _objlist_obj_to_str_fcn_bridge_vlans,
|
||||
.set_fcn = _objlist_set_fcn_bridge_vlans,
|
||||
.strsplit_escaped_tokens = TRUE,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -5022,6 +5027,7 @@ static const NMMetaPropertyInfo *const property_infos_BRIDGE_PORT[] = {
|
|||
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingBridgePort, nm_setting_bridge_port_clear_vlans),
|
||||
.obj_to_str_fcn = _objlist_obj_to_str_fcn_bridge_vlans,
|
||||
.set_fcn = _objlist_set_fcn_bridge_vlans,
|
||||
.strsplit_escaped_tokens = TRUE,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -120,11 +120,11 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_STP N_("Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID N_("The default PVID for the ports of the bridge, that is the VLAN id assigned to incoming untagged frames.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLAN_FILTERING N_("Control whether VLAN filtering is enabled on the bridge.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]...")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the bridge will also have the default-pvid VLAN configured by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE N_("Enables or disables \"hairpin mode\" for the port, which allows frames to be sent back out through the port the frame was received on.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PATH_COST N_("The Spanning Tree Protocol (STP) port cost for destinations via this port.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_PRIORITY N_("The Spanning Tree Protocol (STP) priority of this bridge port.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the port will also have the default-pvid VLAN configured on the bridge 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]]...")
|
||||
#define DESCRIBE_DOC_NM_SETTING_BRIDGE_PORT_VLANS N_("Array of bridge VLAN objects. In addition to the VLANs specified here, the port will also have the default-pvid VLAN configured on the bridge by the bridge.vlan-default-pvid property. In nmcli the VLAN list can be specified with the following syntax: $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CDMA_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CDMA_NUMBER N_("The number to dial to establish the connection to the CDMA-based mobile broadband network, if any. If not specified, the default number (#777) is used when required.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_CDMA_PASSWORD N_("The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here.")
|
||||
|
|
|
|||
|
|
@ -1626,51 +1626,37 @@ team_config_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
|
|||
static void
|
||||
bridge_vlan_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
gs_unref_ptrarray GPtrArray *vlans = NULL;
|
||||
gs_strfreev char **keys = NULL;
|
||||
gsize n_keys = 0;
|
||||
int i;
|
||||
gs_free char *value = NULL;
|
||||
gs_free const char **strv = NULL;
|
||||
const char *const *iter;
|
||||
GError *local = NULL;
|
||||
NMBridgeVlan *vlan;
|
||||
|
||||
keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL);
|
||||
if (n_keys == 0)
|
||||
value = nm_keyfile_plugin_kf_get_string (info->keyfile,
|
||||
nm_setting_get_name (setting),
|
||||
key,
|
||||
NULL);
|
||||
if (!value || !value[0])
|
||||
return;
|
||||
|
||||
vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref);
|
||||
|
||||
for (i = 0; i < n_keys; i++) {
|
||||
NMBridgeVlan *vlan;
|
||||
const char *index;
|
||||
gs_free char *vlan_rest = NULL;
|
||||
gs_free char *vlan_str = NULL;
|
||||
gs_free_error GError *err = NULL;
|
||||
|
||||
if (!g_str_has_prefix (keys[i], "vlan."))
|
||||
continue;
|
||||
|
||||
index = keys[i] + NM_STRLEN("vlan.");
|
||||
|
||||
if (index[0] == '\0')
|
||||
continue;
|
||||
if (index[0] == '0' && index[1] != '\0')
|
||||
continue;
|
||||
if (!NM_STRCHAR_ALL (index, ch, g_ascii_isdigit (ch)))
|
||||
continue;
|
||||
|
||||
vlan_rest = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, keys[i], NULL);
|
||||
vlan_str = g_strdup_printf ("%s %s", index, vlan_rest);
|
||||
|
||||
vlan = nm_bridge_vlan_from_str (vlan_str, &err);
|
||||
if (!vlan) {
|
||||
handle_warn (info, keys[i], NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid bridge vlan: %s"),
|
||||
err->message);
|
||||
continue;
|
||||
strv = nm_utils_escaped_tokens_split (value, ",");
|
||||
if (strv) {
|
||||
for (iter = strv; *iter; iter++) {
|
||||
vlan = nm_bridge_vlan_from_str (*iter, &local);
|
||||
if (!vlan) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
"invalid bridge VLAN: %s", local->message);
|
||||
g_clear_error (&local);
|
||||
continue;
|
||||
}
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
}
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
}
|
||||
|
||||
if (vlans->len >= 1)
|
||||
if (vlans->len > 0)
|
||||
g_object_set (setting, key, vlans, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -2004,26 +1990,34 @@ bridge_vlan_writer (KeyfileWriterInfo *info,
|
|||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
gsize i;
|
||||
GPtrArray *array;
|
||||
nm_auto_free_gstring GString *value_str = NULL;
|
||||
NMBridgeVlan *vlan;
|
||||
GPtrArray *vlans;
|
||||
GString *string;
|
||||
guint i;
|
||||
|
||||
array = (GPtrArray *) g_value_get_boxed (value);
|
||||
if (!array || !array->len)
|
||||
vlans = (GPtrArray *) g_value_get_boxed (value);
|
||||
if (!vlans || !vlans->len)
|
||||
return;
|
||||
|
||||
for (i = 0; i < array->len; i++) {
|
||||
NMBridgeVlan *vlan = array->pdata[i];
|
||||
char key_name[32];
|
||||
string = g_string_new ("");
|
||||
for (i = 0; i < vlans->len; i++) {
|
||||
gs_free char *vlan_str = NULL;
|
||||
|
||||
nm_sprintf_buf (key_name, "vlan.%u", nm_bridge_vlan_get_vid (vlan));
|
||||
nm_gstring_prepare (&value_str);
|
||||
_nm_bridge_vlan_str_append_rest (vlan, value_str, FALSE);
|
||||
nm_keyfile_plugin_kf_set_string (info->keyfile,
|
||||
nm_setting_get_name (setting),
|
||||
key_name,
|
||||
value_str->str);
|
||||
vlan = vlans->pdata[i];
|
||||
vlan_str = nm_bridge_vlan_to_str (vlan, NULL);
|
||||
if (!vlan_str)
|
||||
continue;
|
||||
if (string->len > 0)
|
||||
g_string_append (string, ",");
|
||||
nm_utils_escaped_tokens_escape_gstr_assert (vlan_str, ",", string);
|
||||
}
|
||||
|
||||
nm_keyfile_plugin_kf_set_string (info->keyfile,
|
||||
nm_setting_get_name (setting),
|
||||
"vlans",
|
||||
string->str);
|
||||
|
||||
g_string_free (string, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -235,9 +235,12 @@ nm_setting_bridge_port_remove_vlan (NMSettingBridgePort *setting, guint idx)
|
|||
/**
|
||||
* nm_setting_bridge_port_remove_vlan_by_vid:
|
||||
* @setting: the #NMSettingBridgePort
|
||||
* @vid: the vlan index of the vlan to remove
|
||||
* @vid_start: the vlan start index
|
||||
* @vid_end: the vlan end index
|
||||
*
|
||||
* Removes the vlan vith id @vid.
|
||||
* 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
|
||||
*
|
||||
|
|
@ -245,16 +248,24 @@ nm_setting_bridge_port_remove_vlan (NMSettingBridgePort *setting, guint idx)
|
|||
**/
|
||||
gboolean
|
||||
nm_setting_bridge_port_remove_vlan_by_vid (NMSettingBridgePort *setting,
|
||||
guint16 vid)
|
||||
guint16 vid_start,
|
||||
guint16 vid_end)
|
||||
{
|
||||
NMSettingBridgePortPrivate *priv;
|
||||
guint16 v_start, v_end;
|
||||
NMBridgeVlan *vlan;
|
||||
guint i;
|
||||
|
||||
if (vid_end == 0)
|
||||
vid_end = vid_start;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_BRIDGE_PORT (setting), FALSE);
|
||||
priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting);
|
||||
|
||||
for (i = 0; i < priv->vlans->len; i++) {
|
||||
if (nm_bridge_vlan_get_vid (priv->vlans->pdata[i]) == vid) {
|
||||
vlan = (NMBridgeVlan *) priv->vlans->pdata[i];
|
||||
nm_bridge_vlan_get_vid_range (vlan, &v_start, &v_end);
|
||||
if (v_start == vid_start && v_end == vid_end) {
|
||||
g_ptr_array_remove_index (priv->vlans, i);
|
||||
_notify (setting, PROP_VLANS);
|
||||
return TRUE;
|
||||
|
|
@ -556,13 +567,16 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass)
|
|||
*
|
||||
* $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_PORT_VLANS
|
||||
* description: List of VLANs on the bridge port
|
||||
* example: BRIDGE_PORT_VLANS="1 pvid untagged,20,40 untagged"
|
||||
* example: BRIDGE_PORT_VLANS="1 pvid untagged,20,300-400 untagged"
|
||||
* ---end---
|
||||
*/
|
||||
obj_properties[PROP_VLANS] =
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@ NMBridgeVlan *nm_setting_bridge_port_get_vlan (NMSettingBridgePort *setting, gui
|
|||
NM_AVAILABLE_IN_1_18
|
||||
void nm_setting_bridge_port_remove_vlan (NMSettingBridgePort *setting, guint idx);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_setting_bridge_port_remove_vlan_by_vid (NMSettingBridgePort *setting, guint16 vid);
|
||||
gboolean nm_setting_bridge_port_remove_vlan_by_vid (NMSettingBridgePort *setting,
|
||||
guint16 vid_start,
|
||||
guint16 vid_end);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_setting_bridge_port_clear_vlans (NMSettingBridgePort *setting);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ G_DEFINE_BOXED_TYPE (NMBridgeVlan, nm_bridge_vlan, _nm_bridge_vlan_dup, nm_bridg
|
|||
|
||||
struct _NMBridgeVlan {
|
||||
guint refcount;
|
||||
guint16 vid;
|
||||
guint16 vid_start;
|
||||
guint16 vid_end;
|
||||
bool untagged:1;
|
||||
bool pvid:1;
|
||||
bool sealed:1;
|
||||
|
|
@ -96,25 +97,33 @@ NM_IS_BRIDGE_VLAN (const NMBridgeVlan *self, gboolean also_sealed)
|
|||
|
||||
/**
|
||||
* nm_bridge_vlan_new:
|
||||
* @vid: the VLAN id, must be between 1 and 4094.
|
||||
* @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.
|
||||
* 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)
|
||||
nm_bridge_vlan_new (guint16 vid_start, guint16 vid_end)
|
||||
{
|
||||
NMBridgeVlan *vlan;
|
||||
|
||||
g_return_val_if_fail (vid >= NM_BRIDGE_VLAN_VID_MIN, NULL);
|
||||
g_return_val_if_fail (vid <= NM_BRIDGE_VLAN_VID_MAX, NULL);
|
||||
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 = vid;
|
||||
vlan->vid_start = vid_start;
|
||||
vlan->vid_end = vid_end;
|
||||
|
||||
return vlan;
|
||||
}
|
||||
|
|
@ -179,7 +188,8 @@ nm_bridge_vlan_cmp (const NMBridgeVlan *a, const NMBridgeVlan *b)
|
|||
g_return_val_if_fail (NM_IS_BRIDGE_VLAN (b, TRUE), 0);
|
||||
|
||||
NM_CMP_SELF (a, b);
|
||||
NM_CMP_FIELD (a, b, vid);
|
||||
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);
|
||||
|
||||
|
|
@ -213,21 +223,29 @@ _nm_bridge_vlan_dup_and_seal (const NMBridgeVlan *vlan)
|
|||
}
|
||||
|
||||
/**
|
||||
* nm_bridge_vlan_get_vid:
|
||||
* nm_bridge_vlan_get_vid_range:
|
||||
* @vlan: the #NMBridgeVlan
|
||||
* @vid_start: location to store the VLAN id range start.
|
||||
* @vid_end: location to store the VLAN id range end
|
||||
*
|
||||
* Gets the VLAN id of the object.
|
||||
* Gets the VLAN id range.
|
||||
*
|
||||
* Returns: the VLAN id
|
||||
* Returns: %TRUE is the VLAN specifies a range, %FALSE if it is
|
||||
* a single-id VLAN.
|
||||
*
|
||||
* Since: 1.18
|
||||
**/
|
||||
guint16
|
||||
nm_bridge_vlan_get_vid (const NMBridgeVlan *vlan)
|
||||
gboolean
|
||||
nm_bridge_vlan_get_vid_range (const NMBridgeVlan *vlan,
|
||||
guint16 *vid_start,
|
||||
guint16 *vid_end)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_BRIDGE_VLAN (vlan, TRUE), 0);
|
||||
|
||||
return vlan->vid;
|
||||
NM_SET_OUT (vid_start, vlan->vid_start);
|
||||
NM_SET_OUT (vid_end, vlan->vid_end);
|
||||
|
||||
return vlan->vid_start != vlan->vid_end;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -288,7 +306,9 @@ nm_bridge_vlan_set_untagged (NMBridgeVlan *vlan, gboolean value)
|
|||
* @vlan: the #NMBridgeVlan
|
||||
* @value: the new value
|
||||
*
|
||||
* Change the value of the PVID property of the VLAN.
|
||||
* 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
|
||||
**/
|
||||
|
|
@ -296,6 +316,7 @@ 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;
|
||||
}
|
||||
|
|
@ -351,7 +372,7 @@ nm_bridge_vlan_new_clone (const NMBridgeVlan *vlan)
|
|||
|
||||
g_return_val_if_fail (NM_IS_BRIDGE_VLAN (vlan, TRUE), NULL);
|
||||
|
||||
copy = nm_bridge_vlan_new (vlan->vid);
|
||||
copy = nm_bridge_vlan_new (vlan->vid_start, vlan->vid_end);
|
||||
copy->untagged = vlan->untagged;
|
||||
copy->pvid = vlan->pvid;
|
||||
|
||||
|
|
@ -400,9 +421,13 @@ nm_bridge_vlan_to_str (const NMBridgeVlan *vlan, GError **error)
|
|||
* future if more parameters are added to the object that could
|
||||
* make it invalid. */
|
||||
|
||||
string = g_string_sized_new (20);
|
||||
string = g_string_sized_new (28);
|
||||
|
||||
if (vlan->vid_start == vlan->vid_end)
|
||||
g_string_append_printf (string, "%u", vlan->vid_start);
|
||||
else
|
||||
g_string_append_printf (string, "%u-%u", vlan->vid_start, vlan->vid_end);
|
||||
|
||||
g_string_append_printf (string, "%u", nm_bridge_vlan_get_vid (vlan));
|
||||
_nm_bridge_vlan_str_append_rest (vlan, string, TRUE);
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
|
|
@ -425,14 +450,15 @@ nm_bridge_vlan_from_str (const char *str, GError **error)
|
|||
{
|
||||
NMBridgeVlan *vlan = NULL;
|
||||
gs_free const char **tokens = NULL;
|
||||
guint i, vid;
|
||||
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_strsplit_set (str, " ");
|
||||
tokens = nm_utils_escaped_tokens_split (str, NM_ASCII_SPACES);
|
||||
if (!tokens || !tokens[0]) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
|
|
@ -441,23 +467,58 @@ nm_bridge_vlan_from_str (const char *str, GError **error)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
vid = _nm_utils_ascii_str_to_uint64 (tokens[0],
|
||||
10,
|
||||
NM_BRIDGE_VLAN_VID_MIN,
|
||||
NM_BRIDGE_VLAN_VID_MAX,
|
||||
G_MAXUINT);
|
||||
if (vid == G_MAXUINT) {
|
||||
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 '%s', must be in [1,4094]", tokens[0]);
|
||||
"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 (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"))
|
||||
} else if (nm_streq (tokens[i], "untagged"))
|
||||
untagged = TRUE;
|
||||
else {
|
||||
g_set_error (error,
|
||||
|
|
@ -468,7 +529,7 @@ nm_bridge_vlan_from_str (const char *str, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
vlan = nm_bridge_vlan_new (vid);
|
||||
vlan = nm_bridge_vlan_new (vid_start, vid_end);
|
||||
nm_bridge_vlan_set_pvid (vlan, pvid);
|
||||
nm_bridge_vlan_set_untagged (vlan, untagged);
|
||||
|
||||
|
|
@ -772,9 +833,12 @@ nm_setting_bridge_remove_vlan (NMSettingBridge *setting, guint idx)
|
|||
/**
|
||||
* nm_setting_bridge_remove_vlan_by_vid:
|
||||
* @setting: the #NMSettingBridge
|
||||
* @vid: the vlan index of the vlan to remove
|
||||
* @vid_start: the vlan start index
|
||||
* @vid_end: the vlan end index
|
||||
*
|
||||
* Removes the vlan vith id @vid.
|
||||
* 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
|
||||
*
|
||||
|
|
@ -782,16 +846,22 @@ nm_setting_bridge_remove_vlan (NMSettingBridge *setting, guint idx)
|
|||
**/
|
||||
gboolean
|
||||
nm_setting_bridge_remove_vlan_by_vid (NMSettingBridge *setting,
|
||||
guint16 vid)
|
||||
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++) {
|
||||
if (nm_bridge_vlan_get_vid (priv->vlans->pdata[i]) == vid) {
|
||||
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;
|
||||
|
|
@ -1390,13 +1460,16 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass)
|
|||
*
|
||||
* $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,40 untagged"
|
||||
* example: BRIDGE_VLANS="1 pvid untagged,20,300-400 untagged"
|
||||
* ---end---
|
||||
*/
|
||||
obj_properties[PROP_VLANS] =
|
||||
|
|
|
|||
|
|
@ -108,14 +108,16 @@ NMBridgeVlan *nm_setting_bridge_get_vlan (NMSettingBridge *setting, guint idx);
|
|||
NM_AVAILABLE_IN_1_18
|
||||
void nm_setting_bridge_remove_vlan (NMSettingBridge *setting, guint idx);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_setting_bridge_remove_vlan_by_vid (NMSettingBridge *setting, guint16 vid);
|
||||
gboolean nm_setting_bridge_remove_vlan_by_vid (NMSettingBridge *setting,
|
||||
guint16 vid_start,
|
||||
guint16 vid_end);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_setting_bridge_clear_vlans (NMSettingBridge *setting);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
GType nm_bridge_vlan_get_type (void);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
NMBridgeVlan * nm_bridge_vlan_new (guint16 vid);
|
||||
NMBridgeVlan * nm_bridge_vlan_new (guint16 vid_start, guint16 vid_end);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
NMBridgeVlan * nm_bridge_vlan_ref (NMBridgeVlan *vlan);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
|
|
@ -133,7 +135,7 @@ void nm_bridge_vlan_set_untagged (NMBridgeVlan *vlan, gboolean value);
|
|||
NM_AVAILABLE_IN_1_18
|
||||
void nm_bridge_vlan_set_pvid (NMBridgeVlan *vlan, gboolean value);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint16 nm_bridge_vlan_get_vid (const NMBridgeVlan *vlan);
|
||||
gboolean nm_bridge_vlan_get_vid_range (const NMBridgeVlan *vlan, guint16 *vid_start, guint16 *vid_end);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_bridge_vlan_is_untagged (const NMBridgeVlan *vlan);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
|
|
|
|||
|
|
@ -6800,10 +6800,15 @@ _nm_utils_bridge_vlans_to_dbus (NMSetting *setting, const char *property)
|
|||
for (i = 0; i < vlans->len; i++) {
|
||||
NMBridgeVlan *vlan = vlans->pdata[i];
|
||||
GVariantBuilder vlan_builder;
|
||||
guint16 vid_start, vid_end;
|
||||
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
|
||||
g_variant_builder_init (&vlan_builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&vlan_builder, "{sv}", "vid",
|
||||
g_variant_new_uint16 (nm_bridge_vlan_get_vid (vlan)));
|
||||
g_variant_builder_add (&vlan_builder, "{sv}", "vid-start",
|
||||
g_variant_new_uint16 (vid_start));
|
||||
g_variant_builder_add (&vlan_builder, "{sv}", "vid-end",
|
||||
g_variant_new_uint16 (vid_end));
|
||||
g_variant_builder_add (&vlan_builder, "{sv}", "pvid",
|
||||
g_variant_new_boolean (nm_bridge_vlan_is_pvid (vlan)));
|
||||
g_variant_builder_add (&vlan_builder, "{sv}", "untagged",
|
||||
|
|
@ -6834,19 +6839,29 @@ _nm_utils_bridge_vlans_from_dbus (NMSetting *setting,
|
|||
while (g_variant_iter_next (&vlan_iter, "@a{sv}", &vlan_var)) {
|
||||
_nm_unused gs_unref_variant GVariant *var_unref = vlan_var;
|
||||
NMBridgeVlan *vlan;
|
||||
guint16 vid;
|
||||
guint16 vid_start, vid_end;
|
||||
gboolean pvid = FALSE, untagged = FALSE;
|
||||
|
||||
if (!g_variant_lookup (vlan_var, "vid", "q", &vid))
|
||||
if (!g_variant_lookup (vlan_var, "vid-start", "q", &vid_start))
|
||||
continue;
|
||||
if ( vid < NM_BRIDGE_VLAN_VID_MIN
|
||||
|| vid > NM_BRIDGE_VLAN_VID_MAX)
|
||||
if ( vid_start < NM_BRIDGE_VLAN_VID_MIN
|
||||
|| vid_start > NM_BRIDGE_VLAN_VID_MAX)
|
||||
continue;
|
||||
|
||||
if (!g_variant_lookup (vlan_var, "vid-end", "q", &vid_end))
|
||||
continue;
|
||||
if ( vid_end < NM_BRIDGE_VLAN_VID_MIN
|
||||
|| vid_end > NM_BRIDGE_VLAN_VID_MAX)
|
||||
continue;
|
||||
if (vid_start > vid_end)
|
||||
continue;
|
||||
|
||||
g_variant_lookup (vlan_var, "pvid", "b", &pvid);
|
||||
if (pvid && vid_start != vid_end)
|
||||
continue;
|
||||
g_variant_lookup (vlan_var, "untagged", "b", &untagged);
|
||||
|
||||
vlan = nm_bridge_vlan_new (vid);
|
||||
vlan = nm_bridge_vlan_new (vid_start, vid_end);
|
||||
nm_bridge_vlan_set_untagged (vlan, untagged);
|
||||
nm_bridge_vlan_set_pvid (vlan, pvid);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
|
|
@ -6868,24 +6883,33 @@ _nm_utils_bridge_vlan_verify_list (GPtrArray *vlans,
|
|||
gs_unref_hashtable GHashTable *h = NULL;
|
||||
gboolean pvid_found = FALSE;
|
||||
|
||||
if (!vlans || !vlans->len)
|
||||
if ( !vlans
|
||||
|| vlans->len <= 1)
|
||||
return TRUE;
|
||||
|
||||
if (check_normalizable) {
|
||||
for (i = 1; i < vlans->len; i++) {
|
||||
NMBridgeVlan *vlan_prev = vlans->pdata[i - 1];
|
||||
NMBridgeVlan *vlan = vlans->pdata[i];
|
||||
guint16 vid_prev_end, vid_start, vid_end;
|
||||
|
||||
if (nm_bridge_vlan_get_vid (vlan_prev) > nm_bridge_vlan_get_vid (vlan)) {
|
||||
nm_assert (_nm_utils_bridge_vlan_verify_list (vlans, FALSE, NULL, setting, property));
|
||||
|
||||
nm_bridge_vlan_get_vid_range (vlans->pdata[0], NULL, &vid_prev_end);
|
||||
for (i = 1; i < vlans->len; i++) {
|
||||
const NMBridgeVlan *vlan = vlans->pdata[i];
|
||||
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
|
||||
if (vid_prev_end > vid_start) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("Bridge VLANs %d and %d are not sorted by ascending vid"),
|
||||
nm_bridge_vlan_get_vid (vlan_prev),
|
||||
nm_bridge_vlan_get_vid (vlan));
|
||||
vid_prev_end,
|
||||
vid_start);
|
||||
g_prefix_error (error, "%s.%s: ", setting, property);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
vid_prev_end = vid_end;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -6893,21 +6917,24 @@ _nm_utils_bridge_vlan_verify_list (GPtrArray *vlans,
|
|||
h = g_hash_table_new (nm_direct_hash, NULL);
|
||||
for (i = 0; i < vlans->len; i++) {
|
||||
NMBridgeVlan *vlan = vlans->pdata[i];
|
||||
guint vid;
|
||||
guint16 v, vid_start, vid_end;
|
||||
|
||||
vid = nm_bridge_vlan_get_vid (vlan);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
|
||||
if (g_hash_table_contains (h, GUINT_TO_POINTER (vid))) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("duplicate bridge VLAN vid %u"), vid);
|
||||
g_prefix_error (error, "%s.%s: ", setting, property);
|
||||
return FALSE;
|
||||
for (v = vid_start; v <= vid_end; v++) {
|
||||
if (!nm_g_hash_table_add (h, GUINT_TO_POINTER (v))) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("duplicate bridge VLAN vid %u"), v);
|
||||
g_prefix_error (error, "%s.%s: ", setting, property);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (nm_bridge_vlan_is_pvid (vlan)) {
|
||||
if (pvid_found) {
|
||||
if ( vid_start != vid_end
|
||||
|| pvid_found) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
|
|
@ -6917,8 +6944,6 @@ _nm_utils_bridge_vlan_verify_list (GPtrArray *vlans,
|
|||
}
|
||||
pvid_found = TRUE;
|
||||
}
|
||||
|
||||
g_hash_table_add (h, GUINT_TO_POINTER (vid));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -751,6 +751,7 @@ test_bridge_vlans (void)
|
|||
gs_unref_object NMConnection *con = NULL;
|
||||
NMSettingBridge *s_bridge;
|
||||
NMBridgeVlan *vlan;
|
||||
guint16 vid, vid_end;
|
||||
|
||||
con = nmtst_create_connection_from_keyfile (
|
||||
"[connection]\n"
|
||||
|
|
@ -759,26 +760,37 @@ test_bridge_vlans (void)
|
|||
"interface-name=br4\n"
|
||||
"\n"
|
||||
"[bridge]\n"
|
||||
"vlan.9=untagged\n"
|
||||
"vlan.1=pvid untagged\n"
|
||||
"vlans=900 , 1 pvid untagged, 100-123 untagged\n"
|
||||
"",
|
||||
"/test_bridge_port/vlans");
|
||||
s_bridge = NM_SETTING_BRIDGE (nm_connection_get_setting (con, NM_TYPE_SETTING_BRIDGE));
|
||||
g_assert (s_bridge);
|
||||
g_assert_cmpuint (nm_setting_bridge_get_num_vlans (s_bridge), ==, 2);
|
||||
g_assert_cmpuint (nm_setting_bridge_get_num_vlans (s_bridge), ==, 3);
|
||||
|
||||
vlan = nm_setting_bridge_get_vlan (s_bridge, 0);
|
||||
g_assert (vlan);
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (vlan), ==, 1);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid, &vid_end);
|
||||
g_assert_cmpuint (vid, ==, 1);
|
||||
g_assert_cmpuint (vid_end, ==, 1);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, TRUE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, TRUE);
|
||||
|
||||
vlan = nm_setting_bridge_get_vlan (s_bridge, 1);
|
||||
g_assert (vlan);
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (vlan), ==, 9);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid, &vid_end);
|
||||
g_assert_cmpuint (vid, ==, 100);
|
||||
g_assert_cmpuint (vid_end, ==, 123);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, TRUE);
|
||||
|
||||
vlan = nm_setting_bridge_get_vlan (s_bridge, 2);
|
||||
g_assert (vlan);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid, &vid_end);
|
||||
g_assert_cmpuint (vid, ==, 900);
|
||||
g_assert_cmpuint (vid_end, ==, 900);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, FALSE);
|
||||
|
||||
CLEAR (&con, &keyfile);
|
||||
}
|
||||
|
||||
|
|
@ -789,6 +801,7 @@ test_bridge_port_vlans (void)
|
|||
gs_unref_object NMConnection *con = NULL;
|
||||
NMSettingBridgePort *s_port;
|
||||
NMBridgeVlan *vlan;
|
||||
guint16 vid_start, vid_end;
|
||||
|
||||
con = nmtst_create_connection_from_keyfile (
|
||||
"[connection]\n"
|
||||
|
|
@ -799,31 +812,27 @@ test_bridge_port_vlans (void)
|
|||
"slave-type=bridge\n"
|
||||
"\n"
|
||||
"[bridge-port]\n"
|
||||
"vlan.4000=\n"
|
||||
"vlan.10=untagged\n"
|
||||
"vlan.20=pvid untagged"
|
||||
"vlans=4094 pvid , 10-20 untagged\n"
|
||||
"",
|
||||
"/test_bridge_port/vlans");
|
||||
s_port = NM_SETTING_BRIDGE_PORT (nm_connection_get_setting (con, NM_TYPE_SETTING_BRIDGE_PORT));
|
||||
g_assert (s_port);
|
||||
g_assert_cmpuint (nm_setting_bridge_port_get_num_vlans (s_port), ==, 3);
|
||||
g_assert_cmpuint (nm_setting_bridge_port_get_num_vlans (s_port), ==, 2);
|
||||
|
||||
vlan = nm_setting_bridge_port_get_vlan (s_port, 0);
|
||||
g_assert (vlan);
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (vlan), ==, 10);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
g_assert_cmpuint (vid_start, ==, 10);
|
||||
g_assert_cmpuint (vid_end, ==, 20);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, TRUE);
|
||||
|
||||
vlan = nm_setting_bridge_port_get_vlan (s_port, 1);
|
||||
g_assert (vlan);
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (vlan), ==, 20);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
g_assert_cmpuint (vid_start, ==, 4094);
|
||||
g_assert_cmpuint (vid_end, ==, 4094);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, TRUE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, TRUE);
|
||||
|
||||
vlan = nm_setting_bridge_port_get_vlan (s_port, 2);
|
||||
g_assert (vlan);
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (vlan), ==, 4000);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (vlan), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (vlan), ==, FALSE);
|
||||
|
||||
CLEAR (&con, &keyfile);
|
||||
|
|
|
|||
|
|
@ -1664,6 +1664,7 @@ test_bridge_vlans (void)
|
|||
{
|
||||
NMBridgeVlan *v1, *v2;
|
||||
GError *error = NULL;
|
||||
guint16 vid_start, vid_end;
|
||||
char *str;
|
||||
|
||||
v1 = nm_bridge_vlan_from_str ("1 foobar", &error);
|
||||
|
|
@ -1674,11 +1675,23 @@ test_bridge_vlans (void)
|
|||
nmtst_assert_no_success (v1, error);
|
||||
g_clear_error (&error);
|
||||
|
||||
/* test ranges */
|
||||
v1 = nm_bridge_vlan_from_str ("2-1000 untagged", &error);
|
||||
nmtst_assert_success (v1, error);
|
||||
g_assert_cmpint (nm_bridge_vlan_get_vid_range (v1, &vid_start, &vid_end), ==, TRUE);
|
||||
g_assert_cmpuint (vid_start, ==, 2);
|
||||
g_assert_cmpuint (vid_end, ==, 1000);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (v1), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (v1), ==, TRUE);
|
||||
nm_bridge_vlan_unref (v1);
|
||||
|
||||
/* test comparison (1) */
|
||||
v1 = nm_bridge_vlan_from_str ("10 untagged", &error);
|
||||
nmtst_assert_success (v1, error);
|
||||
|
||||
g_assert_cmpuint (nm_bridge_vlan_get_vid (v1), ==, 10);
|
||||
g_assert_cmpint (nm_bridge_vlan_get_vid_range (v1, &vid_start, &vid_end), ==, FALSE);
|
||||
g_assert_cmpuint (vid_start, ==, 10);
|
||||
g_assert_cmpuint (vid_end, ==, 10);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_sealed (v1), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_pvid (v1), ==, FALSE);
|
||||
g_assert_cmpint (nm_bridge_vlan_is_untagged (v1), ==, TRUE);
|
||||
|
|
|
|||
|
|
@ -1524,7 +1524,7 @@ global:
|
|||
nm_bridge_vlan_cmp;
|
||||
nm_bridge_vlan_from_str;
|
||||
nm_bridge_vlan_get_type;
|
||||
nm_bridge_vlan_get_vid;
|
||||
nm_bridge_vlan_get_vid_range;
|
||||
nm_bridge_vlan_is_pvid;
|
||||
nm_bridge_vlan_is_sealed;
|
||||
nm_bridge_vlan_is_untagged;
|
||||
|
|
|
|||
|
|
@ -268,31 +268,37 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool
|
|||
nm_platform_sysctl_master_set_option (nm_device_get_platform (device), ifindex, option->sysname, value);
|
||||
}
|
||||
|
||||
static NMPlatformBridgeVlan **
|
||||
static const NMPlatformBridgeVlan **
|
||||
setting_vlans_to_platform (GPtrArray *array)
|
||||
{
|
||||
GPtrArray *plat_vlans;
|
||||
NMPlatformBridgeVlan **arr;
|
||||
NMPlatformBridgeVlan *p_data;
|
||||
guint i;
|
||||
|
||||
if (!array || !array->len)
|
||||
return NULL;
|
||||
|
||||
plat_vlans = g_ptr_array_sized_new (array->len + 1);
|
||||
G_STATIC_ASSERT_EXPR (_nm_alignof (NMPlatformBridgeVlan *) >= _nm_alignof (NMPlatformBridgeVlan));
|
||||
arr = g_malloc ( (sizeof (NMPlatformBridgeVlan *) * (array->len + 1))
|
||||
+ (sizeof (NMPlatformBridgeVlan ) * (array->len )));
|
||||
p_data = (NMPlatformBridgeVlan *) &arr[array->len + 1];
|
||||
|
||||
for (i = 0; i < array->len; i++) {
|
||||
NMBridgeVlan *vlan = array->pdata[i];
|
||||
NMPlatformBridgeVlan *plat_vlan;
|
||||
guint16 vid_start, vid_end;
|
||||
|
||||
plat_vlan = g_new0 (NMPlatformBridgeVlan, 1);
|
||||
plat_vlan->vid = nm_bridge_vlan_get_vid (vlan);
|
||||
plat_vlan->pvid = nm_bridge_vlan_is_pvid (vlan);
|
||||
plat_vlan->untagged = nm_bridge_vlan_is_untagged (vlan);
|
||||
nm_bridge_vlan_get_vid_range (vlan, &vid_start, &vid_end);
|
||||
|
||||
g_ptr_array_add (plat_vlans, plat_vlan);
|
||||
p_data[i] = (NMPlatformBridgeVlan) {
|
||||
.vid_start = vid_start,
|
||||
.vid_end = vid_end,
|
||||
.pvid = nm_bridge_vlan_is_pvid (vlan),
|
||||
.untagged = nm_bridge_vlan_is_untagged (vlan),
|
||||
};
|
||||
arr[i] = &p_data[i];
|
||||
}
|
||||
g_ptr_array_add (plat_vlans, NULL);
|
||||
|
||||
return (NMPlatformBridgeVlan **) g_ptr_array_free (plat_vlans, FALSE);
|
||||
arr[i] = NULL;
|
||||
return (const NMPlatformBridgeVlan **) arr;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -424,7 +430,7 @@ bridge_set_vlan_options (NMDevice *device, NMSettingBridge *s_bridge)
|
|||
NMPlatform *plat;
|
||||
int ifindex;
|
||||
gs_unref_ptrarray GPtrArray *vlans = NULL;
|
||||
nm_auto_freev NMPlatformBridgeVlan **plat_vlans = NULL;
|
||||
gs_free const NMPlatformBridgeVlan **plat_vlans = NULL;
|
||||
|
||||
if (self->vlan_configured)
|
||||
return TRUE;
|
||||
|
|
@ -479,8 +485,7 @@ bridge_set_vlan_options (NMDevice *device, NMSettingBridge *s_bridge)
|
|||
g_object_get (s_bridge, NM_SETTING_BRIDGE_VLANS, &vlans, NULL);
|
||||
plat_vlans = setting_vlans_to_platform (vlans);
|
||||
if ( plat_vlans
|
||||
&& !nm_platform_link_set_bridge_vlans (plat, ifindex, FALSE,
|
||||
(const NMPlatformBridgeVlan *const *) plat_vlans))
|
||||
&& !nm_platform_link_set_bridge_vlans (plat, ifindex, FALSE, plat_vlans))
|
||||
return FALSE;
|
||||
|
||||
if (!nm_platform_sysctl_master_set_option (plat, ifindex, "vlan_filtering", "1"))
|
||||
|
|
@ -568,8 +573,6 @@ enslave_slave (NMDevice *device,
|
|||
NMConnection *master_connection;
|
||||
NMSettingBridge *s_bridge;
|
||||
NMSettingBridgePort *s_port;
|
||||
gs_unref_ptrarray GPtrArray *vlans = NULL;
|
||||
nm_auto_freev NMPlatformBridgeVlan **plat_vlans = NULL;
|
||||
|
||||
if (configure) {
|
||||
if (!nm_platform_link_enslave (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)))
|
||||
|
|
@ -584,8 +587,12 @@ enslave_slave (NMDevice *device,
|
|||
bridge_set_vlan_options (device, s_bridge);
|
||||
|
||||
if (nm_setting_bridge_get_vlan_filtering (s_bridge)) {
|
||||
gs_free const NMPlatformBridgeVlan **plat_vlans = NULL;
|
||||
gs_unref_ptrarray GPtrArray *vlans = NULL;
|
||||
|
||||
if (s_port)
|
||||
g_object_get (s_port, NM_SETTING_BRIDGE_PORT_VLANS, &vlans, NULL);
|
||||
|
||||
plat_vlans = setting_vlans_to_platform (vlans);
|
||||
|
||||
/* Since the link was just enslaved, there are no existing VLANs
|
||||
|
|
@ -595,7 +602,7 @@ enslave_slave (NMDevice *device,
|
|||
&& !nm_platform_link_set_bridge_vlans (nm_device_get_platform (slave),
|
||||
nm_device_get_ifindex (slave),
|
||||
TRUE,
|
||||
(const NMPlatformBridgeVlan *const *) plat_vlans))
|
||||
plat_vlans))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6838,9 +6838,10 @@ link_set_bridge_vlans (NMPlatform *platform,
|
|||
/* Add VLANs */
|
||||
for (i = 0; vlans[i]; i++) {
|
||||
const NMPlatformBridgeVlan *vlan = vlans[i];
|
||||
gboolean is_range = vlan->vid_start != vlan->vid_end;
|
||||
|
||||
vinfo.vid = vlan->vid;
|
||||
vinfo.flags = 0;
|
||||
vinfo.vid = vlan->vid_start;
|
||||
vinfo.flags = is_range ? BRIDGE_VLAN_INFO_RANGE_BEGIN : 0;
|
||||
|
||||
if (vlan->untagged)
|
||||
vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
|
||||
|
|
@ -6848,6 +6849,12 @@ link_set_bridge_vlans (NMPlatform *platform,
|
|||
vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
|
||||
|
||||
NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo);
|
||||
|
||||
if (is_range) {
|
||||
vinfo.vid = vlan->vid_end;
|
||||
vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
|
||||
NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Flush existing VLANs */
|
||||
|
|
|
|||
|
|
@ -6542,14 +6542,18 @@ nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len)
|
|||
const char *
|
||||
nm_platform_bridge_vlan_to_string (const NMPlatformBridgeVlan *vlan, char *buf, gsize len)
|
||||
{
|
||||
char str_vid_end[64];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (vlan, &buf, &len))
|
||||
return buf;
|
||||
|
||||
g_snprintf (buf, len,
|
||||
"%u"
|
||||
"%s"
|
||||
"%s"
|
||||
"%s",
|
||||
vlan->vid,
|
||||
vlan->vid_start,
|
||||
vlan->vid_start != vlan->vid_end ? nm_sprintf_buf (str_vid_end, "-%u", vlan->vid_end) : "",
|
||||
vlan->pvid ? " PVID" : "",
|
||||
vlan->untagged ? " untagged" : "");
|
||||
|
||||
|
|
|
|||
|
|
@ -671,7 +671,8 @@ typedef struct {
|
|||
} NMPlatformVF;
|
||||
|
||||
typedef struct {
|
||||
guint16 vid;
|
||||
guint16 vid_start;
|
||||
guint16 vid_end;
|
||||
bool untagged:1;
|
||||
bool pvid:1;
|
||||
} NMPlatformBridgeVlan;
|
||||
|
|
|
|||
|
|
@ -5114,7 +5114,7 @@ read_bridge_vlans (shvarFile *ifcfg,
|
|||
|
||||
array = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref);
|
||||
|
||||
strv = nm_utils_strsplit_set (value, ",");
|
||||
strv = nm_utils_escaped_tokens_split (value, ",");
|
||||
if (strv) {
|
||||
for (iter = strv; *iter; iter++) {
|
||||
vlan = nm_bridge_vlan_from_str (*iter, &local);
|
||||
|
|
|
|||
|
|
@ -1491,8 +1491,8 @@ write_bridge_vlans (NMSetting *setting,
|
|||
if (!vlan_str)
|
||||
return FALSE;
|
||||
if (string->len > 0)
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, vlan_str);
|
||||
g_string_append (string, ",");
|
||||
nm_utils_escaped_tokens_escape_gstr_assert (vlan_str, ",", string);
|
||||
}
|
||||
|
||||
svSetValueStr (ifcfg, key, string->str);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ HWADDR=31:33:33:37:BE:CD
|
|||
MTU=1492
|
||||
TYPE=Ethernet
|
||||
BRIDGING_OPTS="priority=50 path_cost=33"
|
||||
BRIDGE_PORT_VLANS="1 untagged, 2 pvid untagged, 4"
|
||||
BRIDGE_PORT_VLANS="1 untagged,2 pvid,4-4094 untagged"
|
||||
NAME="Test Write Bridge Component"
|
||||
UUID=${UUID}
|
||||
ONBOOT=yes
|
||||
|
|
|
|||
|
|
@ -7651,14 +7651,14 @@ test_write_bridge_main (void)
|
|||
nm_connection_add_setting (connection, NM_SETTING (s_bridge));
|
||||
|
||||
vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref);
|
||||
vlan = nm_bridge_vlan_new (11);
|
||||
vlan = nm_bridge_vlan_new (10, 16);
|
||||
nm_bridge_vlan_set_untagged (vlan, TRUE);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
vlan = nm_bridge_vlan_new (22);
|
||||
vlan = nm_bridge_vlan_new (22, 22);
|
||||
nm_bridge_vlan_set_pvid (vlan, TRUE);
|
||||
nm_bridge_vlan_set_untagged (vlan, TRUE);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
vlan = nm_bridge_vlan_new (44);
|
||||
vlan = nm_bridge_vlan_new (44, 0);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
|
||||
g_object_set (s_bridge,
|
||||
|
|
@ -7774,14 +7774,14 @@ test_write_bridge_component (void)
|
|||
|
||||
/* Bridge port */
|
||||
vlans = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_bridge_vlan_unref);
|
||||
vlan = nm_bridge_vlan_new (1);
|
||||
vlan = nm_bridge_vlan_new (1, 0);
|
||||
nm_bridge_vlan_set_untagged (vlan, TRUE);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
vlan = nm_bridge_vlan_new (2);
|
||||
vlan = nm_bridge_vlan_new (4, 4094);
|
||||
nm_bridge_vlan_set_untagged (vlan, TRUE);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
vlan = nm_bridge_vlan_new (2, 2);
|
||||
nm_bridge_vlan_set_pvid (vlan, TRUE);
|
||||
nm_bridge_vlan_set_untagged (vlan, TRUE);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
vlan = nm_bridge_vlan_new (4);
|
||||
g_ptr_array_add (vlans, vlan);
|
||||
|
||||
s_port = nm_setting_bridge_port_new ();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue