@@ -30,6 +30,7 @@ enum {
TCA_VLAN_PUSH_VLAN_PROTOCOL,
TCA_VLAN_PAD,
TCA_VLAN_PUSH_VLAN_PRIORITY,
+ TCA_VLAN_FLAGS,
__TCA_VLAN_MAX,
};
#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1)
@@ -97,6 +97,8 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
[TCA_VLAN_PUSH_VLAN_ID] = { .type = NLA_U16 },
[TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type = NLA_U16 },
[TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type = NLA_U8 },
+ [TCA_VLAN_FLAGS] = { .type = NLA_BITFIELD32,
+ .validation_data = &tca_flags_allowed },
};
static int tcf_vlan_init(struct net *net, struct nlattr *nla,
@@ -109,6 +111,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
struct tcf_chain *goto_ch = NULL;
struct tcf_vlan_params *p;
struct tc_vlan *parm;
+ u32 index, flags = 0;
struct tcf_vlan *v;
int action;
u16 push_vid = 0;
@@ -116,7 +119,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
u8 push_prio = 0;
bool exists = false;
int ret = 0, err;
- u32 index;
if (!nla)
return -EINVAL;
@@ -187,9 +189,12 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
}
action = parm->v_action;
+ if (tb[TCA_VLAN_FLAGS])
+ flags = nla_get_bitfield32(tb[TCA_VLAN_FLAGS]).value;
+
if (!exists) {
ret = tcf_idr_create(tn, index, est, a,
- &act_vlan_ops, bind, 0);
+ &act_vlan_ops, bind, flags);
if (ret) {
tcf_idr_cleanup(tn, index);
return ret;
@@ -277,6 +282,14 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
(nla_put_u8(skb, TCA_VLAN_PUSH_VLAN_PRIORITY,
p->tcfv_push_prio))))
goto nla_put_failure;
+ if (v->tcf_flags) {
+ struct nla_bitfield32 flags = { v->tcf_flags,
+ v->tcf_flags };
+
+ if (nla_put(skb, TCA_VLAN_FLAGS, sizeof(struct nla_bitfield32),
+ &flags))
+ goto nla_put_failure;
+ }
tcf_tm_dump(&t, &v->tcf_tm);
if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))