libnm-core: add bridge vlan conversion utils

This commit is contained in:
Beniamino Galvani 2019-03-19 15:35:28 +01:00
parent a680bedf94
commit cf71860183
6 changed files with 188 additions and 1 deletions

View file

@ -752,4 +752,8 @@ gboolean nm_utils_base64secret_normalize (const char *base64_key,
/*****************************************************************************/
void _nm_bridge_vlan_str_append_rest (const NMBridgeVlan *vlan,
GString *string,
gboolean leading_space);
#endif

View file

@ -358,6 +358,124 @@ nm_bridge_vlan_new_clone (const NMBridgeVlan *vlan)
return copy;
}
void
_nm_bridge_vlan_str_append_rest (const NMBridgeVlan *vlan,
GString *string,
gboolean leading_space)
{
if (nm_bridge_vlan_is_pvid (vlan)) {
if (leading_space)
g_string_append_c (string, ' ');
g_string_append (string, "pvid");
leading_space = TRUE;
}
if (nm_bridge_vlan_is_untagged (vlan)) {
if (leading_space)
g_string_append_c (string, ' ');
g_string_append (string, "untagged");
leading_space = TRUE;
}
}
/**
* 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)
{
GString *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 = g_string_sized_new (20);
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);
}
/**
* 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_unref_hashtable GHashTable *ht = NULL;
gs_free const char **tokens = NULL;
guint i, vid;
gboolean pvid = FALSE;
gboolean untagged = FALSE;
g_return_val_if_fail (str, NULL);
g_return_val_if_fail (!error || !*error, NULL);
tokens = nm_utils_strsplit_set (str, " ", FALSE);
if (!tokens || !tokens[0]) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"missing VLAN id");
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) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_FAILED,
"invalid VLAN id '%s', must be in [1,4094]", tokens[0]);
return NULL;
}
for (i = 1; tokens[i]; i++) {
if (nm_streq (tokens[i], "pvid"))
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);
nm_bridge_vlan_set_pvid (vlan, pvid);
nm_bridge_vlan_set_untagged (vlan, untagged);
return vlan;
}
/*****************************************************************************/
static int

View file

@ -139,6 +139,11 @@ gboolean nm_bridge_vlan_is_untagged (const NMBridgeVlan *vlan);
NM_AVAILABLE_IN_1_18
gboolean nm_bridge_vlan_is_pvid (const NMBridgeVlan *vlan);
NM_AVAILABLE_IN_1_18
char * nm_bridge_vlan_to_str (const NMBridgeVlan *vlan, GError **error);
NM_AVAILABLE_IN_1_18
NMBridgeVlan * nm_bridge_vlan_from_str (const char *str, GError **error);
G_END_DECLS
#endif /* __NM_SETTING_BRIDGE_H__ */

View file

@ -6849,4 +6849,3 @@ _nm_utils_bridge_vlan_verify_list (GPtrArray *vlans,
return TRUE;
}

View file

@ -1658,6 +1658,63 @@ test_sriov_parse_vlans (void)
test_sriov_parse_vlan_one ("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0});
}
static void
test_bridge_vlans (void)
{
NMBridgeVlan *v1, *v2;
GError *error = NULL;
char *str;
v1 = nm_bridge_vlan_from_str ("1 foobar", &error);
nmtst_assert_no_success (v1, error);
g_clear_error (&error);
v1 = nm_bridge_vlan_from_str ("4095", &error);
nmtst_assert_no_success (v1, error);
g_clear_error (&error);
/* 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_is_sealed (v1), ==, FALSE);
g_assert_cmpint (nm_bridge_vlan_is_pvid (v1), ==, FALSE);
g_assert_cmpint (nm_bridge_vlan_is_untagged (v1), ==, TRUE);
nm_bridge_vlan_set_pvid (v1, TRUE);
nm_bridge_vlan_set_untagged (v1, FALSE);
nm_bridge_vlan_seal (v1);
g_assert_cmpint (nm_bridge_vlan_is_sealed (v1), ==, TRUE);
g_assert_cmpint (nm_bridge_vlan_is_pvid (v1), ==, TRUE);
g_assert_cmpint (nm_bridge_vlan_is_untagged (v1), ==, FALSE);
str = nm_bridge_vlan_to_str (v1, &error);
nmtst_assert_success (str, error);
g_assert_cmpstr (str, ==, "10 pvid");
g_clear_pointer (&str, g_free);
v2 = nm_bridge_vlan_from_str (" 10 pvid ", &error);
nmtst_assert_success (v2, error);
g_assert_cmpint (nm_bridge_vlan_cmp (v1, v2), ==, 0);
nm_bridge_vlan_unref (v1);
nm_bridge_vlan_unref (v2);
/* test comparison (2) */
v1 = nm_bridge_vlan_from_str ("10", &error);
nmtst_assert_success (v1, error);
v2 = nm_bridge_vlan_from_str ("20", &error);
nmtst_assert_success (v2, error);
g_assert_cmpint (nm_bridge_vlan_cmp (v1, v2), <, 0);
nm_bridge_vlan_unref (v1);
nm_bridge_vlan_unref (v2);
}
/*****************************************************************************/
static void
@ -2663,6 +2720,8 @@ main (int argc, char **argv)
g_test_add_func ("/libnm/settings/tc_config/setting/duplicates", test_tc_config_setting_duplicates);
g_test_add_func ("/libnm/settings/tc_config/dbus", test_tc_config_dbus);
g_test_add_func ("/libnm/settings/bridge/vlans", test_bridge_vlans);
#if WITH_JSON_VALIDATION
g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin",
test_runner_roundrobin_sync_from_config);

View file

@ -1522,6 +1522,7 @@ global:
libnm_1_18_0 {
global:
nm_bridge_vlan_cmp;
nm_bridge_vlan_from_str;
nm_bridge_vlan_get_type;
nm_bridge_vlan_get_vid;
nm_bridge_vlan_is_pvid;
@ -1533,6 +1534,7 @@ global:
nm_bridge_vlan_seal;
nm_bridge_vlan_set_pvid;
nm_bridge_vlan_set_untagged;
nm_bridge_vlan_to_str;
nm_bridge_vlan_unref;
nm_setting_bridge_add_vlan;
nm_setting_bridge_clear_vlans;