net_sched: refactor TC action init API

TC action ->init() API has 10 parameters, it becomes harder
to read. Some of them are just boolean and can be replaced
by flags. Similarly for the internal API tcf_action_init()
and tcf_exts_validate().

This patch converts them to flags and fold them into
the upper 16 bits of "flags", whose lower 16 bits are still
reserved for user-space. More specifically, the following
kernel flags are introduced:

TCA_ACT_FLAGS_POLICE replace 'name' in a few contexts, to
distinguish whether it is compatible with policer.

TCA_ACT_FLAGS_BIND replaces 'bind', to indicate whether
this action is bound to a filter.

TCA_ACT_FLAGS_REPLACE  replaces 'ovr' in most contexts,
means we are replacing an existing action.

TCA_ACT_FLAGS_NO_RTNL replaces 'rtnl_held' but has the
opposite meaning, because we still hold RTNL in most
cases.

The only user-space flag TCA_ACT_FLAGS_NO_PERCPU_STATS is
untouched and still stored as before.

I have tested this patch with tdc and I do not see any
failure related to this patch.

Tested-by: Vlad Buslov <vladbu@nvidia.com>
Acked-by: Jamal Hadi Salim<jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Cong Wang 2021-07-29 16:12:14 -07:00 committed by David S. Miller
parent 451395f798
commit 695176bfe5
37 changed files with 185 additions and 169 deletions

View File

@ -58,6 +58,14 @@ struct tc_action {
#define TCA_ACT_HW_STATS_ANY (TCA_ACT_HW_STATS_IMMEDIATE | \ #define TCA_ACT_HW_STATS_ANY (TCA_ACT_HW_STATS_IMMEDIATE | \
TCA_ACT_HW_STATS_DELAYED) TCA_ACT_HW_STATS_DELAYED)
/* Reserve 16 bits for user-space. See TCA_ACT_FLAGS_NO_PERCPU_STATS. */
#define TCA_ACT_FLAGS_USER_BITS 16
#define TCA_ACT_FLAGS_USER_MASK 0xffff
#define TCA_ACT_FLAGS_POLICE (1U << TCA_ACT_FLAGS_USER_BITS)
#define TCA_ACT_FLAGS_BIND (1U << (TCA_ACT_FLAGS_USER_BITS + 1))
#define TCA_ACT_FLAGS_REPLACE (1U << (TCA_ACT_FLAGS_USER_BITS + 2))
#define TCA_ACT_FLAGS_NO_RTNL (1U << (TCA_ACT_FLAGS_USER_BITS + 3))
/* Update lastuse only if needed, to avoid dirtying a cache line. /* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice. * We use a temp variable to avoid fetching jiffies twice.
*/ */
@ -99,8 +107,8 @@ struct tc_action_ops {
void (*cleanup)(struct tc_action *); void (*cleanup)(struct tc_action *);
int (*lookup)(struct net *net, struct tc_action **a, u32 index); int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla, int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr, struct nlattr *est, struct tc_action **act,
int bind, bool rtnl_held, struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack); u32 flags, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *, int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int, struct netlink_callback *, int,
@ -179,18 +187,16 @@ int tcf_action_destroy(struct tc_action *actions[], int bind);
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions, int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
int nr_actions, struct tcf_result *res); int nr_actions, struct tcf_result *res);
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind, struct nlattr *est,
struct tc_action *actions[], int init_res[], size_t *attr_size, struct tc_action *actions[], int init_res[], size_t *attr_size,
bool rtnl_held, struct netlink_ext_ack *extack); u32 flags, struct netlink_ext_ack *extack);
struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, bool police,
bool rtnl_held, bool rtnl_held,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est, struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind,
struct tc_action_ops *a_o, int *init_res, struct tc_action_ops *a_o, int *init_res,
bool rtnl_held, u32 flags, struct netlink_ext_ack *extack);
struct netlink_ext_ack *extack);
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind,
int ref, bool terse); int ref, bool terse);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);

View File

@ -319,7 +319,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
int tcf_exts_validate(struct net *net, struct tcf_proto *tp, int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
struct nlattr **tb, struct nlattr *rate_tlv, struct nlattr **tb, struct nlattr *rate_tlv,
struct tcf_exts *exts, bool ovr, bool rtnl_held, struct tcf_exts *exts, u32 flags,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
void tcf_exts_destroy(struct tcf_exts *exts); void tcf_exts_destroy(struct tcf_exts *exts);
void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);

View File

@ -357,7 +357,7 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *, int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long, struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **, u32 handle, struct nlattr **,
void **, bool, bool, void **, u32,
struct netlink_ext_ack *); struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg, int (*delete)(struct tcf_proto *tp, void *arg,
bool *last, bool rtnl_held, bool *last, bool rtnl_held,

View File

@ -22,6 +22,7 @@ enum {
__TCA_ACT_MAX __TCA_ACT_MAX
}; };
/* See other TCA_ACT_FLAGS_ * flags in include/net/act_api.h. */
#define TCA_ACT_FLAGS_NO_PERCPU_STATS 1 /* Don't use percpu allocator for #define TCA_ACT_FLAGS_NO_PERCPU_STATS 1 /* Don't use percpu allocator for
* actions stats. * actions stats.
*/ */

View File

@ -495,7 +495,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
p->tcfa_tm.install = jiffies; p->tcfa_tm.install = jiffies;
p->tcfa_tm.lastuse = jiffies; p->tcfa_tm.lastuse = jiffies;
p->tcfa_tm.firstuse = 0; p->tcfa_tm.firstuse = 0;
p->tcfa_flags = flags; p->tcfa_flags = flags & TCA_ACT_FLAGS_USER_MASK;
if (est) { if (est) {
err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
&p->tcfa_rate_est, &p->tcfa_rate_est,
@ -941,7 +941,7 @@ void tcf_idr_insert_many(struct tc_action *actions[])
} }
} }
struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, bool police,
bool rtnl_held, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
@ -951,7 +951,7 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
struct nlattr *kind; struct nlattr *kind;
int err; int err;
if (name == NULL) { if (!police) {
err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
tcf_action_policy, extack); tcf_action_policy, extack);
if (err < 0) if (err < 0)
@ -967,7 +967,7 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
return ERR_PTR(err); return ERR_PTR(err);
} }
} else { } else {
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) { if (strlcpy(act_name, "police", IFNAMSIZ) >= IFNAMSIZ) {
NL_SET_ERR_MSG(extack, "TC action name too long"); NL_SET_ERR_MSG(extack, "TC action name too long");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
@ -1004,12 +1004,11 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est, struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind,
struct tc_action_ops *a_o, int *init_res, struct tc_action_ops *a_o, int *init_res,
bool rtnl_held, u32 flags, struct netlink_ext_ack *extack)
struct netlink_ext_ack *extack)
{ {
struct nla_bitfield32 flags = { 0, 0 }; bool police = flags & TCA_ACT_FLAGS_POLICE;
struct nla_bitfield32 userflags = { 0, 0 };
u8 hw_stats = TCA_ACT_HW_STATS_ANY; u8 hw_stats = TCA_ACT_HW_STATS_ANY;
struct nlattr *tb[TCA_ACT_MAX + 1]; struct nlattr *tb[TCA_ACT_MAX + 1];
struct tc_cookie *cookie = NULL; struct tc_cookie *cookie = NULL;
@ -1017,7 +1016,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
int err; int err;
/* backward compatibility for policer */ /* backward compatibility for policer */
if (name == NULL) { if (!police) {
err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
tcf_action_policy, extack); tcf_action_policy, extack);
if (err < 0) if (err < 0)
@ -1032,22 +1031,22 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
} }
hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]); hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]);
if (tb[TCA_ACT_FLAGS]) if (tb[TCA_ACT_FLAGS])
flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]); userflags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]);
err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, tp,
rtnl_held, tp, flags.value, extack); userflags.value | flags, extack);
} else { } else {
err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, err = a_o->init(net, nla, est, &a, tp, userflags.value | flags,
tp, flags.value, extack); extack);
} }
if (err < 0) if (err < 0)
goto err_out; goto err_out;
*init_res = err; *init_res = err;
if (!name && tb[TCA_ACT_COOKIE]) if (!police && tb[TCA_ACT_COOKIE])
tcf_set_action_cookie(&a->act_cookie, cookie); tcf_set_action_cookie(&a->act_cookie, cookie);
if (!name) if (!police)
a->hw_stats = hw_stats; a->hw_stats = hw_stats;
return a; return a;
@ -1063,9 +1062,9 @@ err_out:
/* Returns numbers of initialized actions or negative error. */ /* Returns numbers of initialized actions or negative error. */
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind, struct nlattr *est, struct tc_action *actions[],
struct tc_action *actions[], int init_res[], size_t *attr_size, int init_res[], size_t *attr_size, u32 flags,
bool rtnl_held, struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {};
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
@ -1082,7 +1081,9 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
struct tc_action_ops *a_o; struct tc_action_ops *a_o;
a_o = tc_action_load_ops(name, tb[i], rtnl_held, extack); a_o = tc_action_load_ops(tb[i], flags & TCA_ACT_FLAGS_POLICE,
!(flags & TCA_ACT_FLAGS_NO_RTNL),
extack);
if (IS_ERR(a_o)) { if (IS_ERR(a_o)) {
err = PTR_ERR(a_o); err = PTR_ERR(a_o);
goto err_mod; goto err_mod;
@ -1091,9 +1092,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
} }
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind, act = tcf_action_init_1(net, tp, tb[i], est, ops[i - 1],
ops[i - 1], &init_res[i - 1], rtnl_held, &init_res[i - 1], flags, extack);
extack);
if (IS_ERR(act)) { if (IS_ERR(act)) {
err = PTR_ERR(act); err = PTR_ERR(act);
goto err; goto err;
@ -1113,7 +1113,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
goto err_mod; goto err_mod;
err: err:
tcf_action_destroy(actions, bind); tcf_action_destroy(actions, flags & TCA_ACT_FLAGS_BIND);
err_mod: err_mod:
for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
if (ops[i]) if (ops[i])
@ -1495,7 +1495,7 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
} }
static int tcf_action_add(struct net *net, struct nlattr *nla, static int tcf_action_add(struct net *net, struct nlattr *nla,
struct nlmsghdr *n, u32 portid, int ovr, struct nlmsghdr *n, u32 portid, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
size_t attr_size = 0; size_t attr_size = 0;
@ -1504,8 +1504,8 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
int init_res[TCA_ACT_MAX_PRIO] = {}; int init_res[TCA_ACT_MAX_PRIO] = {};
for (loop = 0; loop < 10; loop++) { for (loop = 0; loop < 10; loop++) {
ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, ret = tcf_action_init(net, NULL, nla, NULL, actions, init_res,
actions, init_res, &attr_size, true, extack); &attr_size, flags, extack);
if (ret != -EAGAIN) if (ret != -EAGAIN)
break; break;
} }
@ -1535,7 +1535,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct nlattr *tca[TCA_ROOT_MAX + 1]; struct nlattr *tca[TCA_ROOT_MAX + 1];
u32 portid = NETLINK_CB(skb).portid; u32 portid = NETLINK_CB(skb).portid;
int ret = 0, ovr = 0; u32 flags = 0;
int ret = 0;
if ((n->nlmsg_type != RTM_GETACTION) && if ((n->nlmsg_type != RTM_GETACTION) &&
!netlink_capable(skb, CAP_NET_ADMIN)) !netlink_capable(skb, CAP_NET_ADMIN))
@ -1561,8 +1562,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
* is zero) then just set this * is zero) then just set this
*/ */
if (n->nlmsg_flags & NLM_F_REPLACE) if (n->nlmsg_flags & NLM_F_REPLACE)
ovr = 1; flags = TCA_ACT_FLAGS_REPLACE;
ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr, ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, flags,
extack); extack);
break; break;
case RTM_DELACTION: case RTM_DELACTION:

View File

@ -275,11 +275,11 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
static int tcf_bpf_init(struct net *net, struct nlattr *nla, static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, struct nlattr *est, struct tc_action **act,
int replace, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, bpf_net_id); struct tc_action_net *tn = net_generic(net, bpf_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tcf_bpf_cfg cfg, old; struct tcf_bpf_cfg cfg, old;
@ -317,7 +317,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (bind) if (bind)
return 0; return 0;
if (!replace) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*act, bind); tcf_idr_release(*act, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -96,12 +96,12 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
static int tcf_connmark_init(struct net *net, struct nlattr *nla, static int tcf_connmark_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, connmark_net_id); struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1]; struct nlattr *tb[TCA_CONNMARK_MAX + 1];
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tcf_connmark_info *ci; struct tcf_connmark_info *ci;
struct tc_connmark *parm; struct tc_connmark *parm;
@ -144,7 +144,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
ci = to_connmark(*a); ci = to_connmark(*a);
if (bind) if (bind)
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -41,11 +41,12 @@ static unsigned int csum_net_id;
static struct tc_action_ops act_csum_ops; static struct tc_action_ops act_csum_ops;
static int tcf_csum_init(struct net *net, struct nlattr *nla, static int tcf_csum_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a,
int bind, bool rtnl_held, struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, csum_net_id); struct tc_action_net *tn = net_generic(net, csum_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct tcf_csum_params *params_new; struct tcf_csum_params *params_new;
struct nlattr *tb[TCA_CSUM_MAX + 1]; struct nlattr *tb[TCA_CSUM_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
@ -78,7 +79,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
} else if (err > 0) { } else if (err > 0) {
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -1235,11 +1235,11 @@ static int tcf_ct_fill_params(struct net *net,
static int tcf_ct_init(struct net *net, struct nlattr *nla, static int tcf_ct_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int replace, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ct_net_id); struct tc_action_net *tn = net_generic(net, ct_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct tcf_ct_params *params = NULL; struct tcf_ct_params *params = NULL;
struct nlattr *tb[TCA_CT_MAX + 1]; struct nlattr *tb[TCA_CT_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
@ -1279,7 +1279,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
if (bind) if (bind)
return 0; return 0;
if (!replace) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -154,11 +154,11 @@ static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = {
static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ctinfo_net_id); struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
u32 dscpmask = 0, dscpstatemask, index; u32 dscpmask = 0, dscpstatemask, index;
struct nlattr *tb[TCA_CTINFO_MAX + 1]; struct nlattr *tb[TCA_CTINFO_MAX + 1];
struct tcf_ctinfo_params *cp_new; struct tcf_ctinfo_params *cp_new;
@ -221,7 +221,7 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
} else if (err > 0) { } else if (err > 0) {
if (bind) /* don't override defaults */ if (bind) /* don't override defaults */
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -52,11 +52,11 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
static int tcf_gact_init(struct net *net, struct nlattr *nla, static int tcf_gact_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, gact_net_id); struct tc_action_net *tn = net_generic(net, gact_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_GACT_MAX + 1]; struct nlattr *tb[TCA_GACT_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_gact *parm; struct tc_gact *parm;
@ -109,7 +109,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
} else if (err > 0) { } else if (err > 0) {
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -295,12 +295,12 @@ static void gate_setup_timer(struct tcf_gate *gact, u64 basetime,
static int tcf_gate_init(struct net *net, struct nlattr *nla, static int tcf_gate_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, gate_net_id); struct tc_action_net *tn = net_generic(net, gate_net_id);
enum tk_offsets tk_offset = TK_OFFS_TAI; enum tk_offsets tk_offset = TK_OFFS_TAI;
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_GATE_MAX + 1]; struct nlattr *tb[TCA_GATE_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
u64 cycletime = 0, basetime = 0; u64 cycletime = 0, basetime = 0;
@ -364,7 +364,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -479,11 +479,11 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
static int tcf_ife_init(struct net *net, struct nlattr *nla, static int tcf_ife_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, ife_net_id); struct tc_action_net *tn = net_generic(net, ife_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_IFE_MAX + 1]; struct nlattr *tb[TCA_IFE_MAX + 1];
struct nlattr *tb2[IFE_META_MAX + 1]; struct nlattr *tb2[IFE_META_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
@ -532,7 +532,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
kfree(p); kfree(p);
return err; return err;
} }
err = load_metalist(tb2, rtnl_held); err = load_metalist(tb2, !(flags & TCA_ACT_FLAGS_NO_RTNL));
if (err) { if (err) {
kfree(p); kfree(p);
return err; return err;
@ -560,7 +560,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
kfree(p); kfree(p);
return -EEXIST; return -EEXIST;
@ -600,7 +600,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
} }
if (tb[TCA_IFE_METALST]) { if (tb[TCA_IFE_METALST]) {
err = populate_metalist(ife, tb2, exists, rtnl_held); err = populate_metalist(ife, tb2, exists,
!(flags & TCA_ACT_FLAGS_NO_RTNL));
if (err) if (err)
goto metadata_parse_err; goto metadata_parse_err;
} else { } else {

View File

@ -94,10 +94,11 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
const struct tc_action_ops *ops, int ovr, int bind, const struct tc_action_ops *ops,
struct tcf_proto *tp, u32 flags) struct tcf_proto *tp, u32 flags)
{ {
struct tc_action_net *tn = net_generic(net, id); struct tc_action_net *tn = net_generic(net, id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_IPT_MAX + 1]; struct nlattr *tb[TCA_IPT_MAX + 1];
struct tcf_ipt *ipt; struct tcf_ipt *ipt;
struct xt_entry_target *td, *t; struct xt_entry_target *td, *t;
@ -154,7 +155,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
if (bind)/* dont override defaults */ if (bind)/* dont override defaults */
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }
@ -201,21 +202,21 @@ err1:
} }
static int tcf_ipt_init(struct net *net, struct nlattr *nla, static int tcf_ipt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a,
int bind, bool rtnl_held, struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr, return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops,
bind, tp, flags); tp, flags);
} }
static int tcf_xt_init(struct net *net, struct nlattr *nla, static int tcf_xt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a,
int bind, bool unlocked, struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr, return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops,
bind, tp, flags); tp, flags);
} }
static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a, static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a,

View File

@ -91,11 +91,11 @@ static struct tc_action_ops act_mirred_ops;
static int tcf_mirred_init(struct net *net, struct nlattr *nla, static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, mirred_net_id); struct tc_action_net *tn = net_generic(net, mirred_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_MIRRED_MAX + 1]; struct nlattr *tb[TCA_MIRRED_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
bool mac_header_xmit = false; bool mac_header_xmit = false;
@ -155,7 +155,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -152,11 +152,11 @@ static const struct nla_policy mpls_policy[TCA_MPLS_MAX + 1] = {
static int tcf_mpls_init(struct net *net, struct nlattr *nla, static int tcf_mpls_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, mpls_net_id); struct tc_action_net *tn = net_generic(net, mpls_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_MPLS_MAX + 1]; struct nlattr *tb[TCA_MPLS_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tcf_mpls_params *p; struct tcf_mpls_params *p;
@ -255,7 +255,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -34,11 +34,11 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
}; };
static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
struct tc_action **a, int ovr, int bind, struct tc_action **a, struct tcf_proto *tp,
bool rtnl_held, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, nat_net_id); struct tc_action_net *tn = net_generic(net, nat_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_NAT_MAX + 1]; struct nlattr *tb[TCA_NAT_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_nat *parm; struct tc_nat *parm;
@ -70,7 +70,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
} else if (err > 0) { } else if (err > 0) {
if (bind) if (bind)
return 0; return 0;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -136,11 +136,11 @@ nla_failure:
static int tcf_pedit_init(struct net *net, struct nlattr *nla, static int tcf_pedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, pedit_net_id); struct tc_action_net *tn = net_generic(net, pedit_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_PEDIT_MAX + 1]; struct nlattr *tb[TCA_PEDIT_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_pedit_key *keys = NULL; struct tc_pedit_key *keys = NULL;
@ -198,7 +198,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
} else if (err > 0) { } else if (err > 0) {
if (bind) if (bind)
goto out_free; goto out_free;
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
ret = -EEXIST; ret = -EEXIST;
goto out_release; goto out_release;
} }

View File

@ -48,11 +48,11 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
static int tcf_police_init(struct net *net, struct nlattr *nla, static int tcf_police_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int ret = 0, tcfp_result = TC_ACT_OK, err, size; int ret = 0, tcfp_result = TC_ACT_OK, err, size;
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_POLICE_MAX + 1]; struct nlattr *tb[TCA_POLICE_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_police *parm; struct tc_police *parm;
@ -97,7 +97,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
spin_lock_init(&(to_police(*a)->tcfp_lock)); spin_lock_init(&(to_police(*a)->tcfp_lock));
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -34,11 +34,12 @@ static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = {
}; };
static int tcf_sample_init(struct net *net, struct nlattr *nla, static int tcf_sample_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a,
int bind, bool rtnl_held, struct tcf_proto *tp, struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, sample_net_id); struct tc_action_net *tn = net_generic(net, sample_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_SAMPLE_MAX + 1]; struct nlattr *tb[TCA_SAMPLE_MAX + 1];
struct psample_group *psample_group; struct psample_group *psample_group;
u32 psample_group_num, rate, index; u32 psample_group_num, rate, index;
@ -75,7 +76,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
return ret; return ret;
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -85,11 +85,11 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
static int tcf_simp_init(struct net *net, struct nlattr *nla, static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, simp_net_id); struct tc_action_net *tn = net_generic(net, simp_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_DEF_MAX + 1]; struct nlattr *tb[TCA_DEF_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
struct tc_defact *parm; struct tc_defact *parm;
@ -147,7 +147,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
tcf_action_set_ctrlact(*a, parm->action, goto_ch); tcf_action_set_ctrlact(*a, parm->action, goto_ch);
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (!ovr) { if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
err = -EEXIST; err = -EEXIST;
goto release_idr; goto release_idr;
} }

View File

@ -96,11 +96,11 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 act_flags, struct tcf_proto *tp, u32 act_flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbedit_net_id); struct tc_action_net *tn = net_generic(net, skbedit_net_id);
bool bind = act_flags & TCA_ACT_FLAGS_BIND;
struct tcf_skbedit_params *params_new; struct tcf_skbedit_params *params_new;
struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
@ -186,7 +186,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
d = to_skbedit(*a); d = to_skbedit(*a);
if (!ovr) { if (!(act_flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -100,11 +100,12 @@ static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = {
static int tcf_skbmod_init(struct net *net, struct nlattr *nla, static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, skbmod_net_id); struct tc_action_net *tn = net_generic(net, skbmod_net_id);
bool ovr = flags & TCA_ACT_FLAGS_REPLACE;
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_SKBMOD_MAX + 1]; struct nlattr *tb[TCA_SKBMOD_MAX + 1];
struct tcf_skbmod_params *p, *p_old; struct tcf_skbmod_params *p, *p_old;
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;

View File

@ -355,11 +355,11 @@ static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
static int tunnel_key_init(struct net *net, struct nlattr *nla, static int tunnel_key_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 act_flags, struct tcf_proto *tp, u32 act_flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
bool bind = act_flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1];
struct tcf_tunnel_key_params *params_new; struct tcf_tunnel_key_params *params_new;
struct metadata_dst *metadata = NULL; struct metadata_dst *metadata = NULL;
@ -504,7 +504,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(act_flags & TCA_ACT_FLAGS_REPLACE)) {
NL_SET_ERR_MSG(extack, "TC IDR already exists"); NL_SET_ERR_MSG(extack, "TC IDR already exists");
ret = -EEXIST; ret = -EEXIST;
goto release_tun_meta; goto release_tun_meta;

View File

@ -114,11 +114,11 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
static int tcf_vlan_init(struct net *net, struct nlattr *nla, static int tcf_vlan_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
int ovr, int bind, bool rtnl_held,
struct tcf_proto *tp, u32 flags, struct tcf_proto *tp, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_action_net *tn = net_generic(net, vlan_net_id); struct tc_action_net *tn = net_generic(net, vlan_net_id);
bool bind = flags & TCA_ACT_FLAGS_BIND;
struct nlattr *tb[TCA_VLAN_MAX + 1]; struct nlattr *tb[TCA_VLAN_MAX + 1];
struct tcf_chain *goto_ch = NULL; struct tcf_chain *goto_ch = NULL;
bool push_prio_exists = false; bool push_prio_exists = false;
@ -223,7 +223,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
} }
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else if (!ovr) { } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -EEXIST; return -EEXIST;
} }

View File

@ -1949,6 +1949,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
int err; int err;
int tp_created; int tp_created;
bool rtnl_held = false; bool rtnl_held = false;
u32 flags = 0;
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
return -EPERM; return -EPERM;
@ -2112,9 +2113,12 @@ replay:
goto errout; goto errout;
} }
if (!(n->nlmsg_flags & NLM_F_CREATE))
flags |= TCA_ACT_FLAGS_REPLACE;
if (!rtnl_held)
flags |= TCA_ACT_FLAGS_NO_RTNL;
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh, err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE, flags, extack);
rtnl_held, extack);
if (err == 0) { if (err == 0) {
tfilter_notify(net, skb, n, tp, block, q, parent, fh, tfilter_notify(net, skb, n, tp, block, q, parent, fh,
RTM_NEWTFILTER, false, rtnl_held); RTM_NEWTFILTER, false, rtnl_held);
@ -3020,8 +3024,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)
EXPORT_SYMBOL(tcf_exts_destroy); EXPORT_SYMBOL(tcf_exts_destroy);
int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr, struct nlattr *rate_tlv, struct tcf_exts *exts,
bool rtnl_held, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
{ {
@ -3032,13 +3036,15 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
if (exts->police && tb[exts->police]) { if (exts->police && tb[exts->police]) {
struct tc_action_ops *a_o; struct tc_action_ops *a_o;
a_o = tc_action_load_ops("police", tb[exts->police], rtnl_held, extack); a_o = tc_action_load_ops(tb[exts->police], true,
!(flags & TCA_ACT_FLAGS_NO_RTNL),
extack);
if (IS_ERR(a_o)) if (IS_ERR(a_o))
return PTR_ERR(a_o); return PTR_ERR(a_o);
flags |= TCA_ACT_FLAGS_POLICE | TCA_ACT_FLAGS_BIND;
act = tcf_action_init_1(net, tp, tb[exts->police], act = tcf_action_init_1(net, tp, tb[exts->police],
rate_tlv, "police", ovr, rate_tlv, a_o, init_res, flags,
TCA_ACT_BIND, a_o, init_res, extack);
rtnl_held, extack);
module_put(a_o->owner); module_put(a_o->owner);
if (IS_ERR(act)) if (IS_ERR(act))
return PTR_ERR(act); return PTR_ERR(act);
@ -3050,10 +3056,10 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
} else if (exts->action && tb[exts->action]) { } else if (exts->action && tb[exts->action]) {
int err; int err;
flags |= TCA_ACT_FLAGS_BIND;
err = tcf_action_init(net, tp, tb[exts->action], err = tcf_action_init(net, tp, tb[exts->action],
rate_tlv, NULL, ovr, TCA_ACT_BIND, rate_tlv, exts->actions, init_res,
exts->actions, init_res, &attr_size, flags, extack);
&attr_size, rtnl_held, extack);
if (err < 0) if (err < 0)
return err; return err;
exts->nr_actions = err; exts->nr_actions = err;

View File

@ -145,12 +145,12 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
static int basic_set_parms(struct net *net, struct tcf_proto *tp, static int basic_set_parms(struct net *net, struct tcf_proto *tp,
struct basic_filter *f, unsigned long base, struct basic_filter *f, unsigned long base,
struct nlattr **tb, struct nlattr **tb,
struct nlattr *est, bool ovr, struct nlattr *est, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int err; int err;
err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, true, extack); err = tcf_exts_validate(net, tp, tb, est, &f->exts, flags, extack);
if (err < 0) if (err < 0)
return err; return err;
@ -169,8 +169,8 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
static int basic_change(struct net *net, struct sk_buff *in_skb, static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg,
bool rtnl_held, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
int err; int err;
struct basic_head *head = rtnl_dereference(tp->root); struct basic_head *head = rtnl_dereference(tp->root);
@ -216,7 +216,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
goto errout; goto errout;
} }
err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr, err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], flags,
extack); extack);
if (err < 0) { if (err < 0) {
if (!fold) if (!fold)

View File

@ -404,7 +404,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp, static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
struct cls_bpf_prog *prog, unsigned long base, struct cls_bpf_prog *prog, unsigned long base,
struct nlattr **tb, struct nlattr *est, bool ovr, struct nlattr **tb, struct nlattr *est, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
bool is_bpf, is_ebpf, have_exts = false; bool is_bpf, is_ebpf, have_exts = false;
@ -416,7 +416,7 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
return -EINVAL; return -EINVAL;
ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, ovr, true, ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, flags,
extack); extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -455,7 +455,7 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, bool rtnl_held, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct cls_bpf_head *head = rtnl_dereference(tp->root); struct cls_bpf_head *head = rtnl_dereference(tp->root);
@ -500,7 +500,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
goto errout; goto errout;
prog->handle = handle; prog->handle = handle;
ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr, ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], flags,
extack); extack);
if (ret < 0) if (ret < 0)
goto errout_idr; goto errout_idr;

View File

@ -76,7 +76,7 @@ static void cls_cgroup_destroy_work(struct work_struct *work)
static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, bool rtnl_held, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[TCA_CGROUP_MAX + 1]; struct nlattr *tb[TCA_CGROUP_MAX + 1];
@ -108,8 +108,8 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
if (err < 0) if (err < 0)
goto errout; goto errout;
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, ovr, err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, flags,
true, extack); extack);
if (err < 0) if (err < 0)
goto errout; goto errout;

View File

@ -387,7 +387,7 @@ static void flow_destroy_filter_work(struct work_struct *work)
static int flow_change(struct net *net, struct sk_buff *in_skb, static int flow_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, bool rtnl_held, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct flow_head *head = rtnl_dereference(tp->root); struct flow_head *head = rtnl_dereference(tp->root);
@ -442,8 +442,8 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
if (err < 0) if (err < 0)
goto err2; goto err2;
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, ovr, err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, flags,
true, extack); extack);
if (err < 0) if (err < 0)
goto err2; goto err2;

View File

@ -1915,23 +1915,22 @@ errout_cleanup:
static int fl_set_parms(struct net *net, struct tcf_proto *tp, static int fl_set_parms(struct net *net, struct tcf_proto *tp,
struct cls_fl_filter *f, struct fl_flow_mask *mask, struct cls_fl_filter *f, struct fl_flow_mask *mask,
unsigned long base, struct nlattr **tb, unsigned long base, struct nlattr **tb,
struct nlattr *est, bool ovr, struct nlattr *est,
struct fl_flow_tmplt *tmplt, bool rtnl_held, struct fl_flow_tmplt *tmplt, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int err; int err;
err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, rtnl_held, err = tcf_exts_validate(net, tp, tb, est, &f->exts, flags, extack);
extack);
if (err < 0) if (err < 0)
return err; return err;
if (tb[TCA_FLOWER_CLASSID]) { if (tb[TCA_FLOWER_CLASSID]) {
f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]); f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
if (!rtnl_held) if (flags & TCA_ACT_FLAGS_NO_RTNL)
rtnl_lock(); rtnl_lock();
tcf_bind_filter(tp, &f->res, base); tcf_bind_filter(tp, &f->res, base);
if (!rtnl_held) if (flags & TCA_ACT_FLAGS_NO_RTNL)
rtnl_unlock(); rtnl_unlock();
} }
@ -1975,10 +1974,11 @@ static int fl_ht_insert_unique(struct cls_fl_filter *fnew,
static int fl_change(struct net *net, struct sk_buff *in_skb, static int fl_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, bool rtnl_held, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct cls_fl_head *head = fl_head_dereference(tp); struct cls_fl_head *head = fl_head_dereference(tp);
bool rtnl_held = !(flags & TCA_ACT_FLAGS_NO_RTNL);
struct cls_fl_filter *fold = *arg; struct cls_fl_filter *fold = *arg;
struct cls_fl_filter *fnew; struct cls_fl_filter *fnew;
struct fl_flow_mask *mask; struct fl_flow_mask *mask;
@ -2034,8 +2034,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
} }
} }
err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr, err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE],
tp->chain->tmplt_priv, rtnl_held, extack); tp->chain->tmplt_priv, flags, extack);
if (err) if (err)
goto errout; goto errout;

View File

@ -198,15 +198,15 @@ static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
static int fw_set_parms(struct net *net, struct tcf_proto *tp, static int fw_set_parms(struct net *net, struct tcf_proto *tp,
struct fw_filter *f, struct nlattr **tb, struct fw_filter *f, struct nlattr **tb,
struct nlattr **tca, unsigned long base, bool ovr, struct nlattr **tca, unsigned long base, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
u32 mask; u32 mask;
int err; int err;
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, ovr, err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, flags,
true, extack); extack);
if (err < 0) if (err < 0)
return err; return err;
@ -237,8 +237,7 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
static int fw_change(struct net *net, struct sk_buff *in_skb, static int fw_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, void **arg, u32 handle, struct nlattr **tca, void **arg,
bool ovr, bool rtnl_held, u32 flags, struct netlink_ext_ack *extack)
struct netlink_ext_ack *extack)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f = *arg; struct fw_filter *f = *arg;
@ -277,7 +276,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
err = fw_set_parms(net, tp, fnew, tb, tca, base, ovr, extack); err = fw_set_parms(net, tp, fnew, tb, tca, base, flags, extack);
if (err < 0) { if (err < 0) {
tcf_exts_destroy(&fnew->exts); tcf_exts_destroy(&fnew->exts);
kfree(fnew); kfree(fnew);
@ -326,7 +325,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
f->id = handle; f->id = handle;
f->tp = tp; f->tp = tp;
err = fw_set_parms(net, tp, f, tb, tca, base, ovr, extack); err = fw_set_parms(net, tp, f, tb, tca, base, flags, extack);
if (err < 0) if (err < 0)
goto errout; goto errout;

View File

@ -163,13 +163,12 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
static int mall_set_parms(struct net *net, struct tcf_proto *tp, static int mall_set_parms(struct net *net, struct tcf_proto *tp,
struct cls_mall_head *head, struct cls_mall_head *head,
unsigned long base, struct nlattr **tb, unsigned long base, struct nlattr **tb,
struct nlattr *est, bool ovr, struct nlattr *est, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int err; int err;
err = tcf_exts_validate(net, tp, tb, est, &head->exts, ovr, true, err = tcf_exts_validate(net, tp, tb, est, &head->exts, flags, extack);
extack);
if (err < 0) if (err < 0)
return err; return err;
@ -183,13 +182,13 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
static int mall_change(struct net *net, struct sk_buff *in_skb, static int mall_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, bool rtnl_held, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct cls_mall_head *head = rtnl_dereference(tp->root); struct cls_mall_head *head = rtnl_dereference(tp->root);
struct nlattr *tb[TCA_MATCHALL_MAX + 1]; struct nlattr *tb[TCA_MATCHALL_MAX + 1];
struct cls_mall_head *new; struct cls_mall_head *new;
u32 flags = 0; u32 userflags = 0;
int err; int err;
if (!tca[TCA_OPTIONS]) if (!tca[TCA_OPTIONS])
@ -204,8 +203,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
if (tb[TCA_MATCHALL_FLAGS]) { if (tb[TCA_MATCHALL_FLAGS]) {
flags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]); userflags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]);
if (!tc_flags_valid(flags)) if (!tc_flags_valid(userflags))
return -EINVAL; return -EINVAL;
} }
@ -220,14 +219,14 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
if (!handle) if (!handle)
handle = 1; handle = 1;
new->handle = handle; new->handle = handle;
new->flags = flags; new->flags = userflags;
new->pf = alloc_percpu(struct tc_matchall_pcnt); new->pf = alloc_percpu(struct tc_matchall_pcnt);
if (!new->pf) { if (!new->pf) {
err = -ENOMEM; err = -ENOMEM;
goto err_alloc_percpu; goto err_alloc_percpu;
} }
err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr, err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], flags,
extack); extack);
if (err) if (err)
goto err_set_parms; goto err_set_parms;

View File

@ -382,7 +382,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, struct route4_filter *f, unsigned long base, struct route4_filter *f,
u32 handle, struct route4_head *head, u32 handle, struct route4_head *head,
struct nlattr **tb, struct nlattr *est, int new, struct nlattr **tb, struct nlattr *est, int new,
bool ovr, struct netlink_ext_ack *extack) u32 flags, struct netlink_ext_ack *extack)
{ {
u32 id = 0, to = 0, nhandle = 0x8000; u32 id = 0, to = 0, nhandle = 0x8000;
struct route4_filter *fp; struct route4_filter *fp;
@ -390,7 +390,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
struct route4_bucket *b; struct route4_bucket *b;
int err; int err;
err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, true, extack); err = tcf_exts_validate(net, tp, tb, est, &f->exts, flags, extack);
if (err < 0) if (err < 0)
return err; return err;
@ -464,8 +464,8 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
static int route4_change(struct net *net, struct sk_buff *in_skb, static int route4_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, u32 flags,
bool rtnl_held, struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct route4_head *head = rtnl_dereference(tp->root); struct route4_head *head = rtnl_dereference(tp->root);
struct route4_filter __rcu **fp; struct route4_filter __rcu **fp;
@ -510,7 +510,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
} }
err = route4_set_parms(net, tp, base, f, handle, head, tb, err = route4_set_parms(net, tp, base, f, handle, head, tb,
tca[TCA_RATE], new, ovr, extack); tca[TCA_RATE], new, flags, extack);
if (err < 0) if (err < 0)
goto errout; goto errout;

View File

@ -470,9 +470,8 @@ static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
static int rsvp_change(struct net *net, struct sk_buff *in_skb, static int rsvp_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle, struct nlattr **tca,
struct nlattr **tca, void **arg, u32 flags,
void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct rsvp_head *data = rtnl_dereference(tp->root); struct rsvp_head *data = rtnl_dereference(tp->root);
@ -499,7 +498,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
err = tcf_exts_init(&e, net, TCA_RSVP_ACT, TCA_RSVP_POLICE); err = tcf_exts_init(&e, net, TCA_RSVP_ACT, TCA_RSVP_POLICE);
if (err < 0) if (err < 0)
return err; return err;
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr, true, err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, flags,
extack); extack);
if (err < 0) if (err < 0)
goto errout2; goto errout2;

View File

@ -330,7 +330,7 @@ static int
tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
u32 handle, struct tcindex_data *p, u32 handle, struct tcindex_data *p,
struct tcindex_filter_result *r, struct nlattr **tb, struct tcindex_filter_result *r, struct nlattr **tb,
struct nlattr *est, bool ovr, struct netlink_ext_ack *extack) struct nlattr *est, u32 flags, struct netlink_ext_ack *extack)
{ {
struct tcindex_filter_result new_filter_result, *old_r = r; struct tcindex_filter_result new_filter_result, *old_r = r;
struct tcindex_data *cp = NULL, *oldp; struct tcindex_data *cp = NULL, *oldp;
@ -342,7 +342,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
err = tcf_exts_init(&e, net, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); err = tcf_exts_init(&e, net, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
if (err < 0) if (err < 0)
return err; return err;
err = tcf_exts_validate(net, tp, tb, est, &e, ovr, true, extack); err = tcf_exts_validate(net, tp, tb, est, &e, flags, extack);
if (err < 0) if (err < 0)
goto errout; goto errout;
@ -529,8 +529,8 @@ errout:
static int static int
tcindex_change(struct net *net, struct sk_buff *in_skb, tcindex_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, u32 flags,
bool rtnl_held, struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_TCINDEX_MAX + 1]; struct nlattr *tb[TCA_TCINDEX_MAX + 1];
@ -551,7 +551,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
return tcindex_set_parms(net, tp, base, handle, p, r, tb, return tcindex_set_parms(net, tp, base, handle, p, r, tb,
tca[TCA_RATE], ovr, extack); tca[TCA_RATE], flags, extack);
} }
static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker, static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker,

View File

@ -709,12 +709,12 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
static int u32_set_parms(struct net *net, struct tcf_proto *tp, static int u32_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, unsigned long base,
struct tc_u_knode *n, struct nlattr **tb, struct tc_u_knode *n, struct nlattr **tb,
struct nlattr *est, bool ovr, struct nlattr *est, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
int err; int err;
err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr, true, extack); err = tcf_exts_validate(net, tp, tb, est, &n->exts, flags, extack);
if (err < 0) if (err < 0)
return err; return err;
@ -840,7 +840,7 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp,
static int u32_change(struct net *net, struct sk_buff *in_skb, static int u32_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, bool rtnl_held, struct nlattr **tca, void **arg, u32 flags,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_u_common *tp_c = tp->data; struct tc_u_common *tp_c = tp->data;
@ -849,7 +849,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
struct tc_u32_sel *s; struct tc_u32_sel *s;
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_U32_MAX + 1]; struct nlattr *tb[TCA_U32_MAX + 1];
u32 htid, flags = 0; u32 htid, userflags = 0;
size_t sel_size; size_t sel_size;
int err; int err;
@ -868,8 +868,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
if (tb[TCA_U32_FLAGS]) { if (tb[TCA_U32_FLAGS]) {
flags = nla_get_u32(tb[TCA_U32_FLAGS]); userflags = nla_get_u32(tb[TCA_U32_FLAGS]);
if (!tc_flags_valid(flags)) { if (!tc_flags_valid(userflags)) {
NL_SET_ERR_MSG_MOD(extack, "Invalid filter flags"); NL_SET_ERR_MSG_MOD(extack, "Invalid filter flags");
return -EINVAL; return -EINVAL;
} }
@ -884,7 +884,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return -EINVAL; return -EINVAL;
} }
if ((n->flags ^ flags) & if ((n->flags ^ userflags) &
~(TCA_CLS_FLAGS_IN_HW | TCA_CLS_FLAGS_NOT_IN_HW)) { ~(TCA_CLS_FLAGS_IN_HW | TCA_CLS_FLAGS_NOT_IN_HW)) {
NL_SET_ERR_MSG_MOD(extack, "Key node flags do not match passed flags"); NL_SET_ERR_MSG_MOD(extack, "Key node flags do not match passed flags");
return -EINVAL; return -EINVAL;
@ -895,7 +895,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return -ENOMEM; return -ENOMEM;
err = u32_set_parms(net, tp, base, new, tb, err = u32_set_parms(net, tp, base, new, tb,
tca[TCA_RATE], ovr, extack); tca[TCA_RATE], flags, extack);
if (err) { if (err) {
u32_destroy_key(new, false); u32_destroy_key(new, false);
@ -955,9 +955,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
ht->handle = handle; ht->handle = handle;
ht->prio = tp->prio; ht->prio = tp->prio;
idr_init(&ht->handle_idr); idr_init(&ht->handle_idr);
ht->flags = flags; ht->flags = userflags;
err = u32_replace_hw_hnode(tp, ht, flags, extack); err = u32_replace_hw_hnode(tp, ht, userflags, extack);
if (err) { if (err) {
idr_remove(&tp_c->handle_idr, handle); idr_remove(&tp_c->handle_idr, handle);
kfree(ht); kfree(ht);
@ -1038,7 +1038,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
RCU_INIT_POINTER(n->ht_up, ht); RCU_INIT_POINTER(n->ht_up, ht);
n->handle = handle; n->handle = handle;
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
n->flags = flags; n->flags = userflags;
err = tcf_exts_init(&n->exts, net, TCA_U32_ACT, TCA_U32_POLICE); err = tcf_exts_init(&n->exts, net, TCA_U32_ACT, TCA_U32_POLICE);
if (err < 0) if (err < 0)
@ -1060,7 +1060,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
} }
#endif #endif
err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE], ovr, err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE], flags,
extack); extack);
if (err == 0) { if (err == 0) {
struct tc_u_knode __rcu **ins; struct tc_u_knode __rcu **ins;