forked from Minki/linux
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:
parent
451395f798
commit
695176bfe5
@ -58,6 +58,14 @@ struct tc_action {
|
||||
#define TCA_ACT_HW_STATS_ANY (TCA_ACT_HW_STATS_IMMEDIATE | \
|
||||
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.
|
||||
* We use a temp variable to avoid fetching jiffies twice.
|
||||
*/
|
||||
@ -99,8 +107,8 @@ struct tc_action_ops {
|
||||
void (*cleanup)(struct tc_action *);
|
||||
int (*lookup)(struct net *net, struct tc_action **a, u32 index);
|
||||
int (*init)(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **act, int ovr,
|
||||
int bind, bool rtnl_held, struct tcf_proto *tp,
|
||||
struct nlattr *est, struct tc_action **act,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack);
|
||||
int (*walk)(struct net *, struct sk_buff *,
|
||||
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 nr_actions, struct tcf_result *res);
|
||||
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,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack);
|
||||
struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
|
||||
u32 flags, struct netlink_ext_ack *extack);
|
||||
struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, bool police,
|
||||
bool rtnl_held,
|
||||
struct netlink_ext_ack *extack);
|
||||
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
|
||||
struct nlattr *nla, struct nlattr *est,
|
||||
char *name, int ovr, int bind,
|
||||
struct tc_action_ops *a_o, int *init_res,
|
||||
bool rtnl_held,
|
||||
struct netlink_ext_ack *extack);
|
||||
u32 flags, struct netlink_ext_ack *extack);
|
||||
int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind,
|
||||
int ref, bool terse);
|
||||
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
|
||||
|
@ -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,
|
||||
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);
|
||||
void tcf_exts_destroy(struct tcf_exts *exts);
|
||||
void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
|
||||
|
@ -357,7 +357,7 @@ struct tcf_proto_ops {
|
||||
int (*change)(struct net *net, struct sk_buff *,
|
||||
struct tcf_proto*, unsigned long,
|
||||
u32 handle, struct nlattr **,
|
||||
void **, bool, bool,
|
||||
void **, u32,
|
||||
struct netlink_ext_ack *);
|
||||
int (*delete)(struct tcf_proto *tp, void *arg,
|
||||
bool *last, bool rtnl_held,
|
||||
|
@ -22,6 +22,7 @@ enum {
|
||||
__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
|
||||
* actions stats.
|
||||
*/
|
||||
|
@ -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.lastuse = jiffies;
|
||||
p->tcfa_tm.firstuse = 0;
|
||||
p->tcfa_flags = flags;
|
||||
p->tcfa_flags = flags & TCA_ACT_FLAGS_USER_MASK;
|
||||
if (est) {
|
||||
err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
|
||||
&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,
|
||||
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;
|
||||
int err;
|
||||
|
||||
if (name == NULL) {
|
||||
if (!police) {
|
||||
err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
|
||||
tcf_action_policy, extack);
|
||||
if (err < 0)
|
||||
@ -967,7 +967,7 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
} 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");
|
||||
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 nlattr *nla, struct nlattr *est,
|
||||
char *name, int ovr, int bind,
|
||||
struct tc_action_ops *a_o, int *init_res,
|
||||
bool rtnl_held,
|
||||
struct netlink_ext_ack *extack)
|
||||
u32 flags, 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;
|
||||
struct nlattr *tb[TCA_ACT_MAX + 1];
|
||||
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;
|
||||
|
||||
/* backward compatibility for policer */
|
||||
if (name == NULL) {
|
||||
if (!police) {
|
||||
err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
|
||||
tcf_action_policy, extack);
|
||||
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]);
|
||||
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,
|
||||
rtnl_held, tp, flags.value, extack);
|
||||
err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, tp,
|
||||
userflags.value | flags, extack);
|
||||
} else {
|
||||
err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
|
||||
tp, flags.value, extack);
|
||||
err = a_o->init(net, nla, est, &a, tp, userflags.value | flags,
|
||||
extack);
|
||||
}
|
||||
if (err < 0)
|
||||
goto err_out;
|
||||
*init_res = err;
|
||||
|
||||
if (!name && tb[TCA_ACT_COOKIE])
|
||||
if (!police && tb[TCA_ACT_COOKIE])
|
||||
tcf_set_action_cookie(&a->act_cookie, cookie);
|
||||
|
||||
if (!name)
|
||||
if (!police)
|
||||
a->hw_stats = hw_stats;
|
||||
|
||||
return a;
|
||||
@ -1063,9 +1062,9 @@ err_out:
|
||||
/* Returns numbers of initialized actions or negative error. */
|
||||
|
||||
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
|
||||
struct nlattr *est, char *name, int ovr, int bind,
|
||||
struct tc_action *actions[], int init_res[], size_t *attr_size,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack)
|
||||
struct nlattr *est, struct tc_action *actions[],
|
||||
int init_res[], size_t *attr_size, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {};
|
||||
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++) {
|
||||
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)) {
|
||||
err = PTR_ERR(a_o);
|
||||
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++) {
|
||||
act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
|
||||
ops[i - 1], &init_res[i - 1], rtnl_held,
|
||||
extack);
|
||||
act = tcf_action_init_1(net, tp, tb[i], est, ops[i - 1],
|
||||
&init_res[i - 1], flags, extack);
|
||||
if (IS_ERR(act)) {
|
||||
err = PTR_ERR(act);
|
||||
goto err;
|
||||
@ -1113,7 +1113,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
|
||||
goto err_mod;
|
||||
|
||||
err:
|
||||
tcf_action_destroy(actions, bind);
|
||||
tcf_action_destroy(actions, flags & TCA_ACT_FLAGS_BIND);
|
||||
err_mod:
|
||||
for (i = 0; i < TCA_ACT_MAX_PRIO; 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,
|
||||
struct nlmsghdr *n, u32 portid, int ovr,
|
||||
struct nlmsghdr *n, u32 portid, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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] = {};
|
||||
|
||||
for (loop = 0; loop < 10; loop++) {
|
||||
ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0,
|
||||
actions, init_res, &attr_size, true, extack);
|
||||
ret = tcf_action_init(net, NULL, nla, NULL, actions, init_res,
|
||||
&attr_size, flags, extack);
|
||||
if (ret != -EAGAIN)
|
||||
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 nlattr *tca[TCA_ROOT_MAX + 1];
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
int ret = 0, ovr = 0;
|
||||
u32 flags = 0;
|
||||
int ret = 0;
|
||||
|
||||
if ((n->nlmsg_type != RTM_GETACTION) &&
|
||||
!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
|
||||
*/
|
||||
if (n->nlmsg_flags & NLM_F_REPLACE)
|
||||
ovr = 1;
|
||||
ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
|
||||
flags = TCA_ACT_FLAGS_REPLACE;
|
||||
ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, flags,
|
||||
extack);
|
||||
break;
|
||||
case RTM_DELACTION:
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **act,
|
||||
int replace, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
struct tcf_bpf_cfg cfg, old;
|
||||
@ -317,7 +317,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
if (bind)
|
||||
return 0;
|
||||
|
||||
if (!replace) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*act, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tc_action_net *tn = net_generic(net, connmark_net_id);
|
||||
struct nlattr *tb[TCA_CONNMARK_MAX + 1];
|
||||
bool bind = flags & TCA_ACT_FLAGS_BIND;
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
struct tcf_connmark_info *ci;
|
||||
struct tc_connmark *parm;
|
||||
@ -144,7 +144,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
|
||||
ci = to_connmark(*a);
|
||||
if (bind)
|
||||
return 0;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -41,11 +41,12 @@ static unsigned int csum_net_id;
|
||||
static struct tc_action_ops act_csum_ops;
|
||||
|
||||
static int tcf_csum_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a, int ovr,
|
||||
int bind, bool rtnl_held, struct tcf_proto *tp,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 nlattr *tb[TCA_CSUM_MAX + 1];
|
||||
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) {
|
||||
if (bind)/* dont override defaults */
|
||||
return 0;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -1235,11 +1235,11 @@ static int tcf_ct_fill_params(struct net *net,
|
||||
|
||||
static int tcf_ct_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int replace, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 nlattr *tb[TCA_CT_MAX + 1];
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
@ -1279,7 +1279,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
|
||||
if (bind)
|
||||
return 0;
|
||||
|
||||
if (!replace) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
|
||||
bool bind = flags & TCA_ACT_FLAGS_BIND;
|
||||
u32 dscpmask = 0, dscpstatemask, index;
|
||||
struct nlattr *tb[TCA_CTINFO_MAX + 1];
|
||||
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) {
|
||||
if (bind) /* don't override defaults */
|
||||
return 0;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
struct tc_gact *parm;
|
||||
@ -109,7 +109,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
|
||||
} else if (err > 0) {
|
||||
if (bind)/* dont override defaults */
|
||||
return 0;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tc_action_net *tn = net_generic(net, gate_net_id);
|
||||
enum tk_offsets tk_offset = TK_OFFS_TAI;
|
||||
bool bind = flags & TCA_ACT_FLAGS_BIND;
|
||||
struct nlattr *tb[TCA_GATE_MAX + 1];
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
u64 cycletime = 0, basetime = 0;
|
||||
@ -364,7 +364,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 *tb2[IFE_META_MAX + 1];
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
@ -532,7 +532,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
|
||||
kfree(p);
|
||||
return err;
|
||||
}
|
||||
err = load_metalist(tb2, rtnl_held);
|
||||
err = load_metalist(tb2, !(flags & TCA_ACT_FLAGS_NO_RTNL));
|
||||
if (err) {
|
||||
kfree(p);
|
||||
return err;
|
||||
@ -560,7 +560,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
|
||||
return ret;
|
||||
}
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
kfree(p);
|
||||
return -EEXIST;
|
||||
@ -600,7 +600,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
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)
|
||||
goto metadata_parse_err;
|
||||
} else {
|
||||
|
@ -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,
|
||||
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 tc_action_net *tn = net_generic(net, id);
|
||||
bool bind = flags & TCA_ACT_FLAGS_BIND;
|
||||
struct nlattr *tb[TCA_IPT_MAX + 1];
|
||||
struct tcf_ipt *ipt;
|
||||
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 */
|
||||
return 0;
|
||||
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
@ -201,21 +202,21 @@ err1:
|
||||
}
|
||||
|
||||
static int tcf_ipt_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a, int ovr,
|
||||
int bind, bool rtnl_held, struct tcf_proto *tp,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
|
||||
bind, tp, flags);
|
||||
return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops,
|
||||
tp, flags);
|
||||
}
|
||||
|
||||
static int tcf_xt_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a, int ovr,
|
||||
int bind, bool unlocked, struct tcf_proto *tp,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
|
||||
bind, tp, flags);
|
||||
return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops,
|
||||
tp, flags);
|
||||
}
|
||||
|
||||
static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a,
|
||||
|
@ -91,11 +91,11 @@ static struct tc_action_ops act_mirred_ops;
|
||||
|
||||
static int tcf_mirred_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
bool mac_header_xmit = false;
|
||||
@ -155,7 +155,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
|
||||
return ret;
|
||||
}
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
struct tcf_mpls_params *p;
|
||||
@ -255,7 +255,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct tc_action **a, int ovr, int bind,
|
||||
bool rtnl_held, struct tcf_proto *tp,
|
||||
struct tc_action **a, struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
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) {
|
||||
if (bind)
|
||||
return 0;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ nla_failure:
|
||||
|
||||
static int tcf_pedit_init(struct net *net, struct nlattr *nla,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = 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) {
|
||||
if (bind)
|
||||
goto out_free;
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
ret = -EEXIST;
|
||||
goto out_release;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
struct tc_police *parm;
|
||||
@ -97,7 +97,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
ret = ACT_P_CREATED;
|
||||
spin_lock_init(&(to_police(*a)->tcfp_lock));
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a, int ovr,
|
||||
int bind, bool rtnl_held, struct tcf_proto *tp,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
struct tcf_proto *tp,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 psample_group *psample_group;
|
||||
u32 psample_group_num, rate, index;
|
||||
@ -75,7 +76,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
|
||||
return ret;
|
||||
}
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
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);
|
||||
ret = ACT_P_CREATED;
|
||||
} else {
|
||||
if (!ovr) {
|
||||
if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
err = -EEXIST;
|
||||
goto release_idr;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 act_flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 nlattr *tb[TCA_SKBEDIT_MAX + 1];
|
||||
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;
|
||||
} else {
|
||||
d = to_skbedit(*a);
|
||||
if (!ovr) {
|
||||
if (!(act_flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_skbmod_params *p, *p_old;
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 act_flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_tunnel_key_params *params_new;
|
||||
struct metadata_dst *metadata = NULL;
|
||||
@ -504,7 +504,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(act_flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
NL_SET_ERR_MSG(extack, "TC IDR already exists");
|
||||
ret = -EEXIST;
|
||||
goto release_tun_meta;
|
||||
|
@ -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,
|
||||
struct nlattr *est, struct tc_action **a,
|
||||
int ovr, int bind, bool rtnl_held,
|
||||
struct tcf_proto *tp, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 tcf_chain *goto_ch = NULL;
|
||||
bool push_prio_exists = false;
|
||||
@ -223,7 +223,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
ret = ACT_P_CREATED;
|
||||
} else if (!ovr) {
|
||||
} else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
|
||||
tcf_idr_release(*a, bind);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
@ -1949,6 +1949,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
|
||||
int err;
|
||||
int tp_created;
|
||||
bool rtnl_held = false;
|
||||
u32 flags = 0;
|
||||
|
||||
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
@ -2112,9 +2113,12 @@ replay:
|
||||
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,
|
||||
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE,
|
||||
rtnl_held, extack);
|
||||
flags, extack);
|
||||
if (err == 0) {
|
||||
tfilter_notify(net, skb, n, tp, block, q, parent, fh,
|
||||
RTM_NEWTFILTER, false, rtnl_held);
|
||||
@ -3020,8 +3024,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)
|
||||
EXPORT_SYMBOL(tcf_exts_destroy);
|
||||
|
||||
int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
|
||||
struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack)
|
||||
struct nlattr *rate_tlv, struct tcf_exts *exts,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
#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]) {
|
||||
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))
|
||||
return PTR_ERR(a_o);
|
||||
flags |= TCA_ACT_FLAGS_POLICE | TCA_ACT_FLAGS_BIND;
|
||||
act = tcf_action_init_1(net, tp, tb[exts->police],
|
||||
rate_tlv, "police", ovr,
|
||||
TCA_ACT_BIND, a_o, init_res,
|
||||
rtnl_held, extack);
|
||||
rate_tlv, a_o, init_res, flags,
|
||||
extack);
|
||||
module_put(a_o->owner);
|
||||
if (IS_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]) {
|
||||
int err;
|
||||
|
||||
flags |= TCA_ACT_FLAGS_BIND;
|
||||
err = tcf_action_init(net, tp, tb[exts->action],
|
||||
rate_tlv, NULL, ovr, TCA_ACT_BIND,
|
||||
exts->actions, init_res,
|
||||
&attr_size, rtnl_held, extack);
|
||||
rate_tlv, exts->actions, init_res,
|
||||
&attr_size, flags, extack);
|
||||
if (err < 0)
|
||||
return err;
|
||||
exts->nr_actions = err;
|
||||
|
@ -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,
|
||||
struct basic_filter *f, unsigned long base,
|
||||
struct nlattr **tb,
|
||||
struct nlattr *est, bool ovr,
|
||||
struct nlattr *est, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca, void **arg, bool ovr,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack)
|
||||
struct nlattr **tca, void **arg,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
int err;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (err < 0) {
|
||||
if (!fold)
|
||||
|
@ -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,
|
||||
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)
|
||||
{
|
||||
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))
|
||||
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);
|
||||
if (ret < 0)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
if (ret < 0)
|
||||
goto errout_idr;
|
||||
|
@ -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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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)
|
||||
goto errout;
|
||||
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, ovr,
|
||||
true, extack);
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &new->exts, flags,
|
||||
extack);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
|
@ -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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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)
|
||||
goto err2;
|
||||
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, ovr,
|
||||
true, extack);
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &fnew->exts, flags,
|
||||
extack);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
|
@ -1915,23 +1915,22 @@ errout_cleanup:
|
||||
static int fl_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
struct cls_fl_filter *f, struct fl_flow_mask *mask,
|
||||
unsigned long base, struct nlattr **tb,
|
||||
struct nlattr *est, bool ovr,
|
||||
struct fl_flow_tmplt *tmplt, bool rtnl_held,
|
||||
struct nlattr *est,
|
||||
struct fl_flow_tmplt *tmplt, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, rtnl_held,
|
||||
extack);
|
||||
err = tcf_exts_validate(net, tp, tb, est, &f->exts, flags, extack);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (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();
|
||||
tcf_bind_filter(tp, &f->res, base);
|
||||
if (!rtnl_held)
|
||||
if (flags & TCA_ACT_FLAGS_NO_RTNL)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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 *fnew;
|
||||
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,
|
||||
tp->chain->tmplt_priv, rtnl_held, extack);
|
||||
err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE],
|
||||
tp->chain->tmplt_priv, flags, extack);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
|
@ -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,
|
||||
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 fw_head *head = rtnl_dereference(tp->root);
|
||||
u32 mask;
|
||||
int err;
|
||||
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, ovr,
|
||||
true, extack);
|
||||
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &f->exts, flags,
|
||||
extack);
|
||||
if (err < 0)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca, void **arg,
|
||||
bool ovr, bool rtnl_held,
|
||||
struct netlink_ext_ack *extack)
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct fw_head *head = rtnl_dereference(tp->root);
|
||||
struct fw_filter *f = *arg;
|
||||
@ -277,7 +276,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
|
||||
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) {
|
||||
tcf_exts_destroy(&fnew->exts);
|
||||
kfree(fnew);
|
||||
@ -326,7 +325,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
|
||||
f->id = handle;
|
||||
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)
|
||||
goto errout;
|
||||
|
||||
|
@ -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,
|
||||
struct cls_mall_head *head,
|
||||
unsigned long base, struct nlattr **tb,
|
||||
struct nlattr *est, bool ovr,
|
||||
struct nlattr *est, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = tcf_exts_validate(net, tp, tb, est, &head->exts, ovr, true,
|
||||
extack);
|
||||
err = tcf_exts_validate(net, tp, tb, est, &head->exts, flags, extack);
|
||||
if (err < 0)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct cls_mall_head *head = rtnl_dereference(tp->root);
|
||||
struct nlattr *tb[TCA_MATCHALL_MAX + 1];
|
||||
struct cls_mall_head *new;
|
||||
u32 flags = 0;
|
||||
u32 userflags = 0;
|
||||
int err;
|
||||
|
||||
if (!tca[TCA_OPTIONS])
|
||||
@ -204,8 +203,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
|
||||
return err;
|
||||
|
||||
if (tb[TCA_MATCHALL_FLAGS]) {
|
||||
flags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]);
|
||||
if (!tc_flags_valid(flags))
|
||||
userflags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]);
|
||||
if (!tc_flags_valid(userflags))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -220,14 +219,14 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
|
||||
if (!handle)
|
||||
handle = 1;
|
||||
new->handle = handle;
|
||||
new->flags = flags;
|
||||
new->flags = userflags;
|
||||
new->pf = alloc_percpu(struct tc_matchall_pcnt);
|
||||
if (!new->pf) {
|
||||
err = -ENOMEM;
|
||||
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);
|
||||
if (err)
|
||||
goto err_set_parms;
|
||||
|
@ -382,7 +382,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
unsigned long base, struct route4_filter *f,
|
||||
u32 handle, struct route4_head *head,
|
||||
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;
|
||||
struct route4_filter *fp;
|
||||
@ -390,7 +390,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
struct route4_bucket *b;
|
||||
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)
|
||||
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,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca, void **arg, bool ovr,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack)
|
||||
struct nlattr **tca, void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct route4_head *head = rtnl_dereference(tp->root);
|
||||
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,
|
||||
tca[TCA_RATE], new, ovr, extack);
|
||||
tca[TCA_RATE], new, flags, extack);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
|
@ -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,
|
||||
struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle,
|
||||
struct nlattr **tca,
|
||||
void **arg, bool ovr, bool rtnl_held,
|
||||
u32 handle, struct nlattr **tca,
|
||||
void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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);
|
||||
if (err < 0)
|
||||
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);
|
||||
if (err < 0)
|
||||
goto errout2;
|
||||
|
@ -330,7 +330,7 @@ static int
|
||||
tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
||||
u32 handle, struct tcindex_data *p,
|
||||
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_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);
|
||||
if (err < 0)
|
||||
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)
|
||||
goto errout;
|
||||
|
||||
@ -529,8 +529,8 @@ errout:
|
||||
static int
|
||||
tcindex_change(struct net *net, struct sk_buff *in_skb,
|
||||
struct tcf_proto *tp, unsigned long base, u32 handle,
|
||||
struct nlattr **tca, void **arg, bool ovr,
|
||||
bool rtnl_held, struct netlink_ext_ack *extack)
|
||||
struct nlattr **tca, void **arg, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nlattr *opt = tca[TCA_OPTIONS];
|
||||
struct nlattr *tb[TCA_TCINDEX_MAX + 1];
|
||||
@ -551,7 +551,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
|
||||
return err;
|
||||
|
||||
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,
|
||||
|
@ -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,
|
||||
unsigned long base,
|
||||
struct tc_u_knode *n, struct nlattr **tb,
|
||||
struct nlattr *est, bool ovr,
|
||||
struct nlattr *est, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
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)
|
||||
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,
|
||||
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 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 nlattr *opt = tca[TCA_OPTIONS];
|
||||
struct nlattr *tb[TCA_U32_MAX + 1];
|
||||
u32 htid, flags = 0;
|
||||
u32 htid, userflags = 0;
|
||||
size_t sel_size;
|
||||
int err;
|
||||
|
||||
@ -868,8 +868,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||
return err;
|
||||
|
||||
if (tb[TCA_U32_FLAGS]) {
|
||||
flags = nla_get_u32(tb[TCA_U32_FLAGS]);
|
||||
if (!tc_flags_valid(flags)) {
|
||||
userflags = nla_get_u32(tb[TCA_U32_FLAGS]);
|
||||
if (!tc_flags_valid(userflags)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Invalid filter flags");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -884,7 +884,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((n->flags ^ flags) &
|
||||
if ((n->flags ^ userflags) &
|
||||
~(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");
|
||||
return -EINVAL;
|
||||
@ -895,7 +895,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||
return -ENOMEM;
|
||||
|
||||
err = u32_set_parms(net, tp, base, new, tb,
|
||||
tca[TCA_RATE], ovr, extack);
|
||||
tca[TCA_RATE], flags, extack);
|
||||
|
||||
if (err) {
|
||||
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->prio = tp->prio;
|
||||
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) {
|
||||
idr_remove(&tp_c->handle_idr, handle);
|
||||
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);
|
||||
n->handle = handle;
|
||||
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);
|
||||
if (err < 0)
|
||||
@ -1060,7 +1060,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||
}
|
||||
#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);
|
||||
if (err == 0) {
|
||||
struct tc_u_knode __rcu **ins;
|
||||
|
Loading…
Reference in New Issue
Block a user