tc/tfilter: add mirred action
This commit is contained in:
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user