Commit 5d851c0f authored by Thomas Haller's avatar Thomas Haller

libnm,platform: merge branch 'th/various-cleanup-platform-libnm'

NetworkManager/NetworkManager!131
parents 143f518c f2ae994b
Pipeline #35691 passed with stages
in 23 minutes and 3 seconds
...@@ -1212,25 +1212,22 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) ...@@ -1212,25 +1212,22 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
g_hash_table_remove (route->attributes, name); g_hash_table_remove (route->attributes, name);
} }
#define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \ static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = {
&(NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type } NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ),
static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = { NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
NULL, NULL,
}; };
......
...@@ -365,17 +365,14 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name) ...@@ -365,17 +365,14 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name)
return g_hash_table_lookup (vf->attributes, name); return g_hash_table_lookup (vf->attributes, name);
} }
#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \ const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = {
&(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type } NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, .str_type = 'm', ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, ),
const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = { NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ),
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ),
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, 0), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ),
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, 0),
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, 0),
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, 0),
/* D-Bus only, synthetic attributes */ /* D-Bus only, synthetic attributes */
SRIOV_ATTR_SPEC_PTR ("vlans", G_VARIANT_TYPE_STRING, 'd'), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("vlans", G_VARIANT_TYPE_STRING, .str_type = 'd', ),
NULL, NULL,
}; };
......
...@@ -38,6 +38,13 @@ struct _NMVariantAttributeSpec { ...@@ -38,6 +38,13 @@ struct _NMVariantAttributeSpec {
char str_type; char str_type;
}; };
#define NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(_name, _type, ...) \
(&((const NMVariantAttributeSpec) { \
.name = _name, \
.type = _type, \
__VA_ARGS__ \
}))
gboolean _nm_utils_string_slist_validate (GSList *list, gboolean _nm_utils_string_slist_validate (GSList *list,
const char **valid_values); const char **valid_values);
......
...@@ -2279,50 +2279,76 @@ _nm_utils_string_append_tc_parent (GString *string, const char *prefix, guint32 ...@@ -2279,50 +2279,76 @@ _nm_utils_string_append_tc_parent (GString *string, const char *prefix, guint32
guint32 guint32
_nm_utils_parse_tc_handle (const char *str, GError **error) _nm_utils_parse_tc_handle (const char *str, GError **error)
{ {
gint64 maj, min; gint64 maj;
char *sep; gint64 min = 0;
const char *sep;
maj = g_ascii_strtoll (str, &sep, 0x10); nm_assert (str);
if (*sep == ':')
min = g_ascii_strtoll (&sep[1], &sep, 0x10); maj = g_ascii_strtoll (str, (char **) &sep, 0x10);
else if (sep == str)
min = 0; goto fail;
sep = nm_str_skip_leading_spaces (sep);
if (sep[0] == ':') {
const char *str2 = &sep[1];
min = g_ascii_strtoll (str2, (char **) &sep, 0x10);
sep = nm_str_skip_leading_spaces (sep);
if (sep[0] != '\0')
goto fail;
} else if (sep[0] != '\0')
goto fail;
if (*sep != '\0' || maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff) { if ( maj <= 0
g_set_error (error, 1, 0, _("'%s' is not a valid handle."), str); || maj > 0xffff
return TC_H_UNSPEC; || min < 0
|| min > 0xffff
|| !NM_STRCHAR_ALL (str, ch, ( g_ascii_isxdigit (ch)
|| ch == ':'
|| g_ascii_isspace (ch)))) {
goto fail;
} }
return TC_H_MAKE (maj << 16, min); return TC_H_MAKE (((guint32) maj) << 16, (guint32) min);
fail:
nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid handle."), str);
return TC_H_UNSPEC;
} }
#define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \ static const NMVariantAttributeSpec *const tc_object_attribute_spec[] = {
&(NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type } NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("root", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("parent", G_VARIANT_TYPE_STRING, .str_type = 'a', ),
static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = { NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("handle", G_VARIANT_TYPE_STRING, .str_type = 'a', ),
TC_ATTR_SPEC_PTR ("root", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
TC_ATTR_SPEC_PTR ("parent", G_VARIANT_TYPE_STRING, FALSE, FALSE, 'a' ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
TC_ATTR_SPEC_PTR ("handle", G_VARIANT_TYPE_STRING, FALSE, FALSE, 'a' ),
TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ),
TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ),
NULL, NULL,
}; };
static const NMVariantAttributeSpec * const tc_qdisc_fq_codel_spec[] = { static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
TC_ATTR_SPEC_PTR ("limit", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("limit", G_VARIANT_TYPE_UINT32, ),
TC_ATTR_SPEC_PTR ("flows", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("flows", G_VARIANT_TYPE_UINT32, ),
TC_ATTR_SPEC_PTR ("target", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("target", G_VARIANT_TYPE_UINT32, ),
TC_ATTR_SPEC_PTR ("interval", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ),
TC_ATTR_SPEC_PTR ("quantum", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ),
TC_ATTR_SPEC_PTR ("ce_threshold", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
TC_ATTR_SPEC_PTR ("memory", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ), /* 0x83126E97u is not a valid value (it means "disabled"). We should reject that
TC_ATTR_SPEC_PTR ("ecn", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), * value. Or alternatively, reject all values >= MAX_INT(32). */
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ce_threshold", G_VARIANT_TYPE_UINT32, ),
/* kernel clamps the value at 2^31. Possibly such values should be rejected from configuration
* as they cannot be configured. Leaving the attribute unspecified causes kernel to choose
* a default (currently 32MB). */
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory_limit", G_VARIANT_TYPE_UINT32, ),
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
NULL, NULL,
}; };
typedef struct { typedef struct {
const char *kind; const char *kind;
const NMVariantAttributeSpec * const *attrs; const NMVariantAttributeSpec *const *attrs;
} NMQdiscAttributeSpec; } NMQdiscAttributeSpec;
static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = { static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = {
...@@ -2536,23 +2562,23 @@ nm_utils_tc_qdisc_from_str (const char *str, GError **error) ...@@ -2536,23 +2562,23 @@ nm_utils_tc_qdisc_from_str (const char *str, GError **error)
/*****************************************************************************/ /*****************************************************************************/
static const NMVariantAttributeSpec * const tc_action_simple_attribute_spec[] = { static const NMVariantAttributeSpec *const tc_action_simple_attribute_spec[] = {
TC_ATTR_SPEC_PTR ("sdata", G_VARIANT_TYPE_BYTESTRING, FALSE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("sdata", G_VARIANT_TYPE_BYTESTRING, ),
NULL, NULL,
}; };
static const NMVariantAttributeSpec * const tc_action_mirred_attribute_spec[] = { static const NMVariantAttributeSpec *const tc_action_mirred_attribute_spec[] = {
TC_ATTR_SPEC_PTR ("egress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("egress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
TC_ATTR_SPEC_PTR ("ingress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ingress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
TC_ATTR_SPEC_PTR ("mirror", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("mirror", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
TC_ATTR_SPEC_PTR ("redirect", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("redirect", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
TC_ATTR_SPEC_PTR ("dev", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("dev", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
NULL, NULL,
}; };
static const NMVariantAttributeSpec * const tc_action_attribute_spec[] = { static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = {
TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
NULL, NULL,
}; };
...@@ -2621,7 +2647,7 @@ nm_utils_tc_action_from_str (const char *str, GError **error) ...@@ -2621,7 +2647,7 @@ nm_utils_tc_action_from_str (const char *str, GError **error)
gs_unref_hashtable GHashTable *ht = NULL; gs_unref_hashtable GHashTable *ht = NULL;
gs_unref_hashtable GHashTable *options = NULL; gs_unref_hashtable GHashTable *options = NULL;
GVariant *variant; GVariant *variant;
const NMVariantAttributeSpec * const *attrs; const NMVariantAttributeSpec *const *attrs;
nm_assert (str); nm_assert (str);
nm_assert (!error || !*error); nm_assert (!error || !*error);
...@@ -2749,9 +2775,9 @@ nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error) ...@@ -2749,9 +2775,9 @@ nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error)
return g_string_free (string, FALSE); return g_string_free (string, FALSE);
} }
static const NMVariantAttributeSpec * const tc_tfilter_attribute_spec[] = { static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = {
TC_ATTR_SPEC_PTR ("action", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("action", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
NULL, NULL,
}; };
...@@ -6441,7 +6467,7 @@ nm_utils_parse_variant_attributes (const char *string, ...@@ -6441,7 +6467,7 @@ nm_utils_parse_variant_attributes (const char *string,
gs_unref_hashtable GHashTable *ht = NULL; gs_unref_hashtable GHashTable *ht = NULL;
const char *ptr = string, *start = NULL, *sep; const char *ptr = string, *start = NULL, *sep;
GVariant *variant; GVariant *variant;
const NMVariantAttributeSpec * const *s; const NMVariantAttributeSpec *const *s;
g_return_val_if_fail (string, NULL); g_return_val_if_fail (string, NULL);
g_return_val_if_fail (attr_separator, NULL); g_return_val_if_fail (attr_separator, NULL);
......
...@@ -3088,6 +3088,60 @@ test_routing_rule (gconstpointer test_data) ...@@ -3088,6 +3088,60 @@ test_routing_rule (gconstpointer test_data)
/*****************************************************************************/ /*****************************************************************************/
static void
test_parse_tc_handle (void)
{
#define _parse_tc_handle(str, exp) \
G_STMT_START { \
gs_free_error GError *_error = NULL; \
GError **_perror = nmtst_get_rand_bool () ? &_error : NULL; \
guint32 _v; \
const guint32 _v_exp = (exp); \
\
_v = _nm_utils_parse_tc_handle (""str"", _perror); \
\
if (_v != _v_exp) \
g_error ("%s:%d: \"%s\" gave %08x but %08x expected.", __FILE__, __LINE__, ""str"", _v, _v_exp); \
\
if (_v == TC_H_UNSPEC) \
g_assert (!_perror || *_perror); \
else \
g_assert (!_perror || !*_perror); \
\
} G_STMT_END
#define _parse_tc_handle_inval(str) _parse_tc_handle (str, TC_H_UNSPEC)
#define _parse_tc_handle_valid(str, maj, min) _parse_tc_handle (str, TC_H_MAKE (((guint32) (maj)) << 16, ((guint16) (min))))
_parse_tc_handle_inval ("");
_parse_tc_handle_inval (" ");
_parse_tc_handle_inval (" \n");
_parse_tc_handle_valid ("1", 1, 0);
_parse_tc_handle_valid(" 1 ", 1, 0);
_parse_tc_handle_valid ("1:", 1, 0);
_parse_tc_handle_valid ("1: ", 1, 0);
_parse_tc_handle_valid ("1:0", 1, 0);
_parse_tc_handle_valid ("1 :0", 1, 0);
_parse_tc_handle_valid ("1 \t\n\f\r:0", 1, 0);
_parse_tc_handle_inval ("1 \t\n\f\r\v:0");
_parse_tc_handle_valid (" 1 : 0 ", 1, 0);
_parse_tc_handle_inval (" \t\v\n1: 0");
_parse_tc_handle_valid ("1:2", 1, 2);
_parse_tc_handle_valid ("01:02", 1, 2);
_parse_tc_handle_inval ("0x01:0x02");
_parse_tc_handle_valid (" 01: 02", 1, 2);
_parse_tc_handle_valid ("019: 020", 0x19, 0x20);
_parse_tc_handle_valid ("FFFF: 020", 0xFFFF, 0x20);
_parse_tc_handle_valid ("FfFF: ffff", 0xFFFF, 0xFFFF);
_parse_tc_handle_valid ("FFFF", 0xFFFF, 0);
_parse_tc_handle_inval ("0xFFFF");
_parse_tc_handle_inval ("10000");
_parse_tc_handle_valid ("\t\n\f\r FFFF", 0xFFFF, 0);
_parse_tc_handle_inval ("\t\n\f\r \vFFFF");
}
/*****************************************************************************/
NMTST_DEFINE (); NMTST_DEFINE ();
int int
...@@ -3173,5 +3227,7 @@ main (int argc, char **argv) ...@@ -3173,5 +3227,7 @@ main (int argc, char **argv)
g_test_add_data_func ("/libnm/settings/routing-rule/1", GINT_TO_POINTER (0), test_routing_rule); g_test_add_data_func ("/libnm/settings/routing-rule/1", GINT_TO_POINTER (0), test_routing_rule);
g_test_add_func ("/libnm/parse-tc-handle", test_parse_tc_handle);
return g_test_run (); return g_test_run ();
} }
...@@ -734,10 +734,7 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma ...@@ -734,10 +734,7 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
gint64 v; gint64 v;
const char *s = NULL; const char *s = NULL;
if (str) { str = nm_str_skip_leading_spaces (str);
while (g_ascii_isspace (str[0]))
str++;
}
if (!str || !str[0]) { if (!str || !str[0]) {
errno = EINVAL; errno = EINVAL;
return fallback; return fallback;
...@@ -748,9 +745,9 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma ...@@ -748,9 +745,9 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
if (errno != 0) if (errno != 0)
return fallback; return fallback;
if (s[0] != '\0') { if (s[0] != '\0') {
while (g_ascii_isspace (s[0])) s = nm_str_skip_leading_spaces (s);
s++;
if (s[0] != '\0') { if (s[0] != '\0') {
errno = EINVAL; errno = EINVAL;
return fallback; return fallback;
......
...@@ -6500,7 +6500,7 @@ tc_commit (NMDevice *self) ...@@ -6500,7 +6500,7 @@ tc_commit (NMDevice *self)
NMSettingTCConfig *s_tc = NULL; NMSettingTCConfig *s_tc = NULL;
int ip_ifindex; int ip_ifindex;
guint nqdiscs, ntfilters; guint nqdiscs, ntfilters;
int i; guint i;
connection = nm_device_get_applied_connection (self); connection = nm_device_get_applied_connection (self);
if (connection) if (connection)
...@@ -6508,7 +6508,7 @@ tc_commit (NMDevice *self) ...@@ -6508,7 +6508,7 @@ tc_commit (NMDevice *self)
ip_ifindex = nm_device_get_ip_ifindex (self); ip_ifindex = nm_device_get_ip_ifindex (self);
if (!ip_ifindex) if (!ip_ifindex)
return s_tc == NULL; return s_tc == NULL;
if (s_tc) { if (s_tc) {
nqdiscs = nm_setting_tc_config_get_num_qdiscs (s_tc); nqdiscs = nm_setting_tc_config_get_num_qdiscs (s_tc);
...@@ -6520,7 +6520,12 @@ tc_commit (NMDevice *self) ...@@ -6520,7 +6520,12 @@ tc_commit (NMDevice *self)
NMPlatformQdisc *qdisc = NMP_OBJECT_CAST_QDISC (q); NMPlatformQdisc *qdisc = NMP_OBJECT_CAST_QDISC (q);
qdisc->ifindex = ip_ifindex; qdisc->ifindex = ip_ifindex;
/* Note: kind string is still owned by NMTCTfilter.
* This qdisc instance must not be kept alive beyond this function.
* nm_platform_qdisc_sync() promises to do that. */
qdisc->kind = nm_tc_qdisc_get_kind (s_qdisc); qdisc->kind = nm_tc_qdisc_get_kind (s_qdisc);
qdisc->addr_family = AF_UNSPEC; qdisc->addr_family = AF_UNSPEC;
qdisc->handle = nm_tc_qdisc_get_handle (s_qdisc); qdisc->handle = nm_tc_qdisc_get_handle (s_qdisc);
qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc); qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc);
...@@ -6537,14 +6542,14 @@ tc_commit (NMDevice *self) ...@@ -6537,14 +6542,14 @@ tc_commit (NMDevice *self)
} G_STMT_END } G_STMT_END
if (strcmp (qdisc->kind, "fq_codel") == 0) { if (strcmp (qdisc->kind, "fq_codel") == 0) {
GET_ATTR("limit", qdisc->fq_codel.limit, UINT32, uint32, 0); GET_ATTR ("limit", qdisc->fq_codel.limit, UINT32, uint32, 0);
GET_ATTR("flows", qdisc->fq_codel.flows, UINT32, uint32, 0); GET_ATTR ("flows", qdisc->fq_codel.flows, UINT32, uint32, 0);
GET_ATTR("target", qdisc->fq_codel.target, UINT32, uint32, 0); GET_ATTR ("target", qdisc->fq_codel.target, UINT32, uint32, 0);
GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0); GET_ATTR ("interval", qdisc->fq_codel.interval, UINT32, uint32, 0);
GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0); GET_ATTR ("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0);
GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, -1); GET_ATTR ("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED);
GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, -1); GET_ATTR ("memory_limit", qdisc->fq_codel.memory_limit, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET);
GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE); GET_ATTR ("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE);
} }
#undef GET_ADDR #undef GET_ADDR
...@@ -6562,7 +6567,12 @@ tc_commit (NMDevice *self) ...@@ -6562,7 +6567,12 @@ tc_commit (NMDevice *self)
NMPlatformTfilter *tfilter = NMP_OBJECT_CAST_TFILTER (q); NMPlatformTfilter *tfilter = NMP_OBJECT_CAST_TFILTER (q);
tfilter->ifindex = ip_ifindex; tfilter->ifindex = ip_ifindex;
/* Note: kind string is still owned by NMTCTfilter.
* This tfilter instance must not be kept alive beyond this function.
* nm_platform_tfilter_sync() promises to do that. */
tfilter->kind = nm_tc_tfilter_get_kind (s_tfilter); tfilter->kind = nm_tc_tfilter_get_kind (s_tfilter);
tfilter->addr_family = AF_UNSPEC; tfilter->addr_family = AF_UNSPEC;
tfilter->handle = nm_tc_tfilter_get_handle (s_tfilter); tfilter->handle = nm_tc_tfilter_get_handle (s_tfilter);
tfilter->parent = nm_tc_tfilter_get_parent (s_tfilter); tfilter->parent = nm_tc_tfilter_get_parent (s_tfilter);
...@@ -6572,7 +6582,11 @@ tc_commit (NMDevice *self) ...@@ -6572,7 +6582,11 @@ tc_commit (NMDevice *self)
if (action) { if (action) {
GVariant *var; GVariant *var;
/* Note: kind string is still owned by NMTCAction.
* This tfilter instance must not be kept alive beyond this function.
* nm_platform_tfilter_sync() promises to do that. */
tfilter->action.kind = nm_tc_action_get_kind (action); tfilter->action.kind = nm_tc_action_get_kind (action);
if (strcmp (tfilter->action.kind, "simple") == 0) { if (strcmp (tfilter->action.kind, "simple") == 0) {
var = nm_tc_action_get_attribute (action, "sdata"); var = nm_tc_action_get_attribute (action, "sdata");
if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) { if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) {
...@@ -6595,9 +6609,12 @@ tc_commit (NMDevice *self) ...@@ -6595,9 +6609,12 @@ tc_commit (NMDevice *self)
var = nm_tc_action_get_attribute (action, "dev"); var = nm_tc_action_get_attribute (action, "dev");
if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) { if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) {
int ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self), int ifindex;
g_variant_get_string (var, NULL));
tfilter->action.mirred.ifindex = ifindex; ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self),
g_variant_get_string (var, NULL));
if (ifindex > 0)
tfilter->action.mirred.ifindex = ifindex;
} }
} }
} }
......
...@@ -3515,6 +3515,11 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) ...@@ -3515,6 +3515,11 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
obj->qdisc.parent = tcm->tcm_parent; obj->qdisc.parent = tcm->tcm_parent;
obj->qdisc.info = tcm->tcm_info; obj->qdisc.info = tcm->tcm_info;
if (nm_streq0 (obj->qdisc.kind, "fq_codel")) {
obj->qdisc.fq_codel.memory_limit = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET;
obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED;
}
if (tb[TCA_OPTIONS]) { if (tb[TCA_OPTIONS]) {
struct nlattr *options_attr; struct nlattr *options_attr;
int remaining; int remaining;
...@@ -3544,10 +3549,10 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only) ...@@ -3544,10 +3549,10 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr); obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr);
break; break;
case TCA_FQ_CODEL_MEMORY_LIMIT: case TCA_FQ_CODEL_MEMORY_LIMIT:
obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr); obj->qdisc.fq_codel.memory_limit = nla_get_u32 (options_attr);
break; break;
case TCA_FQ_CODEL_ECN: case TCA_FQ_CODEL_ECN:
obj->qdisc.fq_codel.ecn = nla_get_u32 (options_attr); obj->qdisc.fq_codel.ecn = !!nla_get_u32 (options_attr);
break; break;
} }
} }
...@@ -3676,7 +3681,7 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg, ...@@ -3676,7 +3681,7 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg,
return TRUE; return TRUE;
nla_put_failure: nla_put_failure:
return FALSE; g_return_val_if_reached (FALSE);
} }
static gboolean static gboolean
...@@ -3827,7 +3832,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg, ...@@ -3827,7 +3832,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg,
return TRUE; return TRUE;
nla_put_failure: nla_put_failure:
return FALSE; g_return_val_if_reached (FALSE);
} }
static struct nl_msg * static struct nl_msg *
...@@ -4239,12 +4244,12 @@ _nl_msg_new_qdisc (int nlmsg_type, ...@@ -4239,12 +4244,12 @@ _nl_msg_new_qdisc (int nlmsg_type,
NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval);
if (qdisc->fq_codel.quantum) if (qdisc->fq_codel.quantum)
NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum);
if (qdisc->fq_codel.ce_threshold != -1) if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED)
NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold);
if (qdisc->fq_codel.memory != -1) if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory); NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory_limit);
if (qdisc->fq_codel.ecn) if (qdisc->fq_codel.ecn)
NLA_PUT_S32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn);
} }
nla_nest_end (msg, tc_options); nla_nest_end (msg, tc_options);
...@@ -4255,83 +4260,6 @@ nla_put_failure: ...@@ -4255,83 +4260,6 @@ nla_put_failure:
g_return_val_if_reached (NULL); g_return_val_if_reached (NULL);
} }
static gboolean
_add_action_simple (struct nl_msg *msg,
const NMPlatformActionSimple *simple)
{
struct nlattr *act_options;
struct tc_defact sel = { 0, };
if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS)))
goto nla_put_failure;
NLA_PUT (msg, TCA_DEF_PARMS, sizeof (sel), &sel);
NLA_PUT (msg, TCA_DEF_DATA, sizeof (simple->sdata), simple->sdata);
nla_nest_end (msg, act_options);
return TRUE;
nla_put_failure:
return FALSE;
}
static gboolean
_add_action_mirred (struct nl_msg *msg,
const NMPlatformActionMirred *mirred)
{
struct nlattr *act_options;
struct tc_mirred sel = { 0, };
if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS)))
goto nla_put_failure;
if (mirred->egress && mirred->redirect)
sel.eaction = TCA_EGRESS_REDIR;
else if (mirred->egress && mirred->mirror)
sel.eaction = TCA_EGRESS_MIRROR;
else if (mirred->ingress && mirred->redirect)
sel.eaction = TCA_INGRESS_REDIR;
else if (mirred->ingress && mirred->mirror)
sel.eaction = TCA_INGRESS_MIRROR;
sel.ifindex = mirred->ifindex;
NLA_PUT (msg, TCA_MIRRED_PARMS, sizeof (sel), &sel);
nla_nest_end (msg, act_options);
return TRUE;
nla_put_failure:
return FALSE;
}
static gboolean
_add_action (struct nl_msg *msg,
const NMPlatformAction *action)
{
struct nlattr *prio;
nm_assert (action || action->kind);
if (!(prio = nla_nest_start (msg, 1 /* priority */)))
goto nla_put_failure;
NLA_PUT_STRING (msg, TCA_ACT_KIND, action->kind);
if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE))
_add_action_simple (msg, &action->simple);
else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED))
_add_action_mirred (msg, &action->mirred);
nla_nest_end (msg, prio);