You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2449 lines
97 KiB
2449 lines
97 KiB
5 years ago
|
From 67047a444d45dd6e74d381cfe06a418c13693539 Mon Sep 17 00:00:00 2001
|
||
|
From: Lubomir Rintel <lkundrak@v3.sk>
|
||
|
Date: Tue, 9 Apr 2019 13:42:52 +0200
|
||
|
Subject: [PATCH 01/20] tc/qdisc: add support for fq_codel attributes
|
||
|
|
||
|
(cherry picked from commit 1efe982e39be7e8b7852a19957c7b49cab46e67c)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 13 ++++++
|
||
|
src/devices/nm-device.c | 23 ++++++++++
|
||
|
src/platform/nm-linux-platform.c | 72 ++++++++++++++++++++++++++++++++
|
||
|
src/platform/nm-platform.c | 55 ++++++++++++++++++++----
|
||
|
src/platform/nm-platform.h | 14 +++++++
|
||
|
5 files changed, 170 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 04d5b1b558..b82c580345 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2309,12 +2309,25 @@ static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = {
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
+static const NMVariantAttributeSpec * const tc_qdisc_fq_codel_spec[] = {
|
||
|
+ TC_ATTR_SPEC_PTR ("limit", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("flows", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("target", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("interval", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("quantum", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
+ 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 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("ecn", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+ NULL,
|
||
|
+};
|
||
|
+
|
||
|
typedef struct {
|
||
|
const char *kind;
|
||
|
const NMVariantAttributeSpec * const *attrs;
|
||
|
} NMQdiscAttributeSpec;
|
||
|
|
||
|
static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = {
|
||
|
+ &(const NMQdiscAttributeSpec) { "fq_codel", tc_qdisc_fq_codel_spec },
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index 60709c50d5..195686707b 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6522,6 +6522,29 @@ tc_commit (NMDevice *self)
|
||
|
qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc);
|
||
|
qdisc->info = 0;
|
||
|
|
||
|
+#define GET_ATTR(name, dst, variant_type, type, dflt) G_STMT_START { \
|
||
|
+ GVariant *_variant = nm_tc_qdisc_get_attribute (s_qdisc, ""name""); \
|
||
|
+ \
|
||
|
+ if ( _variant \
|
||
|
+ && g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \
|
||
|
+ (dst) = g_variant_get_ ## type (_variant); \
|
||
|
+ else \
|
||
|
+ (dst) = (dflt); \
|
||
|
+} G_STMT_END
|
||
|
+
|
||
|
+ if (strcmp (qdisc->kind, "fq_codel") == 0) {
|
||
|
+ GET_ATTR("limit", qdisc->fq_codel.limit, 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("interval", qdisc->fq_codel.interval, 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("memory", qdisc->fq_codel.memory, UINT32, uint32, -1);
|
||
|
+ GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE);
|
||
|
+ }
|
||
|
+
|
||
|
+#undef GET_ADDR
|
||
|
+
|
||
|
g_ptr_array_add (qdiscs, q);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index d4b0115252..a346d6618c 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -84,6 +84,13 @@ enum {
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
|
||
|
+/* Compat with older kernels. */
|
||
|
+
|
||
|
+#define TCA_FQ_CODEL_CE_THRESHOLD 7
|
||
|
+#define TCA_FQ_CODEL_MEMORY_LIMIT 9
|
||
|
+
|
||
|
+/*****************************************************************************/
|
||
|
+
|
||
|
#define VLAN_FLAG_MVRP 0x8
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
@@ -3481,6 +3488,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
{
|
||
|
static const struct nla_policy policy[] = {
|
||
|
[TCA_KIND] = { .type = NLA_STRING },
|
||
|
+ [TCA_OPTIONS] = { .type = NLA_NESTED },
|
||
|
};
|
||
|
struct nlattr *tb[G_N_ELEMENTS (policy)];
|
||
|
const struct tcmsg *tcm;
|
||
|
@@ -3506,6 +3514,45 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.parent = tcm->tcm_parent;
|
||
|
obj->qdisc.info = tcm->tcm_info;
|
||
|
|
||
|
+ if (tb[TCA_OPTIONS]) {
|
||
|
+ struct nlattr *options_attr;
|
||
|
+ int remaining;
|
||
|
+
|
||
|
+ nla_for_each_nested (options_attr, tb[TCA_OPTIONS], remaining) {
|
||
|
+ if (nla_len (options_attr) < sizeof (uint32_t))
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if (nm_streq0 (obj->qdisc.kind, "fq_codel")) {
|
||
|
+ switch (nla_type (options_attr)) {
|
||
|
+ case TCA_FQ_CODEL_LIMIT:
|
||
|
+ obj->qdisc.fq_codel.limit = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_FLOWS:
|
||
|
+ obj->qdisc.fq_codel.flows = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_TARGET:
|
||
|
+ obj->qdisc.fq_codel.target = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_INTERVAL:
|
||
|
+ obj->qdisc.fq_codel.interval = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_QUANTUM:
|
||
|
+ obj->qdisc.fq_codel.quantum = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_CE_THRESHOLD:
|
||
|
+ obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_MEMORY_LIMIT:
|
||
|
+ obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ case TCA_FQ_CODEL_ECN:
|
||
|
+ obj->qdisc.fq_codel.ecn = nla_get_u32 (options_attr);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
@@ -4161,6 +4208,7 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
const NMPlatformQdisc *qdisc)
|
||
|
{
|
||
|
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||
|
+ struct nlattr *tc_options;
|
||
|
const struct tcmsg tcm = {
|
||
|
.tcm_family = qdisc->addr_family,
|
||
|
.tcm_ifindex = qdisc->ifindex,
|
||
|
@@ -4176,6 +4224,30 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
|
||
|
NLA_PUT_STRING (msg, TCA_KIND, qdisc->kind);
|
||
|
|
||
|
+ if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS)))
|
||
|
+ goto nla_put_failure;
|
||
|
+
|
||
|
+ if (strcmp (qdisc->kind, "fq_codel") == 0) {
|
||
|
+ if (qdisc->fq_codel.limit)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit);
|
||
|
+ if (qdisc->fq_codel.flows)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_FLOWS, qdisc->fq_codel.flows);
|
||
|
+ if (qdisc->fq_codel.target)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_TARGET, qdisc->fq_codel.target);
|
||
|
+ if (qdisc->fq_codel.interval)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval);
|
||
|
+ if (qdisc->fq_codel.quantum)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum);
|
||
|
+ if (qdisc->fq_codel.ce_threshold != -1)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold);
|
||
|
+ if (qdisc->fq_codel.memory != -1)
|
||
|
+ NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory);
|
||
|
+ if (qdisc->fq_codel.ecn)
|
||
|
+ NLA_PUT_S32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn);
|
||
|
+ }
|
||
|
+
|
||
|
+ nla_nest_end (msg, tc_options);
|
||
|
+
|
||
|
return g_steal_pointer (&msg);
|
||
|
|
||
|
nla_put_failure:
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index 1fc0ccb750..3d78902860 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6430,13 +6430,32 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
if (!nm_utils_to_string_buffer_init_null (qdisc, &buf, &len))
|
||
|
return buf;
|
||
|
|
||
|
- g_snprintf (buf, len, "%s%s family %d handle %x parent %x info %x",
|
||
|
- qdisc->kind,
|
||
|
- _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)),
|
||
|
- qdisc->addr_family,
|
||
|
- qdisc->handle,
|
||
|
- qdisc->parent,
|
||
|
- qdisc->info);
|
||
|
+ nm_utils_strbuf_append (&buf, &len, "%s%s family %u handle %x parent %x info %x",
|
||
|
+ qdisc->kind,
|
||
|
+ _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)),
|
||
|
+ qdisc->addr_family,
|
||
|
+ qdisc->handle,
|
||
|
+ qdisc->parent,
|
||
|
+ qdisc->info);
|
||
|
+
|
||
|
+ if (nm_streq0 (qdisc->kind, "fq_codel")) {
|
||
|
+ if (qdisc->fq_codel.limit)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " limit %u", qdisc->fq_codel.limit);
|
||
|
+ if (qdisc->fq_codel.flows)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " flows %u", qdisc->fq_codel.flows);
|
||
|
+ if (qdisc->fq_codel.target)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " target %u", qdisc->fq_codel.target);
|
||
|
+ if (qdisc->fq_codel.interval)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " interval %u", qdisc->fq_codel.interval);
|
||
|
+ if (qdisc->fq_codel.quantum)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum);
|
||
|
+ if (qdisc->fq_codel.ce_threshold != -1)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold);
|
||
|
+ if (qdisc->fq_codel.memory != -1)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory);
|
||
|
+ if (qdisc->fq_codel.ecn)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " ecn");
|
||
|
+ }
|
||
|
|
||
|
return buf;
|
||
|
}
|
||
|
@@ -6451,6 +6470,17 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h)
|
||
|
obj->handle,
|
||
|
obj->parent,
|
||
|
obj->info);
|
||
|
+ if (nm_streq0 (obj->kind, "fq_codel")) {
|
||
|
+ nm_hash_update_vals (h,
|
||
|
+ obj->fq_codel.limit,
|
||
|
+ obj->fq_codel.flows,
|
||
|
+ obj->fq_codel.target,
|
||
|
+ obj->fq_codel.interval,
|
||
|
+ obj->fq_codel.quantum,
|
||
|
+ obj->fq_codel.ce_threshold,
|
||
|
+ obj->fq_codel.memory,
|
||
|
+ obj->fq_codel.ecn == TRUE);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
int
|
||
|
@@ -6464,6 +6494,17 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b)
|
||
|
NM_CMP_FIELD (a, b, handle);
|
||
|
NM_CMP_FIELD (a, b, info);
|
||
|
|
||
|
+ if (nm_streq0 (a->kind, "fq_codel")) {
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.limit);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.flows);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.target);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.interval);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.quantum);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.ce_threshold);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.memory);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE);
|
||
|
+ }
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 97be88324e..8742b90555 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -596,6 +596,17 @@ typedef struct {
|
||
|
bool uid_range_has:1; /* has(FRA_UID_RANGE) */
|
||
|
} NMPlatformRoutingRule;
|
||
|
|
||
|
+typedef struct {
|
||
|
+ guint32 limit;
|
||
|
+ guint32 flows;
|
||
|
+ guint32 target;
|
||
|
+ guint32 interval;
|
||
|
+ guint32 quantum;
|
||
|
+ guint32 ce_threshold;
|
||
|
+ guint32 memory;
|
||
|
+ bool ecn:1;
|
||
|
+} NMPlatformQdiscFqCodel;
|
||
|
+
|
||
|
typedef struct {
|
||
|
__NMPlatformObjWithIfindex_COMMON;
|
||
|
const char *kind;
|
||
|
@@ -603,6 +614,9 @@ typedef struct {
|
||
|
guint32 handle;
|
||
|
guint32 parent;
|
||
|
guint32 info;
|
||
|
+ union {
|
||
|
+ NMPlatformQdiscFqCodel fq_codel;
|
||
|
+ };
|
||
|
} NMPlatformQdisc;
|
||
|
|
||
|
typedef struct {
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 4be7cf71e06da4801d8bb066b977c733e7e7097c Mon Sep 17 00:00:00 2001
|
||
|
From: Lubomir Rintel <lkundrak@v3.sk>
|
||
|
Date: Tue, 9 Apr 2019 16:23:39 +0200
|
||
|
Subject: [PATCH 02/20] tc/tfilter: add mirred action
|
||
|
|
||
|
(cherry picked from commit 900292147d8fd584479a7af0881984c2d77a60bf)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 11 +++++++++++
|
||
|
src/devices/nm-device.c | 29 +++++++++++++++++++++++-----
|
||
|
src/platform/nm-linux-platform.c | 33 ++++++++++++++++++++++++++++++++
|
||
|
src/platform/nm-platform.c | 29 +++++++++++++++++++++++++---
|
||
|
src/platform/nm-platform.h | 10 ++++++++++
|
||
|
5 files changed, 104 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index b82c580345..3af3e04ed9 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2542,6 +2542,15 @@ static const NMVariantAttributeSpec * const tc_action_simple_attribute_spec[] =
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
+static const NMVariantAttributeSpec * const tc_action_mirred_attribute_spec[] = {
|
||
|
+ TC_ATTR_SPEC_PTR ("egress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("ingress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("mirror", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("redirect", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+ TC_ATTR_SPEC_PTR ("dev", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ),
|
||
|
+ NULL,
|
||
|
+};
|
||
|
+
|
||
|
static const NMVariantAttributeSpec * const tc_action_attribute_spec[] = {
|
||
|
TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ),
|
||
|
TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ),
|
||
|
@@ -2636,6 +2645,8 @@ nm_utils_tc_action_from_str (const char *str, GError **error)
|
||
|
kind = g_variant_get_string (variant, NULL);
|
||
|
if (strcmp (kind, "simple") == 0)
|
||
|
attrs = tc_action_simple_attribute_spec;
|
||
|
+ else if (strcmp (kind, "mirred") == 0)
|
||
|
+ attrs = tc_action_mirred_attribute_spec;
|
||
|
else
|
||
|
attrs = NULL;
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index 195686707b..ea6ad7e2ad 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6566,16 +6566,35 @@ tc_commit (NMDevice *self)
|
||
|
|
||
|
action = nm_tc_tfilter_get_action (s_tfilter);
|
||
|
if (action) {
|
||
|
+ GVariant *var;
|
||
|
+
|
||
|
tfilter->action.kind = nm_tc_action_get_kind (action);
|
||
|
if (strcmp (tfilter->action.kind, "simple") == 0) {
|
||
|
- GVariant *sdata;
|
||
|
-
|
||
|
- sdata = nm_tc_action_get_attribute (action, "sdata");
|
||
|
- if (sdata && g_variant_is_of_type (sdata, G_VARIANT_TYPE_BYTESTRING)) {
|
||
|
+ var = nm_tc_action_get_attribute (action, "sdata");
|
||
|
+ if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) {
|
||
|
g_strlcpy (tfilter->action.simple.sdata,
|
||
|
- g_variant_get_bytestring (sdata),
|
||
|
+ g_variant_get_bytestring (var),
|
||
|
sizeof (tfilter->action.simple.sdata));
|
||
|
}
|
||
|
+ } else if (strcmp (tfilter->action.kind, "mirred") == 0) {
|
||
|
+ if (nm_tc_action_get_attribute (action, "egress"))
|
||
|
+ tfilter->action.mirred.egress = TRUE;
|
||
|
+
|
||
|
+ if (nm_tc_action_get_attribute (action, "ingress"))
|
||
|
+ tfilter->action.mirred.ingress = TRUE;
|
||
|
+
|
||
|
+ if (nm_tc_action_get_attribute (action, "mirror"))
|
||
|
+ tfilter->action.mirred.mirror = TRUE;
|
||
|
+
|
||
|
+ if (nm_tc_action_get_attribute (action, "redirect"))
|
||
|
+ tfilter->action.mirred.redirect = TRUE;
|
||
|
+
|
||
|
+ var = nm_tc_action_get_attribute (action, "dev");
|
||
|
+ if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) {
|
||
|
+ int ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self),
|
||
|
+ g_variant_get_string (var, NULL));
|
||
|
+ tfilter->action.mirred.ifindex = ifindex;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index a346d6618c..6064d89eb6 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -34,6 +34,7 @@
|
||
|
#include <linux/if_tun.h>
|
||
|
#include <linux/if_tunnel.h>
|
||
|
#include <linux/ip6_tunnel.h>
|
||
|
+#include <linux/tc_act/tc_mirred.h>
|
||
|
#include <netinet/icmp6.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <poll.h>
|
||
|
@@ -4275,6 +4276,36 @@ 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)
|
||
|
@@ -4290,6 +4321,8 @@ _add_action (struct nl_msg *msg,
|
||
|
|
||
|
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);
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index 3d78902860..6f23ddb589 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -34,6 +34,7 @@
|
||
|
#include <linux/if_tun.h>
|
||
|
#include <linux/if_tunnel.h>
|
||
|
#include <linux/rtnetlink.h>
|
||
|
+#include <linux/tc_act/tc_mirred.h>
|
||
|
#include <libudev.h>
|
||
|
|
||
|
#include "nm-utils.h"
|
||
|
@@ -6533,11 +6534,18 @@ nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsiz
|
||
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL
|
||
|
| NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII,
|
||
|
&t));
|
||
|
+ } else if (nm_streq (tfilter->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
+ nm_utils_strbuf_append (&p, &l, "%s%s%s%s dev %d",
|
||
|
+ tfilter->action.mirred.ingress ? " ingress" : "",
|
||
|
+ tfilter->action.mirred.egress ? " egress" : "",
|
||
|
+ tfilter->action.mirred.mirror ? " mirror" : "",
|
||
|
+ tfilter->action.mirred.redirect ? " redirect" : "",
|
||
|
+ tfilter->action.mirred.ifindex);
|
||
|
}
|
||
|
} else
|
||
|
act_buf[0] = '\0';
|
||
|
|
||
|
- g_snprintf (buf, len, "%s%s family %d handle %x parent %x info %x%s",
|
||
|
+ g_snprintf (buf, len, "%s%s family %u handle %x parent %x info %x%s",
|
||
|
tfilter->kind,
|
||
|
_to_string_dev (NULL, tfilter->ifindex, str_dev, sizeof (str_dev)),
|
||
|
tfilter->addr_family,
|
||
|
@@ -6561,8 +6569,16 @@ nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h)
|
||
|
obj->info);
|
||
|
if (obj->action.kind) {
|
||
|
nm_hash_update_str (h, obj->action.kind);
|
||
|
- if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE))
|
||
|
+ if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) {
|
||
|
nm_hash_update_strarr (h, obj->action.simple.sdata);
|
||
|
+ } else if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
+ nm_hash_update_vals (h,
|
||
|
+ obj->action.mirred.ingress,
|
||
|
+ obj->action.mirred.egress,
|
||
|
+ obj->action.mirred.mirror,
|
||
|
+ obj->action.mirred.redirect,
|
||
|
+ obj->action.mirred.ifindex);
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -6579,8 +6595,15 @@ nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b)
|
||
|
|
||
|
NM_CMP_FIELD_STR_INTERNED (a, b, action.kind);
|
||
|
if (a->action.kind) {
|
||
|
- if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE))
|
||
|
+ if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) {
|
||
|
NM_CMP_FIELD_STR (a, b, action.simple.sdata);
|
||
|
+ } else if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
+ NM_CMP_FIELD (a, b, action.mirred.ingress);
|
||
|
+ NM_CMP_FIELD (a, b, action.mirred.egress);
|
||
|
+ NM_CMP_FIELD (a, b, action.mirred.mirror);
|
||
|
+ NM_CMP_FIELD (a, b, action.mirred.redirect);
|
||
|
+ NM_CMP_FIELD (a, b, action.mirred.ifindex);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 8742b90555..16747f093b 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -623,14 +623,24 @@ typedef struct {
|
||
|
char sdata[32];
|
||
|
} NMPlatformActionSimple;
|
||
|
|
||
|
+typedef struct {
|
||
|
+ gboolean egress;
|
||
|
+ gboolean ingress;
|
||
|
+ gboolean mirror;
|
||
|
+ gboolean redirect;
|
||
|
+ int ifindex;
|
||
|
+} NMPlatformActionMirred;
|
||
|
+
|
||
|
typedef struct {
|
||
|
const char *kind;
|
||
|
union {
|
||
|
NMPlatformActionSimple simple;
|
||
|
+ NMPlatformActionMirred mirred;
|
||
|
};
|
||
|
} NMPlatformAction;
|
||
|
|
||
|
#define NM_PLATFORM_ACTION_KIND_SIMPLE "simple"
|
||
|
+#define NM_PLATFORM_ACTION_KIND_MIRRED "mirred"
|
||
|
|
||
|
typedef struct {
|
||
|
__NMPlatformObjWithIfindex_COMMON;
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 84bd35e4fadf0aa8244b2c683c60fdfc4b87cf6f Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 11:36:02 +0200
|
||
|
Subject: [PATCH 03/20] shared: use nm_str_skip_leading_spaces() in
|
||
|
_nm_utils_ascii_str_to_int64()
|
||
|
|
||
|
(cherry picked from commit 9d2623cceb8550fbe6becf5dde2e0cef152e1086)
|
||
|
---
|
||
|
shared/nm-glib-aux/nm-shared-utils.c | 9 +++------
|
||
|
1 file changed, 3 insertions(+), 6 deletions(-)
|
||
|
|
||
|
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
|
||
|
index cf08a77fde..fb945ef9fb 100644
|
||
|
--- a/shared/nm-glib-aux/nm-shared-utils.c
|
||
|
+++ b/shared/nm-glib-aux/nm-shared-utils.c
|
||
|
@@ -734,10 +734,7 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
|
||
|
gint64 v;
|
||
|
const char *s = NULL;
|
||
|
|
||
|
- if (str) {
|
||
|
- while (g_ascii_isspace (str[0]))
|
||
|
- str++;
|
||
|
- }
|
||
|
+ str = nm_str_skip_leading_spaces (str);
|
||
|
if (!str || !str[0]) {
|
||
|
errno = EINVAL;
|
||
|
return fallback;
|
||
|
@@ -748,9 +745,9 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
|
||
|
|
||
|
if (errno != 0)
|
||
|
return fallback;
|
||
|
+
|
||
|
if (s[0] != '\0') {
|
||
|
- while (g_ascii_isspace (s[0]))
|
||
|
- s++;
|
||
|
+ s = nm_str_skip_leading_spaces (s);
|
||
|
if (s[0] != '\0') {
|
||
|
errno = EINVAL;
|
||
|
return fallback;
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 13e3bd4161d11c81cd4188a733c6d370d41452c3 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 10:49:16 +0200
|
||
|
Subject: [PATCH 04/20] libnm/tests: add test for _nm_utils_parse_tc_handle()
|
||
|
|
||
|
(cherry picked from commit fac95d0062d9bbe256b8e479ba7cb452cbac340e)
|
||
|
---
|
||
|
libnm-core/tests/test-setting.c | 56 +++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 56 insertions(+)
|
||
|
|
||
|
diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c
|
||
|
index 03100a039b..7587b65ba7 100644
|
||
|
--- a/libnm-core/tests/test-setting.c
|
||
|
+++ b/libnm-core/tests/test-setting.c
|
||
|
@@ -2979,6 +2979,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_inval(" 1 ");
|
||
|
+ _parse_tc_handle_valid ("1:", 1, 0);
|
||
|
+ _parse_tc_handle_inval ("1: ");
|
||
|
+ _parse_tc_handle_valid ("1:0", 1, 0);
|
||
|
+ _parse_tc_handle_inval ("1 :0");
|
||
|
+ _parse_tc_handle_inval ("1 \t\n\f\r:0");
|
||
|
+ _parse_tc_handle_inval ("1 \t\n\f\r\v:0");
|
||
|
+ _parse_tc_handle_inval (" 1 : 0 ");
|
||
|
+ _parse_tc_handle_valid (" \t\v\n1: 0", 1, 0);
|
||
|
+ _parse_tc_handle_valid ("1:2", 1, 2);
|
||
|
+ _parse_tc_handle_valid ("01:02", 1, 2);
|
||
|
+ _parse_tc_handle_valid ("0x01:0x02", 1, 2);
|
||
|
+ _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_valid ("0xFFFF", 0xFFFF, 0);
|
||
|
+ _parse_tc_handle_inval ("10000");
|
||
|
+ _parse_tc_handle_valid ("\t\n\f\r FFFF", 0xFFFF, 0);
|
||
|
+ _parse_tc_handle_valid ("\t\n\f\r \vFFFF", 0xFFFF, 0);
|
||
|
+}
|
||
|
+
|
||
|
+/*****************************************************************************/
|
||
|
+
|
||
|
NMTST_DEFINE ();
|
||
|
|
||
|
int
|
||
|
@@ -3064,5 +3118,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_func ("/libnm/parse-tc-handle", test_parse_tc_handle);
|
||
|
+
|
||
|
return g_test_run ();
|
||
|
}
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From b954ddc2752285b28885398441879edb922c68fc Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 10:27:32 +0200
|
||
|
Subject: [PATCH 05/20] libnm: cleanup _nm_utils_parse_tc_handle()
|
||
|
|
||
|
- g_ascii_strtoll() accepts leading spaces, but it leaves
|
||
|
the end pointer at the first space after the digit. That means,
|
||
|
we accepted "1: 0" but not "1 :0". We should either consistently
|
||
|
accept spaces around the digits/colon or reject it.
|
||
|
|
||
|
- g_ascii_strtoll() accepts "\v" as a space (just like `man 3 isspace`
|
||
|
comments that "\v" is a space in C and POSIX locale.
|
||
|
For some reasons (unknown to me) g_ascii_isspace() does not treat
|
||
|
"\v" as space. And neither does NM_ASCII_SPACES and
|
||
|
nm_str_skip_leading_spaces().
|
||
|
We should be consistent about what we consider spaces and what not.
|
||
|
It's already odd to accept '\n' as spaces here, but well, lets do
|
||
|
it for the sake of consistency (so that it matches with our
|
||
|
understanding of ASCII spaces, albeit not POSIX's).
|
||
|
|
||
|
- don't use bogus error domains in "g_set_error (error, 1, 0, ..."
|
||
|
That is a bug and we have NM_UTILS_ERROR exactly for error instances
|
||
|
with unspecified domain and code.
|
||
|
|
||
|
- as before, accept a trailing ":" with omitted minor number.
|
||
|
|
||
|
- reject all unexpected characters. strtoll() accepts '+' / '-'
|
||
|
and a "0x" prefix of the numbers (and leading POSIX spaces). Be
|
||
|
strict here and only accepts NM_ASCII_SPACES, ':', and hexdigits.
|
||
|
In particular, don't accept the "0x" prefix.
|
||
|
|
||
|
This parsing would be significantly simpler to implement, if we could
|
||
|
just strdup() the string, split the string at the colon delimiter and
|
||
|
use _nm_utils_ascii_str_to_int64() which gets leading/trailing spaces
|
||
|
right. But let's save the "overhead" of an additional alloc.
|
||
|
|
||
|
(cherry picked from commit cc9f07167607124bcb0df735034858aadfdb8541)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 43 ++++++++++++++++++++++++---------
|
||
|
libnm-core/tests/test-setting.c | 18 +++++++-------
|
||
|
2 files changed, 41 insertions(+), 20 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 3af3e04ed9..7a7c6de114 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2280,21 +2280,42 @@ _nm_utils_string_append_tc_parent (GString *string, const char *prefix, guint32
|
||
|
guint32
|
||
|
_nm_utils_parse_tc_handle (const char *str, GError **error)
|
||
|
{
|
||
|
- gint64 maj, min;
|
||
|
- char *sep;
|
||
|
+ gint64 maj;
|
||
|
+ gint64 min = 0;
|
||
|
+ const char *sep;
|
||
|
|
||
|
- maj = g_ascii_strtoll (str, &sep, 0x10);
|
||
|
- if (*sep == ':')
|
||
|
- min = g_ascii_strtoll (&sep[1], &sep, 0x10);
|
||
|
- else
|
||
|
- min = 0;
|
||
|
+ nm_assert (str);
|
||
|
|
||
|
- if (*sep != '\0' || maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff) {
|
||
|
- g_set_error (error, 1, 0, _("'%s' is not a valid handle."), str);
|
||
|
- return TC_H_UNSPEC;
|
||
|
+ maj = g_ascii_strtoll (str, (char **) &sep, 0x10);
|
||
|
+ if (sep == str)
|
||
|
+ 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 ( maj <= 0
|
||
|
+ || maj > 0xffff
|
||
|
+ || 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) \
|
||
|
diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c
|
||
|
index 7587b65ba7..5c9c614fb5 100644
|
||
|
--- a/libnm-core/tests/test-setting.c
|
||
|
+++ b/libnm-core/tests/test-setting.c
|
||
|
@@ -3008,27 +3008,27 @@ test_parse_tc_handle (void)
|
||
|
_parse_tc_handle_inval (" ");
|
||
|
_parse_tc_handle_inval (" \n");
|
||
|
_parse_tc_handle_valid ("1", 1, 0);
|
||
|
- _parse_tc_handle_inval(" 1 ");
|
||
|
+ _parse_tc_handle_valid(" 1 ", 1, 0);
|
||
|
_parse_tc_handle_valid ("1:", 1, 0);
|
||
|
- _parse_tc_handle_inval ("1: ");
|
||
|
+ _parse_tc_handle_valid ("1: ", 1, 0);
|
||
|
_parse_tc_handle_valid ("1:0", 1, 0);
|
||
|
- _parse_tc_handle_inval ("1 :0");
|
||
|
- _parse_tc_handle_inval ("1 \t\n\f\r: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_inval (" 1 : 0 ");
|
||
|
- _parse_tc_handle_valid (" \t\v\n1: 0", 1, 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_valid ("0x01:0x02", 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_valid ("0xFFFF", 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_valid ("\t\n\f\r \vFFFF", 0xFFFF, 0);
|
||
|
+ _parse_tc_handle_inval ("\t\n\f\r \vFFFF");
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From fde9250cdc664b557a80a517f57929a36597094a Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 11:53:13 +0200
|
||
|
Subject: [PATCH 06/20] libnm: mark NMVariantAttributeSpec pointers as const
|
||
|
|
||
|
This actually allows the compiler/linker to mark the memory as read-only and any
|
||
|
modification will cause a segmentation fault.
|
||
|
|
||
|
I would also think that it allows the compiler to put the structure directly
|
||
|
beside the outer constant array (in which this pointer is embedded). That is good
|
||
|
locality-wise.
|
||
|
|
||
|
(cherry picked from commit 4e3955e6ddf02d5ea32012bd563aa02fece5c0ef)
|
||
|
---
|
||
|
libnm-core/nm-setting-ip-config.c | 2 +-
|
||
|
libnm-core/nm-setting-sriov.c | 2 +-
|
||
|
libnm-core/nm-utils.c | 2 +-
|
||
|
3 files changed, 3 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
|
||
|
index f362945f41..26fbc8849f 100644
|
||
|
--- a/libnm-core/nm-setting-ip-config.c
|
||
|
+++ b/libnm-core/nm-setting-ip-config.c
|
||
|
@@ -1213,7 +1213,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
|
||
|
}
|
||
|
|
||
|
#define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \
|
||
|
- &(NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type }
|
||
|
+ &((const NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type })
|
||
|
|
||
|
static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
||
|
ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c
|
||
|
index b662ca2cf6..9a47d141d2 100644
|
||
|
--- a/libnm-core/nm-setting-sriov.c
|
||
|
+++ b/libnm-core/nm-setting-sriov.c
|
||
|
@@ -366,7 +366,7 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name)
|
||
|
}
|
||
|
|
||
|
#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \
|
||
|
- &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type }
|
||
|
+ &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type })
|
||
|
|
||
|
const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = {
|
||
|
SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'),
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 7a7c6de114..7df63b83bb 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2319,7 +2319,7 @@ fail:
|
||
|
}
|
||
|
|
||
|
#define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \
|
||
|
- &(NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type }
|
||
|
+ &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type })
|
||
|
|
||
|
static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = {
|
||
|
TC_ATTR_SPEC_PTR ("root", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 38cf36022ef0bb678daf4d2e70da82c96185b310 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 11:56:29 +0200
|
||
|
Subject: [PATCH 07/20] libnm: use macro and designated initializers for
|
||
|
NMVariantAttributeSpec
|
||
|
|
||
|
I think initializing structs should (almost) be always done with designated
|
||
|
initializers, because otherwise it's easy to get the order wrong. The
|
||
|
problem is that otherwise the order of fields gets additional meaning
|
||
|
not only for the memory layout, but also for the code that initialize
|
||
|
the structs.
|
||
|
|
||
|
Add a macro NM_VARIANT_ATTRIBUTE_SPEC_DEFINE() that replaces the other
|
||
|
(duplicate) macros. This macro also gets it right to mark the struct as
|
||
|
const.
|
||
|
|
||
|
(cherry picked from commit 86dc50d4760b77f30f3d29c5fa46ea32b06d73f8)
|
||
|
---
|
||
|
libnm-core/nm-setting-ip-config.c | 35 ++++++++--------
|
||
|
libnm-core/nm-setting-sriov.c | 17 ++++----
|
||
|
libnm-core/nm-utils-private.h | 7 ++++
|
||
|
libnm-core/nm-utils.c | 67 +++++++++++++++----------------
|
||
|
4 files changed, 62 insertions(+), 64 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
|
||
|
index 26fbc8849f..375c309dd6 100644
|
||
|
--- a/libnm-core/nm-setting-ip-config.c
|
||
|
+++ b/libnm-core/nm-setting-ip-config.c
|
||
|
@@ -1212,25 +1212,22 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
|
||
|
g_hash_table_remove (route->attributes, name);
|
||
|
}
|
||
|
|
||
|
-#define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \
|
||
|
- &((const NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type })
|
||
|
-
|
||
|
-static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = {
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||
|
- ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, TRUE, TRUE, 0 ),
|
||
|
- 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 ),
|
||
|
+static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = {
|
||
|
+ 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', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, .v6 = TRUE, .str_type = 'p', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_ONLINK, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_INITRWND, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_MTU, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, G_VARIANT_TYPE_BOOLEAN, .v4 = TRUE, .v6 = TRUE, ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c
|
||
|
index 9a47d141d2..0625331e3f 100644
|
||
|
--- a/libnm-core/nm-setting-sriov.c
|
||
|
+++ b/libnm-core/nm-setting-sriov.c
|
||
|
@@ -365,17 +365,14 @@ nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name)
|
||
|
return g_hash_table_lookup (vf->attributes, name);
|
||
|
}
|
||
|
|
||
|
-#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \
|
||
|
- &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type })
|
||
|
-
|
||
|
-const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = {
|
||
|
- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC, G_VARIANT_TYPE_STRING, 'm'),
|
||
|
- SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, G_VARIANT_TYPE_BOOLEAN, 0),
|
||
|
- 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),
|
||
|
+const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = {
|
||
|
+ 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, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_TRUST, G_VARIANT_TYPE_BOOLEAN, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, G_VARIANT_TYPE_UINT32, ),
|
||
|
/* 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,
|
||
|
};
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
|
||
|
index a1a1369a39..1b9b888773 100644
|
||
|
--- a/libnm-core/nm-utils-private.h
|
||
|
+++ b/libnm-core/nm-utils-private.h
|
||
|
@@ -38,6 +38,13 @@ struct _NMVariantAttributeSpec {
|
||
|
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,
|
||
|
const char **valid_values);
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 7df63b83bb..7cf482d3de 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2318,33 +2318,30 @@ fail:
|
||
|
return TC_H_UNSPEC;
|
||
|
}
|
||
|
|
||
|
-#define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \
|
||
|
- &((const NMVariantAttributeSpec) { name, type, FALSE, FALSE, no_value, consumes_rest, str_type })
|
||
|
-
|
||
|
-static const NMVariantAttributeSpec * const tc_object_attribute_spec[] = {
|
||
|
- TC_ATTR_SPEC_PTR ("root", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("parent", G_VARIANT_TYPE_STRING, FALSE, FALSE, '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' ),
|
||
|
+static const NMVariantAttributeSpec *const tc_object_attribute_spec[] = {
|
||
|
+ 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', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("handle", G_VARIANT_TYPE_STRING, .str_type = 'a', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
-static const NMVariantAttributeSpec * const tc_qdisc_fq_codel_spec[] = {
|
||
|
- TC_ATTR_SPEC_PTR ("limit", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("flows", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("target", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("interval", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("quantum", G_VARIANT_TYPE_UINT32, FALSE, FALSE, 0 ),
|
||
|
- 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 ),
|
||
|
- TC_ATTR_SPEC_PTR ("ecn", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
+static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("limit", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("flows", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("target", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ce_threshold", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("memory", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
typedef struct {
|
||
|
const char *kind;
|
||
|
- const NMVariantAttributeSpec * const *attrs;
|
||
|
+ const NMVariantAttributeSpec *const *attrs;
|
||
|
} NMQdiscAttributeSpec;
|
||
|
|
||
|
static const NMQdiscAttributeSpec *const tc_qdisc_attribute_spec[] = {
|
||
|
@@ -2558,23 +2555,23 @@ nm_utils_tc_qdisc_from_str (const char *str, GError **error)
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
|
||
|
-static const NMVariantAttributeSpec * const tc_action_simple_attribute_spec[] = {
|
||
|
- TC_ATTR_SPEC_PTR ("sdata", G_VARIANT_TYPE_BYTESTRING, FALSE, FALSE, 0 ),
|
||
|
+static const NMVariantAttributeSpec *const tc_action_simple_attribute_spec[] = {
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("sdata", G_VARIANT_TYPE_BYTESTRING, ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
-static const NMVariantAttributeSpec * const tc_action_mirred_attribute_spec[] = {
|
||
|
- TC_ATTR_SPEC_PTR ("egress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("ingress", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("mirror", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("redirect", G_VARIANT_TYPE_BOOLEAN, TRUE, FALSE, 0 ),
|
||
|
- TC_ATTR_SPEC_PTR ("dev", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ),
|
||
|
+static const NMVariantAttributeSpec *const tc_action_mirred_attribute_spec[] = {
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("egress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ingress", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("mirror", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("redirect", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("dev", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
-static const NMVariantAttributeSpec * const tc_action_attribute_spec[] = {
|
||
|
- TC_ATTR_SPEC_PTR ("kind", G_VARIANT_TYPE_STRING, TRUE, FALSE, 'a' ),
|
||
|
- TC_ATTR_SPEC_PTR ("", G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a' ),
|
||
|
+static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = {
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("kind", G_VARIANT_TYPE_STRING, .no_value = TRUE, .str_type = 'a', ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
@@ -2643,7 +2640,7 @@ nm_utils_tc_action_from_str (const char *str, GError **error)
|
||
|
gs_unref_hashtable GHashTable *ht = NULL;
|
||
|
gs_unref_hashtable GHashTable *options = NULL;
|
||
|
GVariant *variant;
|
||
|
- const NMVariantAttributeSpec * const *attrs;
|
||
|
+ const NMVariantAttributeSpec *const *attrs;
|
||
|
|
||
|
nm_assert (str);
|
||
|
nm_assert (!error || !*error);
|
||
|
@@ -2771,9 +2768,9 @@ nm_utils_tc_tfilter_to_str (NMTCTfilter *tfilter, GError **error)
|
||
|
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' ),
|
||
|
+static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = {
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("action", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
+ NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("", G_VARIANT_TYPE_STRING, .no_value = TRUE, .consumes_rest = TRUE, .str_type = 'a', ),
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
@@ -6460,7 +6457,7 @@ nm_utils_parse_variant_attributes (const char *string,
|
||
|
gs_unref_hashtable GHashTable *ht = NULL;
|
||
|
const char *ptr = string, *start = NULL, *sep;
|
||
|
GVariant *variant;
|
||
|
- const NMVariantAttributeSpec * const *s;
|
||
|
+ const NMVariantAttributeSpec *const *s;
|
||
|
|
||
|
g_return_val_if_fail (string, NULL);
|
||
|
g_return_val_if_fail (attr_separator, NULL);
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 73fdcd38f16eb759de395de8680c994a742fbe1c Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 08:52:54 +0200
|
||
|
Subject: [PATCH 08/20] device: fix type of loop variable in tc_commit()
|
||
|
|
||
|
nqdiscs and ntfilters are unsigned integers. The loop variable must agree in
|
||
|
range and signedness.
|
||
|
|
||
|
(cherry picked from commit 438855e915c328867b7802b14ebef47d7f946ca8)
|
||
|
---
|
||
|
src/devices/nm-device.c | 2 +-
|
||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index ea6ad7e2ad..e07798094f 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6496,7 +6496,7 @@ tc_commit (NMDevice *self)
|
||
|
NMSettingTCConfig *s_tc = NULL;
|
||
|
int ip_ifindex;
|
||
|
guint nqdiscs, ntfilters;
|
||
|
- int i;
|
||
|
+ guint i;
|
||
|
|
||
|
connection = nm_device_get_applied_connection (self);
|
||
|
if (connection)
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 366d3af00960803c973a307a6bd7ffeedd9c1520 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 08:10:47 +0200
|
||
|
Subject: [PATCH 09/20] platform: use NM_CMP_FIELD_UNSAFE() for comparing
|
||
|
bitfield in nm_platform_qdisc_cmp()
|
||
|
|
||
|
"NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE)" is quite a hack as it relies on
|
||
|
the implementation of the macro in a particular way. The problem is, that
|
||
|
NM_CMP_FIELD() uses typeof() which cannot be used with bitfields. So, the
|
||
|
nicer solution is to use NM_CMP_FIELD_UNSAFE() which exists exactly for bitfields
|
||
|
(it's "unsafe", because it evaluates arguments more than once as it avoids
|
||
|
the temporary variable with typeof()).
|
||
|
|
||
|
Same with nm_hash_update_vals() which uses typeof() to avoid evaluating
|
||
|
arguments more than once. But that again does not work with bitfields.
|
||
|
The "proper" way is to use NM_HASH_COMBINE_BOOLS().
|
||
|
|
||
|
(cherry picked from commit 47d8bee1130c619a41fe64753d88d88012f9fb98)
|
||
|
---
|
||
|
src/platform/nm-platform.c | 5 +++--
|
||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index 6f23ddb589..f8cf0b8999 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6480,7 +6480,8 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h)
|
||
|
obj->fq_codel.quantum,
|
||
|
obj->fq_codel.ce_threshold,
|
||
|
obj->fq_codel.memory,
|
||
|
- obj->fq_codel.ecn == TRUE);
|
||
|
+ NM_HASH_COMBINE_BOOLS (guint8,
|
||
|
+ obj->fq_codel.ecn));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -6503,7 +6504,7 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b)
|
||
|
NM_CMP_FIELD (a, b, fq_codel.quantum);
|
||
|
NM_CMP_FIELD (a, b, fq_codel.ce_threshold);
|
||
|
NM_CMP_FIELD (a, b, fq_codel.memory);
|
||
|
- NM_CMP_FIELD (a, b, fq_codel.ecn == TRUE);
|
||
|
+ NM_CMP_FIELD_UNSAFE (a, b, fq_codel.ecn);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From ef2b660bb8cb2c30faf55c51a411e8a757707076 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 08:20:42 +0200
|
||
|
Subject: [PATCH 10/20] platform: use u32 netlink type for TCA_FQ_CODEL_ECN
|
||
|
|
||
|
In practice, there is no difference when representing 0 or 1 as signed/unsigned 32
|
||
|
bit integer. But still use the correct type that also kernel uses.
|
||
|
|
||
|
Also, the implicit conversation from uint32 to bool was correct already.
|
||
|
Still, explicitly convert the uint32 value to boolean in _new_from_nl_qdisc().
|
||
|
It's no change in behavior.
|
||
|
|
||
|
(cherry picked from commit a1099a1fab661a430fa8e8015369b536c806433e)
|
||
|
---
|
||
|
src/platform/nm-linux-platform.c | 4 ++--
|
||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 6064d89eb6..1428778e03 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -3547,7 +3547,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.fq_codel.memory = nla_get_u32 (options_attr);
|
||
|
break;
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
@@ -4244,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
if (qdisc->fq_codel.memory != -1)
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory);
|
||
|
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);
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From dd3ca10284f9f7f95b1f313a3aa678f2aef01b3f Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 08:23:00 +0200
|
||
|
Subject: [PATCH 11/20] platform: fix nm_platform_qdisc_to_string()
|
||
|
|
||
|
When using nm_utils_strbuf_*() API, the buffer gets always moved to the current
|
||
|
end. We must thus remember and return the original start of the buffer.
|
||
|
|
||
|
(cherry picked from commit b658e3da0825cf6e62e0850d3508dde1dd5c1914)
|
||
|
---
|
||
|
src/platform/nm-platform.c | 5 ++++-
|
||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index f8cf0b8999..4d3b61405d 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6427,10 +6427,13 @@ const char *
|
||
|
nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
{
|
||
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
||
|
+ const char *buf0;
|
||
|
|
||
|
if (!nm_utils_to_string_buffer_init_null (qdisc, &buf, &len))
|
||
|
return buf;
|
||
|
|
||
|
+ buf0 = buf;
|
||
|
+
|
||
|
nm_utils_strbuf_append (&buf, &len, "%s%s family %u handle %x parent %x info %x",
|
||
|
qdisc->kind,
|
||
|
_to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)),
|
||
|
@@ -6458,7 +6461,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ecn");
|
||
|
}
|
||
|
|
||
|
- return buf;
|
||
|
+ return buf0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 509a1bc5f2e52f6d639b75a0467b584c08a90463 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 08:43:31 +0200
|
||
|
Subject: [PATCH 12/20] platform: fix handling of fq_codel's memory limit
|
||
|
default value
|
||
|
|
||
|
The memory-limit is an unsigned integer. It is ugly (if not wrong) to compare unsigned
|
||
|
values with "-1". When comparing with the default value we must also use an u32 type.
|
||
|
Instead add a define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET.
|
||
|
|
||
|
Note that like iproute2 we treat NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
|
||
|
to indicate to not set TCA_FQ_CODEL_MEMORY_LIMIT in RTM_NEWQDISC. This
|
||
|
special value is entirely internal to NetworkManager (or iproute2) and
|
||
|
kernel will then choose a default memory limit (of 32MB). So setting
|
||
|
NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET means to leave it to kernel to
|
||
|
choose a value (which then chooses 32MB).
|
||
|
|
||
|
See kernel's net/sched/sch_fq_codel.c:
|
||
|
|
||
|
static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
|
||
|
struct netlink_ext_ack *extack)
|
||
|
{
|
||
|
...
|
||
|
q->memory_limit = 32 << 20; /* 32 MBytes */
|
||
|
|
||
|
static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
|
||
|
struct netlink_ext_ack *extack)
|
||
|
...
|
||
|
if (tb[TCA_FQ_CODEL_MEMORY_LIMIT])
|
||
|
q->memory_limit = min(1U << 31, nla_get_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]));
|
||
|
|
||
|
Note that not having zero as default value is problematic. In fields like
|
||
|
"NMPlatformIP4Route.table_coerced" and "NMPlatformRoutingRule.suppress_prefixlen_inverse"
|
||
|
we avoid this problem by storing a coerced value in the structure so that zero is still
|
||
|
the default. We don't do that here for memory-limit, so the caller must always explicitly
|
||
|
set the value.
|
||
|
|
||
|
(cherry picked from commit 46a904389bf13a2cfd40888ab2a843827fda7469)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 5 +++++
|
||
|
src/devices/nm-device.c | 2 +-
|
||
|
src/platform/nm-linux-platform.c | 5 ++++-
|
||
|
src/platform/nm-platform.c | 2 +-
|
||
|
src/platform/nm-platform.h | 9 ++++++++-
|
||
|
5 files changed, 19 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 7cf482d3de..2e66e6ae2d 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2334,7 +2334,12 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ),
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ),
|
||
|
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", G_VARIANT_TYPE_UINT32, ),
|
||
|
+
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("ecn", G_VARIANT_TYPE_BOOLEAN, .no_value = TRUE, ),
|
||
|
NULL,
|
||
|
};
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index e07798094f..ce50d5b73d 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6539,7 +6539,7 @@ tc_commit (NMDevice *self)
|
||
|
GET_ATTR("interval", qdisc->fq_codel.interval, 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("memory", qdisc->fq_codel.memory, UINT32, uint32, -1);
|
||
|
+ GET_ATTR("memory", qdisc->fq_codel.memory, UINT32, uint32, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET);
|
||
|
GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 1428778e03..cec5fb9431 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -3515,6 +3515,9 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.parent = tcm->tcm_parent;
|
||
|
obj->qdisc.info = tcm->tcm_info;
|
||
|
|
||
|
+ if (nm_streq0 (obj->qdisc.kind, "fq_codel"))
|
||
|
+ obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET;
|
||
|
+
|
||
|
if (tb[TCA_OPTIONS]) {
|
||
|
struct nlattr *options_attr;
|
||
|
int remaining;
|
||
|
@@ -4241,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum);
|
||
|
if (qdisc->fq_codel.ce_threshold != -1)
|
||
|
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 != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory);
|
||
|
if (qdisc->fq_codel.ecn)
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn);
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index 4d3b61405d..fc49db19a1 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6455,7 +6455,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum);
|
||
|
if (qdisc->fq_codel.ce_threshold != -1)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold);
|
||
|
- if (qdisc->fq_codel.memory != -1)
|
||
|
+ if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory);
|
||
|
if (qdisc->fq_codel.ecn)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ecn");
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 16747f093b..9f9fcf5c31 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -596,6 +596,8 @@ typedef struct {
|
||
|
bool uid_range_has:1; /* has(FRA_UID_RANGE) */
|
||
|
} NMPlatformRoutingRule;
|
||
|
|
||
|
+#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0))
|
||
|
+
|
||
|
typedef struct {
|
||
|
guint32 limit;
|
||
|
guint32 flows;
|
||
|
@@ -603,7 +605,12 @@ typedef struct {
|
||
|
guint32 interval;
|
||
|
guint32 quantum;
|
||
|
guint32 ce_threshold;
|
||
|
- guint32 memory;
|
||
|
+ guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel
|
||
|
+ * and kernel defaults to 32MB.
|
||
|
+ * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
|
||
|
+ * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request).
|
||
|
+ * This will cause kernel to choose the default (32MB).
|
||
|
+ * Beware: zero is not the default you must always explicitly set this value. */
|
||
|
bool ecn:1;
|
||
|
} NMPlatformQdiscFqCodel;
|
||
|
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 859f8479d453c9270987245b9d6e537af0e42077 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 09:19:59 +0200
|
||
|
Subject: [PATCH 13/20] platform: fix handling of default value for
|
||
|
TCA_FQ_CODEL_CE_THRESHOLD
|
||
|
|
||
|
iproute2 uses the special value ~0u to indicate not to set
|
||
|
TCA_FQ_CODEL_CE_THRESHOLD in RTM_NEWQDISC. When not explicitly
|
||
|
setting the value, kernel treats the threshold as disabled.
|
||
|
|
||
|
However note that 0xFFFFFFFFu is not an invalid threshold (as far as
|
||
|
kernel is concerned). Thus, we should not use that as value to indicate
|
||
|
that the value is unset. Note that iproute2 uses the special value ~0u
|
||
|
only internally thereby making it impossible to set the threshold to
|
||
|
0xFFFFFFFFu). But kernel does not have this limitation.
|
||
|
|
||
|
Maybe the cleanest way would be to add another field to NMPlatformQDisc:
|
||
|
|
||
|
guint32 ce_threshold;
|
||
|
bool ce_threshold_set:1;
|
||
|
|
||
|
that indicates whether the threshold is enable or not.
|
||
|
But note that kernel does:
|
||
|
|
||
|
static void codel_params_init(struct codel_params *params)
|
||
|
{
|
||
|
...
|
||
|
params->ce_threshold = CODEL_DISABLED_THRESHOLD;
|
||
|
|
||
|
static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
|
||
|
struct netlink_ext_ack *extack)
|
||
|
{
|
||
|
...
|
||
|
if (tb[TCA_FQ_CODEL_CE_THRESHOLD]) {
|
||
|
u64 val = nla_get_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]);
|
||
|
|
||
|
q->cparams.ce_threshold = (val * NSEC_PER_USEC) >> CODEL_SHIFT;
|
||
|
}
|
||
|
|
||
|
static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||
|
{
|
||
|
...
|
||
|
if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD &&
|
||
|
nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD,
|
||
|
codel_time_to_us(q->cparams.ce_threshold)))
|
||
|
goto nla_put_failure;
|
||
|
|
||
|
This means, kernel internally uses the special value 0x83126E97u to indicate
|
||
|
that the threshold is disabled (WTF). That is because
|
||
|
|
||
|
(((guint64) 0x83126E97u) * NSEC_PER_USEC) >> CODEL_SHIFT == CODEL_DISABLED_THRESHOLD
|
||
|
|
||
|
So in kernel API this value is reserved (and has a special meaning
|
||
|
to indicate that the threshold is disabled). So, instead of adding a
|
||
|
ce_threshold_set flag, use the same value that kernel anyway uses.
|
||
|
|
||
|
(cherry picked from commit 973db2d41b957c4ee9d4ee9863f4b35c6890ac30)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 3 +++
|
||
|
src/devices/nm-device.c | 2 +-
|
||
|
src/platform/nm-linux-platform.c | 6 ++++--
|
||
|
src/platform/nm-platform.c | 2 +-
|
||
|
src/platform/nm-platform.h | 12 +++++++++++-
|
||
|
5 files changed, 20 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 2e66e6ae2d..9e2eb63594 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2333,6 +2333,9 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("target", G_VARIANT_TYPE_UINT32, ),
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("interval", G_VARIANT_TYPE_UINT32, ),
|
||
|
NM_VARIANT_ATTRIBUTE_SPEC_DEFINE ("quantum", G_VARIANT_TYPE_UINT32, ),
|
||
|
+
|
||
|
+ /* 0x83126E97u is not a valid value (it means "disabled"). We should reject that
|
||
|
+ * 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
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index ce50d5b73d..22ccabb26e 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6538,7 +6538,7 @@ tc_commit (NMDevice *self)
|
||
|
GET_ATTR("target", qdisc->fq_codel.target, 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("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, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET);
|
||
|
GET_ATTR("ecn", qdisc->fq_codel.ecn, BOOLEAN, boolean, FALSE);
|
||
|
}
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index cec5fb9431..2e11052e1a 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -3515,8 +3515,10 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.parent = tcm->tcm_parent;
|
||
|
obj->qdisc.info = tcm->tcm_info;
|
||
|
|
||
|
- if (nm_streq0 (obj->qdisc.kind, "fq_codel"))
|
||
|
+ if (nm_streq0 (obj->qdisc.kind, "fq_codel")) {
|
||
|
obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET;
|
||
|
+ obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED;
|
||
|
+ }
|
||
|
|
||
|
if (tb[TCA_OPTIONS]) {
|
||
|
struct nlattr *options_attr;
|
||
|
@@ -4242,7 +4244,7 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval);
|
||
|
if (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);
|
||
|
if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory);
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index fc49db19a1..cbf9eed5c1 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6453,7 +6453,7 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
nm_utils_strbuf_append (&buf, &len, " interval %u", qdisc->fq_codel.interval);
|
||
|
if (qdisc->fq_codel.quantum)
|
||
|
nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum);
|
||
|
- if (qdisc->fq_codel.ce_threshold != -1)
|
||
|
+ if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold);
|
||
|
if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory);
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 9f9fcf5c31..d7c388b1b8 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -598,13 +598,23 @@ typedef struct {
|
||
|
|
||
|
#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0))
|
||
|
|
||
|
+#define NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED ((guint32) 0x83126E97u)
|
||
|
+
|
||
|
+G_STATIC_ASSERT (((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) == (guint64) INT_MAX);
|
||
|
+
|
||
|
typedef struct {
|
||
|
guint32 limit;
|
||
|
guint32 flows;
|
||
|
guint32 target;
|
||
|
guint32 interval;
|
||
|
guint32 quantum;
|
||
|
- guint32 ce_threshold;
|
||
|
+ guint32 ce_threshold; /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as
|
||
|
+ * ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in
|
||
|
+ * the domain with this coersion) is CODEL_DISABLED_THRESHOLD (INT_MAX).
|
||
|
+ * That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the
|
||
|
+ * netlink attribute but also as the special value 0x83126E97u
|
||
|
+ * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED).
|
||
|
+ * Beware: zero is not the default you must always explicitly set this value. */
|
||
|
guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel
|
||
|
* and kernel defaults to 32MB.
|
||
|
* Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From c17fa82b314d6b3c027240ee3506706e26ef9e5d Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 12:56:46 +0200
|
||
|
Subject: [PATCH 14/20] libnm: rename "memory" parameter of fq_codel QDisc to
|
||
|
"memory_limit"
|
||
|
|
||
|
Kernel calls the netlink attribute TCA_FQ_CODEL_MEMORY_LIMIT. Likewise,
|
||
|
iproute2 calls this "memory_limit".
|
||
|
|
||
|
Rename because TC parameters are inherrently tied to the kernel
|
||
|
implementation and we should use the familiar name.
|
||
|
|
||
|
(cherry picked from commit 666d58802b6f9072825d97498ab74e5d37652e93)
|
||
|
---
|
||
|
libnm-core/nm-utils.c | 2 +-
|
||
|
src/devices/nm-device.c | 2 +-
|
||
|
src/platform/nm-linux-platform.c | 8 ++++----
|
||
|
src/platform/nm-platform.c | 8 ++++----
|
||
|
src/platform/nm-platform.h | 2 +-
|
||
|
5 files changed, 11 insertions(+), 11 deletions(-)
|
||
|
|
||
|
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
|
||
|
index 9e2eb63594..394ca7c3a7 100644
|
||
|
--- a/libnm-core/nm-utils.c
|
||
|
+++ b/libnm-core/nm-utils.c
|
||
|
@@ -2341,7 +2341,7 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
|
||
|
/* 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", G_VARIANT_TYPE_UINT32, ),
|
||
|
+ 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,
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index 22ccabb26e..e2a5fd4bf2 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6539,7 +6539,7 @@ tc_commit (NMDevice *self)
|
||
|
GET_ATTR("interval", qdisc->fq_codel.interval, UINT32, uint32, 0);
|
||
|
GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0);
|
||
|
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, NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET);
|
||
|
+ 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);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 2e11052e1a..9721ff9403 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -3516,7 +3516,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.info = tcm->tcm_info;
|
||
|
|
||
|
if (nm_streq0 (obj->qdisc.kind, "fq_codel")) {
|
||
|
- obj->qdisc.fq_codel.memory = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET;
|
||
|
+ 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;
|
||
|
}
|
||
|
|
||
|
@@ -3549,7 +3549,7 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
|
||
|
obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr);
|
||
|
break;
|
||
|
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;
|
||
|
case TCA_FQ_CODEL_ECN:
|
||
|
obj->qdisc.fq_codel.ecn = !!nla_get_u32 (options_attr);
|
||
|
@@ -4246,8 +4246,8 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum);
|
||
|
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);
|
||
|
- if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
- NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory);
|
||
|
+ 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_limit);
|
||
|
if (qdisc->fq_codel.ecn)
|
||
|
NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn);
|
||
|
}
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index cbf9eed5c1..ea73f21019 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6455,8 +6455,8 @@ nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len)
|
||
|
nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum);
|
||
|
if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold);
|
||
|
- if (qdisc->fq_codel.memory != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
- nm_utils_strbuf_append (&buf, &len, " memory %u", qdisc->fq_codel.memory);
|
||
|
+ if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET)
|
||
|
+ nm_utils_strbuf_append (&buf, &len, " memory_limit %u", qdisc->fq_codel.memory_limit);
|
||
|
if (qdisc->fq_codel.ecn)
|
||
|
nm_utils_strbuf_append (&buf, &len, " ecn");
|
||
|
}
|
||
|
@@ -6482,7 +6482,7 @@ nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h)
|
||
|
obj->fq_codel.interval,
|
||
|
obj->fq_codel.quantum,
|
||
|
obj->fq_codel.ce_threshold,
|
||
|
- obj->fq_codel.memory,
|
||
|
+ obj->fq_codel.memory_limit,
|
||
|
NM_HASH_COMBINE_BOOLS (guint8,
|
||
|
obj->fq_codel.ecn));
|
||
|
}
|
||
|
@@ -6506,7 +6506,7 @@ nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b)
|
||
|
NM_CMP_FIELD (a, b, fq_codel.interval);
|
||
|
NM_CMP_FIELD (a, b, fq_codel.quantum);
|
||
|
NM_CMP_FIELD (a, b, fq_codel.ce_threshold);
|
||
|
- NM_CMP_FIELD (a, b, fq_codel.memory);
|
||
|
+ NM_CMP_FIELD (a, b, fq_codel.memory_limit);
|
||
|
NM_CMP_FIELD_UNSAFE (a, b, fq_codel.ecn);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index d7c388b1b8..5a0efceca7 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -615,7 +615,7 @@ typedef struct {
|
||
|
* netlink attribute but also as the special value 0x83126E97u
|
||
|
* (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED).
|
||
|
* Beware: zero is not the default you must always explicitly set this value. */
|
||
|
- guint32 memory; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel
|
||
|
+ guint32 memory_limit; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel
|
||
|
* and kernel defaults to 32MB.
|
||
|
* Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
|
||
|
* to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request).
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 79e3b2a838b1ae7e6174de8ff000509e918d5c90 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 12:58:37 +0200
|
||
|
Subject: [PATCH 15/20] platform: use bool bitfields in NMPlatformActionMirred
|
||
|
structure
|
||
|
|
||
|
Arguably, the structure is used inside a union with another (larger)
|
||
|
struct, hence no memory is saved.
|
||
|
|
||
|
In fact, it may well be slower performance wise to access a boolean bitfield
|
||
|
than a gboolean (int).
|
||
|
|
||
|
Still, boolean fields in structures should be bool:1 bitfields for
|
||
|
consistency.
|
||
|
|
||
|
(cherry picked from commit 36d6aa3bcd97f2144e8f435249ed8f3cb709ae43)
|
||
|
---
|
||
|
src/platform/nm-platform.c | 19 ++++++++++---------
|
||
|
src/platform/nm-platform.h | 8 ++++----
|
||
|
2 files changed, 14 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index ea73f21019..ee71319dd6 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -6577,11 +6577,12 @@ nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h)
|
||
|
nm_hash_update_strarr (h, obj->action.simple.sdata);
|
||
|
} else if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
nm_hash_update_vals (h,
|
||
|
- obj->action.mirred.ingress,
|
||
|
- obj->action.mirred.egress,
|
||
|
- obj->action.mirred.mirror,
|
||
|
- obj->action.mirred.redirect,
|
||
|
- obj->action.mirred.ifindex);
|
||
|
+ obj->action.mirred.ifindex,
|
||
|
+ NM_HASH_COMBINE_BOOLS (guint8,
|
||
|
+ obj->action.mirred.ingress,
|
||
|
+ obj->action.mirred.egress,
|
||
|
+ obj->action.mirred.mirror,
|
||
|
+ obj->action.mirred.redirect));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -6602,11 +6603,11 @@ nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b)
|
||
|
if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) {
|
||
|
NM_CMP_FIELD_STR (a, b, action.simple.sdata);
|
||
|
} else if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
- NM_CMP_FIELD (a, b, action.mirred.ingress);
|
||
|
- NM_CMP_FIELD (a, b, action.mirred.egress);
|
||
|
- NM_CMP_FIELD (a, b, action.mirred.mirror);
|
||
|
- NM_CMP_FIELD (a, b, action.mirred.redirect);
|
||
|
NM_CMP_FIELD (a, b, action.mirred.ifindex);
|
||
|
+ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.ingress);
|
||
|
+ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.egress);
|
||
|
+ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.mirror);
|
||
|
+ NM_CMP_FIELD_UNSAFE (a, b, action.mirred.redirect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 5a0efceca7..9b6848d977 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -641,11 +641,11 @@ typedef struct {
|
||
|
} NMPlatformActionSimple;
|
||
|
|
||
|
typedef struct {
|
||
|
- gboolean egress;
|
||
|
- gboolean ingress;
|
||
|
- gboolean mirror;
|
||
|
- gboolean redirect;
|
||
|
int ifindex;
|
||
|
+ bool egress:1;
|
||
|
+ bool ingress:1;
|
||
|
+ bool mirror:1;
|
||
|
+ bool redirect:1;
|
||
|
} NMPlatformActionMirred;
|
||
|
|
||
|
typedef struct {
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 8b1b398c0545f31121c52d323276e013705ddf80 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 13:07:43 +0200
|
||
|
Subject: [PATCH 16/20] platform: assert for out-of-memory in netlink code
|
||
|
|
||
|
These lines can be reached if the allocated buffer is too
|
||
|
small to hold the netlink message. That is actually a bug
|
||
|
that we need to fix. Assert.
|
||
|
|
||
|
(cherry picked from commit 3784a2a2ec6f8c6307f45bae12c17630b7d70b0a)
|
||
|
---
|
||
|
src/platform/nm-linux-platform.c | 10 +++++-----
|
||
|
src/platform/wifi/nm-wifi-utils-nl80211.c | 12 ++++++------
|
||
|
src/platform/wpan/nm-wpan-utils.c | 8 ++++----
|
||
|
3 files changed, 15 insertions(+), 15 deletions(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 9721ff9403..6dd5b4ab3e 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -3681,7 +3681,7 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg,
|
||
|
|
||
|
return TRUE;
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
@@ -3832,7 +3832,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg,
|
||
|
|
||
|
return TRUE;
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static struct nl_msg *
|
||
|
@@ -4278,7 +4278,7 @@ _add_action_simple (struct nl_msg *msg,
|
||
|
return TRUE;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
@@ -4308,7 +4308,7 @@ _add_action_mirred (struct nl_msg *msg,
|
||
|
return TRUE;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
@@ -4334,7 +4334,7 @@ _add_action (struct nl_msg *msg,
|
||
|
return TRUE;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static struct nl_msg *
|
||
|
diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c
|
||
|
index 4f7ede9757..6a8525ed4b 100644
|
||
|
--- a/src/platform/wifi/nm-wifi-utils-nl80211.c
|
||
|
+++ b/src/platform/wifi/nm-wifi-utils-nl80211.c
|
||
|
@@ -103,7 +103,7 @@ _nl80211_alloc_msg (int id, int ifindex, int phy, guint32 cmd, guint32 flags)
|
||
|
return g_steal_pointer (&msg);
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return NULL;
|
||
|
+ g_return_val_if_reached (NULL);
|
||
|
}
|
||
|
|
||
|
static struct nl_msg *
|
||
|
@@ -250,7 +250,7 @@ wifi_nl80211_set_mode (NMWifiUtils *data, const NM80211Mode mode)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
@@ -267,7 +267,7 @@ wifi_nl80211_set_powersave (NMWifiUtils *data, guint32 powersave)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
@@ -365,7 +365,7 @@ wifi_nl80211_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wo
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
/* @divisor: pass what value @xbm should be divided by to get dBm */
|
||
|
@@ -642,7 +642,7 @@ nl80211_get_ap_info (NMWifiUtilsNl80211 *self,
|
||
|
return;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return;
|
||
|
+ g_return_if_reached ();
|
||
|
}
|
||
|
|
||
|
static guint32
|
||
|
@@ -695,7 +695,7 @@ wifi_nl80211_indicate_addressing_running (NMWifiUtils *data, gboolean running)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
struct nl80211_device_info {
|
||
|
diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c
|
||
|
index b7a51e9bf2..0afc2a4d0c 100644
|
||
|
--- a/src/platform/wpan/nm-wpan-utils.c
|
||
|
+++ b/src/platform/wpan/nm-wpan-utils.c
|
||
|
@@ -92,7 +92,7 @@ _nl802154_alloc_msg (int id, int ifindex, guint32 cmd, guint32 flags)
|
||
|
return g_steal_pointer (&msg);
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return NULL;
|
||
|
+ g_return_val_if_reached (NULL);
|
||
|
}
|
||
|
|
||
|
static struct nl_msg *
|
||
|
@@ -217,7 +217,7 @@ nm_wpan_utils_set_pan_id (NMWpanUtils *self, guint16 pan_id)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
guint16
|
||
|
@@ -244,7 +244,7 @@ nm_wpan_utils_set_short_addr (NMWpanUtils *self, guint16 short_addr)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
@@ -262,7 +262,7 @@ nm_wpan_utils_set_channel (NMWpanUtils *self, guint8 page, guint8 channel)
|
||
|
return err >= 0;
|
||
|
|
||
|
nla_put_failure:
|
||
|
- return FALSE;
|
||
|
+ g_return_val_if_reached (FALSE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 27341d042487afabcd48fbc08054069f89b9c424 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 13:15:57 +0200
|
||
|
Subject: [PATCH 17/20] platform: merge _add_action(), _add_action_simple() and
|
||
|
_add_action_mirred() into _nl_msg_new_tfilter()
|
||
|
|
||
|
There is only one caller, hence it's simpler to see it all in one place.
|
||
|
I prefer this, because then I can read the code top to bottom and
|
||
|
see what's happening, without following helper functions.
|
||
|
|
||
|
Also, this way we can "reuse" the nla_put_failure label and assertion. Previously,
|
||
|
if the assertion was hit we would not rewind the buffer but continue
|
||
|
constructing the message (which is already borked). Not that it matters
|
||
|
too much, because this was on an "failed-assertion" code path.
|
||
|
|
||
|
(cherry picked from commit 04bd404dffc8bc1ec5c3fed91e75fad1a1b1a4d3)
|
||
|
---
|
||
|
src/platform/nm-linux-platform.c | 125 ++++++++++++-------------------
|
||
|
1 file changed, 46 insertions(+), 79 deletions(-)
|
||
|
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 6dd5b4ab3e..4a62a76485 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -4260,83 +4260,6 @@ nla_put_failure:
|
||
|
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:
|
||
|
- g_return_val_if_reached (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:
|
||
|
- g_return_val_if_reached (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);
|
||
|
-
|
||
|
- return TRUE;
|
||
|
-
|
||
|
-nla_put_failure:
|
||
|
- g_return_val_if_reached (FALSE);
|
||
|
-}
|
||
|
-
|
||
|
static struct nl_msg *
|
||
|
_nl_msg_new_tfilter (int nlmsg_type,
|
||
|
int nlmsg_flags,
|
||
|
@@ -4366,8 +4289,52 @@ _nl_msg_new_tfilter (int nlmsg_type,
|
||
|
if (!(act_tab = nla_nest_start (msg, TCA_OPTIONS))) // 3 TCA_ACT_KIND TCA_ACT_KIND
|
||
|
goto nla_put_failure;
|
||
|
|
||
|
- if (tfilter->action.kind)
|
||
|
- _add_action (msg, &tfilter->action);
|
||
|
+ if (tfilter->action.kind) {
|
||
|
+ const NMPlatformAction *action = &tfilter->action;
|
||
|
+ struct nlattr *prio;
|
||
|
+ struct nlattr *act_options;
|
||
|
+
|
||
|
+ 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)) {
|
||
|
+ const NMPlatformActionSimple *simple = &action->simple;
|
||
|
+ 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);
|
||
|
+
|
||
|
+ } else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) {
|
||
|
+ const NMPlatformActionMirred *mirred = &action->mirred;
|
||
|
+ 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);
|
||
|
+ }
|
||
|
+
|
||
|
+ nla_nest_end (msg, prio);
|
||
|
+ }
|
||
|
|
||
|
nla_nest_end (msg, tc_options);
|
||
|
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From a0161aa9772af8d7a35812dfdf86864bb941f751 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 13:27:28 +0200
|
||
|
Subject: [PATCH 18/20] device/trivial: add space between macro name and
|
||
|
arguments and vertically align lines
|
||
|
|
||
|
Also calling macros we commonly put a space between the macro name and
|
||
|
the parenthesis.
|
||
|
|
||
|
Also align the parameters. Otherwise it's hard to read for me.
|
||
|
|
||
|
(cherry picked from commit 9399297a82cbb5e8fc218fdefde7005353cb44d6)
|
||
|
---
|
||
|
src/devices/nm-device.c | 16 ++++++++--------
|
||
|
1 file changed, 8 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index e2a5fd4bf2..1241a098d1 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6533,14 +6533,14 @@ tc_commit (NMDevice *self)
|
||
|
} G_STMT_END
|
||
|
|
||
|
if (strcmp (qdisc->kind, "fq_codel") == 0) {
|
||
|
- GET_ATTR("limit", qdisc->fq_codel.limit, 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("interval", qdisc->fq_codel.interval, UINT32, uint32, 0);
|
||
|
- GET_ATTR("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0);
|
||
|
- GET_ATTR("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED);
|
||
|
- 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 ("limit", qdisc->fq_codel.limit, 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 ("interval", qdisc->fq_codel.interval, UINT32, uint32, 0);
|
||
|
+ GET_ATTR ("quantum", qdisc->fq_codel.quantum, UINT32, uint32, 0);
|
||
|
+ GET_ATTR ("ce_threshold", qdisc->fq_codel.ce_threshold, UINT32, uint32, NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED);
|
||
|
+ 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);
|
||
|
}
|
||
|
|
||
|
#undef GET_ADDR
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From ea7de52d774f3aa3a099f6fce1cb9313b6456cef Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 16:34:27 +0200
|
||
|
Subject: [PATCH 19/20] device: don't rely on nm_platform_link_get_ifindex()
|
||
|
returning 0
|
||
|
|
||
|
While nm_platform_link_get_ifindex() is documented to return 0 if the device
|
||
|
is not found, don't rely on it. Instead, check that a valid(!) ifindex was
|
||
|
returned, and only then set the ifindex. Otherwise leave it at zero. There
|
||
|
is of course no difference in practice, but we generally treat invalid ifindexes
|
||
|
as <= 0, so it's not immediately clear what nm_platform_link_get_ifindex()
|
||
|
returns to signal no device.
|
||
|
|
||
|
(cherry picked from commit 9eefe27a1c7879e6f94bbb7dec5c9efe722888fa)
|
||
|
---
|
||
|
src/devices/nm-device.c | 11 +++++++----
|
||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index 1241a098d1..5195eb667f 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6504,7 +6504,7 @@ tc_commit (NMDevice *self)
|
||
|
|
||
|
ip_ifindex = nm_device_get_ip_ifindex (self);
|
||
|
if (!ip_ifindex)
|
||
|
- return s_tc == NULL;
|
||
|
+ return s_tc == NULL;
|
||
|
|
||
|
if (s_tc) {
|
||
|
nqdiscs = nm_setting_tc_config_get_num_qdiscs (s_tc);
|
||
|
@@ -6591,9 +6591,12 @@ tc_commit (NMDevice *self)
|
||
|
|
||
|
var = nm_tc_action_get_attribute (action, "dev");
|
||
|
if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_STRING)) {
|
||
|
- int ifindex = nm_platform_link_get_ifindex (nm_device_get_platform (self),
|
||
|
- g_variant_get_string (var, NULL));
|
||
|
- tfilter->action.mirred.ifindex = ifindex;
|
||
|
+ int 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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
--
|
||
|
2.21.0
|
||
|
|
||
|
From 6d9030acb60c2f9a89224847f0a5e68f8b55b0f0 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Haller <thaller@redhat.com>
|
||
|
Date: Wed, 1 May 2019 16:35:29 +0200
|
||
|
Subject: [PATCH 20/20] device/trivial: add comment about lifetime of "kind" in
|
||
|
tc_commit()
|
||
|
|
||
|
In general, all fields of public NMPlatform* structs must be
|
||
|
plain/simple. Meaning: copying the struct must be possible without
|
||
|
caring about cloning/duplicating memory.
|
||
|
In other words, if there are fields which lifetime is limited,
|
||
|
then these fields cannot be inside the public part NMPlatform*.
|
||
|
|
||
|
That is why
|
||
|
|
||
|
- "NMPlatformLink.kind", "NMPlatformQdisc.kind", "NMPlatformTfilter.kind"
|
||
|
are set by platform code to an interned string (g_intern_string())
|
||
|
that has a static lifetime.
|
||
|
|
||
|
- the "ingress_qos_map" field is inside the ref-counted struct NMPObjectLnkVlan
|
||
|
and not NMPlatformLnkVlan. This field requires managing the lifetime
|
||
|
of the array and NMPlatformLnkVlan cannot provide that.
|
||
|
|
||
|
See also for example NMPClass.cmd_obj_copy() which can deep-copy an object.
|
||
|
But this is only suitable for fields in NMPObject*. The purpose of this
|
||
|
rule is that you always can safely copy a NMPlatform* struct without
|
||
|
worrying about the ownership and lifetime of the fields (the field's
|
||
|
lifetime is unlimited).
|
||
|
|
||
|
This rule and managing of resource lifetime is the main reason for the
|
||
|
NMPlatform*/NMPObject* split. NMPlatform* structs simply have no mechanism
|
||
|
for copying/releasing fields, that is why the NMPObject* counterpart exists
|
||
|
(which is ref-counted and has a copy and destructor function).
|
||
|
|
||
|
This is violated in tc_commit() for the "kind" strings. The lifetime
|
||
|
of these strings is tied to the setting instance.
|
||
|
|
||
|
We cannot intern the strings (because these are arbitrary strings
|
||
|
and interned strings are leaked indefinitely). We also cannot g_strdup()
|
||
|
the strings, because NMPlatform* is not supposed to own strings.
|
||
|
|
||
|
So, just add comments that warn about this ugliness.
|
||
|
|
||
|
The more correct solution would be to move the "kind" fields inside
|
||
|
NMPObjectQdisc and NMPObjectTfilter, but that is a lot of extra effort.
|
||
|
|
||
|
(cherry picked from commit f2ae994b2359aa690183a268c5b4cc8fb1a6012e)
|
||
|
---
|
||
|
src/devices/nm-device.c | 14 +++++++++++++
|
||
|
src/platform/nm-linux-platform.c | 6 ++++++
|
||
|
src/platform/nm-platform.c | 34 ++++++++++++++++++++++++++++++++
|
||
|
src/platform/nm-platform.h | 12 +++++++++++
|
||
|
4 files changed, 66 insertions(+)
|
||
|
|
||
|
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
|
||
|
index 5195eb667f..09ba9c5d57 100644
|
||
|
--- a/src/devices/nm-device.c
|
||
|
+++ b/src/devices/nm-device.c
|
||
|
@@ -6516,7 +6516,12 @@ tc_commit (NMDevice *self)
|
||
|
NMPlatformQdisc *qdisc = NMP_OBJECT_CAST_QDISC (q);
|
||
|
|
||
|
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->addr_family = AF_UNSPEC;
|
||
|
qdisc->handle = nm_tc_qdisc_get_handle (s_qdisc);
|
||
|
qdisc->parent = nm_tc_qdisc_get_parent (s_qdisc);
|
||
|
@@ -6558,7 +6563,12 @@ tc_commit (NMDevice *self)
|
||
|
NMPlatformTfilter *tfilter = NMP_OBJECT_CAST_TFILTER (q);
|
||
|
|
||
|
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->addr_family = AF_UNSPEC;
|
||
|
tfilter->handle = nm_tc_tfilter_get_handle (s_tfilter);
|
||
|
tfilter->parent = nm_tc_tfilter_get_parent (s_tfilter);
|
||
|
@@ -6568,7 +6578,11 @@ tc_commit (NMDevice *self)
|
||
|
if (action) {
|
||
|
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);
|
||
|
+
|
||
|
if (strcmp (tfilter->action.kind, "simple") == 0) {
|
||
|
var = nm_tc_action_get_attribute (action, "sdata");
|
||
|
if (var && g_variant_is_of_type (var, G_VARIANT_TYPE_BYTESTRING)) {
|
||
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
||
|
index 4a62a76485..7d66a88fa7 100644
|
||
|
--- a/src/platform/nm-linux-platform.c
|
||
|
+++ b/src/platform/nm-linux-platform.c
|
||
|
@@ -8244,6 +8244,9 @@ qdisc_add (NMPlatform *platform,
|
||
|
char s_buf[256];
|
||
|
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||
|
|
||
|
+ /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind
|
||
|
+ * is undefined. */
|
||
|
+
|
||
|
msg = _nl_msg_new_qdisc (RTM_NEWQDISC, flags, qdisc);
|
||
|
|
||
|
event_handler_read_netlink (platform, FALSE);
|
||
|
@@ -8285,6 +8288,9 @@ tfilter_add (NMPlatform *platform,
|
||
|
char s_buf[256];
|
||
|
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||
|
|
||
|
+ /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind
|
||
|
+ * and tfilter.action.kind is undefined. */
|
||
|
+
|
||
|
msg = _nl_msg_new_tfilter (RTM_NEWTFILTER, flags, tfilter);
|
||
|
|
||
|
event_handler_read_netlink (platform, FALSE);
|
||
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
||
|
index ee71319dd6..7add7dcdbe 100644
|
||
|
--- a/src/platform/nm-platform.c
|
||
|
+++ b/src/platform/nm-platform.c
|
||
|
@@ -5077,10 +5077,27 @@ nm_platform_qdisc_add (NMPlatform *self,
|
||
|
int ifindex = qdisc->ifindex;
|
||
|
_CHECK_SELF (self, klass, -NME_BUG);
|
||
|
|
||
|
+ /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind
|
||
|
+ * is undefined. */
|
||
|
+
|
||
|
_LOG3D ("adding or updating a qdisc: %s", nm_platform_qdisc_to_string (qdisc, NULL, 0));
|
||
|
return klass->qdisc_add (self, flags, qdisc);
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * nm_platform_qdisc_sync:
|
||
|
+ * @self: the #NMPlatform instance
|
||
|
+ * @ifindex: the ifindex where to configure the qdiscs.
|
||
|
+ * @known_qdiscs: the list of qdiscs (#NMPObject).
|
||
|
+ *
|
||
|
+ * The function promises not to take any reference to the qdisc
|
||
|
+ * instances from @known_qdiscs, nor to keep them around after
|
||
|
+ * the function returns. This is important, because it allows the
|
||
|
+ * caller to pass NMPlatformQdisc instances which "kind" string
|
||
|
+ * have a limited lifetime.
|
||
|
+ *
|
||
|
+ * Returns: %TRUE on success.
|
||
|
+ */
|
||
|
gboolean
|
||
|
nm_platform_qdisc_sync (NMPlatform *self,
|
||
|
int ifindex,
|
||
|
@@ -5143,10 +5160,27 @@ nm_platform_tfilter_add (NMPlatform *self,
|
||
|
int ifindex = tfilter->ifindex;
|
||
|
_CHECK_SELF (self, klass, -NME_BUG);
|
||
|
|
||
|
+ /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind
|
||
|
+ * and tfilter.action.kind is undefined. */
|
||
|
+
|
||
|
_LOG3D ("adding or updating a tfilter: %s", nm_platform_tfilter_to_string (tfilter, NULL, 0));
|
||
|
return klass->tfilter_add (self, flags, tfilter);
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * nm_platform_qdisc_sync:
|
||
|
+ * @self: the #NMPlatform instance
|
||
|
+ * @ifindex: the ifindex where to configure the qdiscs.
|
||
|
+ * @known_tfilters: the list of tfilters (#NMPObject).
|
||
|
+ *
|
||
|
+ * The function promises not to take any reference to the tfilter
|
||
|
+ * instances from @known_tfilters, nor to keep them around after
|
||
|
+ * the function returns. This is important, because it allows the
|
||
|
+ * caller to pass NMPlatformTfilter instances which "kind" string
|
||
|
+ * have a limited lifetime.
|
||
|
+ *
|
||
|
+ * Returns: %TRUE on success.
|
||
|
+ */
|
||
|
gboolean
|
||
|
nm_platform_tfilter_sync (NMPlatform *self,
|
||
|
int ifindex,
|
||
|
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
|
||
|
index 9b6848d977..a2d8e57ff6 100644
|
||
|
--- a/src/platform/nm-platform.h
|
||
|
+++ b/src/platform/nm-platform.h
|
||
|
@@ -626,7 +626,11 @@ typedef struct {
|
||
|
|
||
|
typedef struct {
|
||
|
__NMPlatformObjWithIfindex_COMMON;
|
||
|
+
|
||
|
+ /* beware, kind is embedded in an NMPObject, hence you must
|
||
|
+ * take care of the lifetime of the string. */
|
||
|
const char *kind;
|
||
|
+
|
||
|
int addr_family;
|
||
|
guint32 handle;
|
||
|
guint32 parent;
|
||
|
@@ -649,7 +653,11 @@ typedef struct {
|
||
|
} NMPlatformActionMirred;
|
||
|
|
||
|
typedef struct {
|
||
|
+
|
||
|
+ /* beware, kind is embedded in an NMPObject, hence you must
|
||
|
+ * take care of the lifetime of the string. */
|
||
|
const char *kind;
|
||
|
+
|
||
|
union {
|
||
|
NMPlatformActionSimple simple;
|
||
|
NMPlatformActionMirred mirred;
|
||
|
@@ -661,7 +669,11 @@ typedef struct {
|
||
|
|
||
|
typedef struct {
|
||
|
__NMPlatformObjWithIfindex_COMMON;
|
||
|
+
|
||
|
+ /* beware, kind is embedded in an NMPObject, hence you must
|
||
|
+ * take care of the lifetime of the string. */
|
||
|
const char *kind;
|
||
|
+
|
||
|
int addr_family;
|
||
|
guint32 handle;
|
||
|
guint32 parent;
|
||
|
--
|
||
|
2.21.0
|