diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-09 16:23:39 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-30 15:59:41 +0200 |
commit | 900292147d8fd584479a7af0881984c2d77a60bf (patch) | |
tree | e697477cbd16e3ab8724ca3044148e43de4d9d23 | |
parent | 1efe982e39be7e8b7852a19957c7b49cab46e67c (diff) | |
download | NetworkManager-900292147d8fd584479a7af0881984c2d77a60bf.tar.gz |
tc/tfilter: add mirred action
-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 | 29 | ||||
-rw-r--r-- | 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 009e802859..442ab9af64 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -2541,6 +2541,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' ), @@ -2635,6 +2644,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 44eb0f5321..1a9a8a3745 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -6570,16 +6570,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> @@ -4276,6 +4277,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) { @@ -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 @@ -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; |