@@ -21,6 +21,7 @@ enum {
TCA_MIRRED_TM,
TCA_MIRRED_PARMS,
TCA_MIRRED_PAD,
+ TCA_MIRRED_FLAGS,
__TCA_MIRRED_MAX
};
#define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1)
@@ -84,6 +84,8 @@ static void tcf_mirred_release(struct tc_action *a)
static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
[TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) },
+ [TCA_MIRRED_FLAGS] = { .type = NLA_BITFIELD32,
+ .validation_data = &tca_flags_allowed },
};
static unsigned int mirred_net_id;
@@ -102,9 +104,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct tc_mirred *parm;
struct tcf_mirred *m;
struct net_device *dev;
+ u32 index, flags = 0;
bool exists = false;
int ret, err;
- u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
@@ -142,6 +144,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
+ if (tb[TCA_MIRRED_FLAGS])
+ flags = nla_get_bitfield32(tb[TCA_MIRRED_FLAGS]).value;
+
if (!exists) {
if (!parm->ifindex) {
tcf_idr_cleanup(tn, index);
@@ -149,7 +154,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
ret = tcf_idr_create(tn, index, est, a,
- &act_mirred_ops, bind, 0);
+ &act_mirred_ops, bind, flags);
if (ret) {
tcf_idr_cleanup(tn, index);
return ret;
@@ -344,6 +349,14 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
if (nla_put(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt))
goto nla_put_failure;
+ if (m->tcf_flags) {
+ struct nla_bitfield32 flags = { m->tcf_flags,
+ m->tcf_flags };
+
+ if (nla_put(skb, TCA_MIRRED_FLAGS,
+ sizeof(struct nla_bitfield32), &flags))
+ goto nla_put_failure;
+ }
tcf_tm_dump(&t, &m->tcf_tm);
if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD))