@@ -22,6 +22,7 @@ enum {
TCA_CT_NAT_PORT_MIN, /* be16 */
TCA_CT_NAT_PORT_MAX, /* be16 */
TCA_CT_PAD,
+ TCA_CT_FLAGS,
__TCA_CT_MAX
};
@@ -492,6 +492,8 @@ static const struct nla_policy ct_policy[TCA_CT_MAX + 1] = {
.len = sizeof(struct in6_addr) },
[TCA_CT_NAT_PORT_MIN] = { .type = NLA_U16 },
[TCA_CT_NAT_PORT_MAX] = { .type = NLA_U16 },
+ [TCA_CT_FLAGS] = { .type = NLA_BITFIELD32,
+ .validation_data = &tca_flags_allowed },
};
static int tcf_ct_fill_params_nat(struct tcf_ct_params *p,
@@ -663,10 +665,10 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
struct tcf_ct_params *params = NULL;
struct nlattr *tb[TCA_CT_MAX + 1];
struct tcf_chain *goto_ch = NULL;
+ u32 index, flags = 0;
struct tc_ct *parm;
struct tcf_ct *c;
int err, res = 0;
- u32 index;
if (!nla) {
NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed");
@@ -687,9 +689,12 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
if (err < 0)
return err;
+ if (tb[TCA_CT_FLAGS])
+ flags = nla_get_bitfield32(tb[TCA_CT_FLAGS]).value;
+
if (!err) {
err = tcf_idr_create(tn, index, est, a,
- &act_ct_ops, bind, 0);
+ &act_ct_ops, bind, flags);
if (err) {
tcf_idr_cleanup(tn, index);
return err;
@@ -870,6 +875,14 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a,
skip_dump:
if (nla_put(skb, TCA_CT_PARMS, sizeof(opt), &opt))
goto nla_put_failure;
+ if (c->tcf_flags) {
+ struct nla_bitfield32 flags = { c->tcf_flags,
+ c->tcf_flags };
+
+ if (nla_put(skb, TCA_CT_FLAGS, sizeof(struct nla_bitfield32),
+ &flags))
+ goto nla_put_failure;
+ }
tcf_tm_dump(&t, &c->tcf_tm);
if (nla_put_64bit(skb, TCA_CT_TM, sizeof(t), &t, TCA_CT_PAD))