summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-11-28 09:26:14 +0100
committerLubomir Rintel <lkundrak@v3.sk>2017-12-11 11:02:04 +0100
commitde41c45e616c1b92c22462feb72653cbaeb51f67 (patch)
treea8028b8e0392695465a7236bec75013198306ba4
parente035cb7be054d5377116a781cbeeb90ed53c283c (diff)
downloadNetworkManager-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.c139
-rw-r--r--libnm-core/nm-utils.h5
-rw-r--r--libnm/libnm.ver2
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 {