Commit de41c45e authored by Lubomir Rintel's avatar Lubomir Rintel

libnm-core: add functionality for dealing with tc-style traffic filter specifiers

Tailored to fit both nmcli and keyfile needs.
parent e035cb7b
......@@ -2465,6 +2465,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
......
......@@ -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__ */
......@@ -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 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment