summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2019-04-09 16:23:39 +0200
committerLubomir Rintel <lkundrak@v3.sk>2019-04-09 16:23:39 +0200
commit94a14ceffe8ccd65d175ed5661868cffb9f37339 (patch)
treebf16c20baf03019a64cd7e0303da42de0f52acf7
parente4f2c2d8b2a939209ead2606c79c9f83fbbfd81c (diff)
downloadNetworkManager-lr/tc-attrs.tar.gz
tc/tfilter: add mirred actionlr/tc-attrs
-rw-r--r--libnm-core/nm-utils.c11
-rw-r--r--src/devices/nm-device.c29
-rw-r--r--src/platform/nm-linux-platform.c33
-rw-r--r--src/platform/nm-platform.c27
-rw-r--r--src/platform/nm-platform.h10
5 files changed, 103 insertions, 7 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index cbeeae05a1..4e0bd97938 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -2561,6 +2561,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' ),
@@ -2665,6 +2674,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 b6afe7fbcd..23574966d8 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -6588,16 +6588,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 2fd5c81790..a1dd5e70b7 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>
@@ -4335,6 +4336,36 @@ nla_put_failure:
}
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)
{
@@ -4349,6 +4380,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 ec6affd968..044b03a80d 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"
@@ -6480,6 +6481,13 @@ 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';
@@ -6508,8 +6516,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);
+ }
}
}
@@ -6526,8 +6542,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 008865dab7..1a37846dd8 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -624,13 +624,23 @@ typedef struct {
} 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;