diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-09 16:23:39 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-09 16:23:39 +0200 |
commit | 94a14ceffe8ccd65d175ed5661868cffb9f37339 (patch) | |
tree | bf16c20baf03019a64cd7e0303da42de0f52acf7 | |
parent | e4f2c2d8b2a939209ead2606c79c9f83fbbfd81c (diff) | |
download | NetworkManager-lr/tc-attrs.tar.gz |
tc/tfilter: add mirred actionlr/tc-attrs
-rw-r--r-- | libnm-core/nm-utils.c | 11 | ||||
-rw-r--r-- | src/devices/nm-device.c | 29 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 33 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 27 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 10 |
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; |