libnm: refactor parsing of NMVlanQosMapping and support wildcard for "to"

- avoid the memory allocations by not using g_strsplit().

- add a helper function priority_map_parse_str(). This will
  be used later, to avoid allocating a NMVlanQosMapping
  result, when we don't need it on the heap.

- for the priority mappings, the "from" part is the key and must
  be unique. As such, it would make sense to say

    $ nmcli connection modify "$PROFILE" -vlan.ingress-priority-map '1:*'

  or

    $ nmcli connection modify "$PROFILE" -vlan.ingress-priority-map '1:'

  to delete any mapping for that priority, regardless of the "to" part.
  Add an option to leave the "to" part unspecified. This will be used
  later.
This commit is contained in:
Thomas Haller
2019-03-16 13:43:17 +01:00
parent 395738900f
commit aaaccfd264

View File

@@ -116,38 +116,87 @@ get_max_prio (NMVlanPriorityMap map, gboolean from)
g_assert_not_reached ();
}
static gboolean
priority_map_parse_str (NMVlanPriorityMap map_type,
const char *str,
gboolean allow_wildcard_to,
guint32 *out_from,
guint32 *out_to,
gboolean *out_has_wildcard_to)
{
const char *s2;
gint64 v1, v2;
nm_assert (str);
s2 = strchr (str, ':');
if (!s2) {
if (!allow_wildcard_to)
return FALSE;
v1 = _nm_utils_ascii_str_to_int64 (str, 10, 0, G_MAXUINT32, -1);
v2 = -1;
} else {
gs_free char *s1_free = NULL;
gsize s1_len = (s2 - str);
s2 = nm_str_skip_leading_spaces (&s2[1]);
if ( s2[0] == '\0'
|| ( s2[0] == '*'
&& NM_STRCHAR_ALL (&s2[1], ch, g_ascii_isspace (ch)))) {
if (!allow_wildcard_to)
return FALSE;
v2 = -1;
} else {
v2 = _nm_utils_ascii_str_to_int64 (s2, 10, 0, G_MAXUINT32, -1);
if ( v2 < 0
|| v2 > get_max_prio (map_type, FALSE))
return FALSE;
}
v1 = _nm_utils_ascii_str_to_int64 (nm_strndup_a (100, str, s1_len, &s1_free),
10, 0, G_MAXUINT32, -1);
}
if ( v1 < 0
|| v1 > get_max_prio (map_type, TRUE))
return FALSE;
NM_SET_OUT (out_from, v1);
NM_SET_OUT (out_to, v2 < 0
? 0u
: (guint) v2);
NM_SET_OUT (out_has_wildcard_to, v2 < 0);
return TRUE;
}
static NMVlanQosMapping *
priority_map_new (guint32 from, guint32 to)
{
NMVlanQosMapping *mapping;
mapping = g_new (NMVlanQosMapping, 1);
*mapping = (NMVlanQosMapping) {
.from = from,
.to = to,
};
return mapping;
}
static NMVlanQosMapping *
priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
{
NMVlanQosMapping *p = NULL;
char **t = NULL;
guint32 len;
guint64 from, to;
guint32 from, to;
g_return_val_if_fail (str && str[0], NULL);
t = g_strsplit (str, ":", 0);
len = g_strv_length (t);
if (len == 2) {
from = g_ascii_strtoull (t[0], NULL, 10);
to = g_ascii_strtoull (t[1], NULL, 10);
if ((from <= get_max_prio (map, TRUE)) && (to <= get_max_prio (map, FALSE))) {
G_STATIC_ASSERT (sizeof (*p) == sizeof (p->from) + sizeof (p->to));
p = g_malloc (sizeof (NMVlanQosMapping));
p->from = from;
p->to = to;
}
}
g_strfreev (t);
return p;
if (!priority_map_parse_str (map, str, FALSE, &from, &to, NULL))
return NULL;
return priority_map_new (from, to);
}
static void
priority_map_free (NMVlanQosMapping *map)
{
g_return_if_fail (map != NULL);
nm_assert (map);
g_free (map);
}