diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2017-11-28 09:26:14 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2017-12-11 11:02:04 +0100 |
commit | de41c45e616c1b92c22462feb72653cbaeb51f67 (patch) | |
tree | a8028b8e0392695465a7236bec75013198306ba4 | |
parent | e035cb7be054d5377116a781cbeeb90ed53c283c (diff) | |
download | NetworkManager-de41c45e616c1b92c22462feb72653cbaeb51f67.tar.gz |
libnm-core: add functionality for dealing with tc-style traffic filter specifiers
Tailored to fit both nmcli and keyfile needs.
-rw-r--r-- | libnm-core/nm-utils.c | 139 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 5 | ||||
-rw-r--r-- | libnm/libnm.ver | 2 |
3 files changed, 146 insertions, 0 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index b9a50e11f6..73eb4b520b 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -2466,6 +2466,145 @@ nm_utils_tc_action_from_str (const char *str, GError **error) /*****************************************************************************/ /** + * _nm_utils_string_append_tc_tfilter_rest: + * @string: the string to write the formatted tfilter to + * @tfilter: the %NMTCTfilter + * + * This formats the rest of the tfilter string but the parent. Useful to format + * the keyfile value and nowhere else. + * Use nm_utils_tc_tfilter_to_str() that also includes the parent instead. + */ +gboolean +_nm_utils_string_append_tc_tfilter_rest (GString *string, NMTCTfilter *tfilter, GError **error) +{ + guint32 handle = nm_tc_tfilter_get_handle (tfilter); + const char *kind = nm_tc_tfilter_get_kind (tfilter); + NMTCAction *action; + + if (handle != TC_H_UNSPEC) { + g_string_append (string, "handle "); + _string_append_tc_handle (string, handle); + g_string_append_c (string, ' '); + } + + g_string_append (string, kind); + + action = nm_tc_tfilter_get_action (tfilter); + if (action) { + g_string_append (string, " action "); + if (!_string_append_tc_action (string, action, error)) + return FALSE; + } + + return TRUE; +} + +/** + * nm_utils_tc_tfilter_to_str: + * @tfilter: the %NMTCTfilter + * @error: location of the error + * + * Turns the %NMTCTfilter into a tc style string representation of the queueing + * discipline. + * + * Returns: formatted string or %NULL + * + * Since: 1.12 + */ +char * +nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error) +{ + GString *string; + + string = g_string_sized_new (60); + + _nm_utils_string_append_tc_parent (string, "parent", + nm_tc_tfilter_get_parent (tfilter)); + if (!_nm_utils_string_append_tc_tfilter_rest (string, tfilter, error)) { + g_string_free (string, TRUE); + return NULL; + } + + return g_string_free (string, FALSE); +} + +static const NMVariantAttributeSpec * const tc_tfilter_attribute_spec[] = { + TC_ATTR_SPEC_PTR ("action", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), + TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), + NULL, +}; + +/** + * nm_utils_tc_tfilter_from_str: + * @str: the string representation of a tfilter + * @error: location of the error + * + * Parces the tc style string tfilter representation of the queueing + * discipline to a %NMTCTfilter instance. Supports a subset of the tc language. + * + * Returns: the %NMTCTfilter or %NULL + * + * Since: 1.12 + */ +NMTCTfilter * +nm_utils_tc_tfilter_from_str (const char *str, GError **error) +{ + guint32 handle = TC_H_UNSPEC; + guint32 parent = TC_H_UNSPEC; + gs_free char *kind = NULL; + gs_free char *rest = NULL; + NMTCAction *action = NULL; + const char *extra_opts = NULL; + NMTCTfilter *tfilter = NULL; + gs_unref_hashtable GHashTable *ht = NULL; + GVariant *variant; + + nm_assert (str); + nm_assert (!error || !*error); + + if (!_tc_read_common_opts (str, &handle, &parent, &kind, &rest, error)) + return NULL; + + if (rest) { + ht = nm_utils_parse_variant_attributes (rest, + ' ', ' ', FALSE, + tc_tfilter_attribute_spec, + error); + if (!ht) + return NULL; + + variant = g_hash_table_lookup (ht, ""); + if (variant) + extra_opts = g_variant_get_string (variant, NULL); + + if (g_hash_table_contains (ht, "action")) { + action = nm_utils_tc_action_from_str (extra_opts, error); + if (!action) { + g_prefix_error (error, _("invalid action: ")); + return NULL; + } + } else { + g_set_error (error, 1, 0, _("unsupported tfilter option: '%s'."), rest); + return NULL; + } + } + + tfilter = nm_tc_tfilter_new (kind, parent, error); + if (!tfilter) + return NULL; + + nm_tc_tfilter_set_handle (tfilter, handle); + if (action) { + nm_tc_tfilter_set_action (tfilter, action); + nm_tc_action_unref (action); + } + + return tfilter; +} + +/*****************************************************************************/ + +/** * nm_utils_uuid_generate_buf_: * @buf: input buffer, must contain at least 37 bytes * diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 10e81d668e..1f645a8042 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -243,6 +243,11 @@ NMTCAction *nm_utils_tc_action_from_str (const char *str, GError **error); NM_AVAILABLE_IN_1_12 char *nm_utils_tc_action_to_str (NMTCAction *action, GError **error); +NM_AVAILABLE_IN_1_12 +NMTCTfilter *nm_utils_tc_tfilter_from_str (const char *str, GError **error); +NM_AVAILABLE_IN_1_12 +char *nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error); + G_END_DECLS #endif /* __NM_UTILS_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index e620725437..5ad7b798ae 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1284,6 +1284,8 @@ global: nm_utils_tc_action_to_str; nm_utils_tc_qdisc_from_str; nm_utils_tc_qdisc_to_str; + nm_utils_tc_tfilter_from_str; + nm_utils_tc_tfilter_to_str; } libnm_1_10_0; libnm_1_12_0 { |