net_sched: refactor TC action init API
authorCong Wang <cong.wang@bytedance.com>
Thu, 29 Jul 2021 23:12:14 +0000 (16:12 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Aug 2021 09:24:38 +0000 (10:24 +0100)
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>
37 files changed:
include/net/act_api.h
include/net/pkt_cls.h
include/net/sch_generic.h
include/uapi/linux/pkt_cls.h
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gact.c
net/sched/act_gate.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_mpls.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c
net/sched/cls_api.c
net/sched/cls_basic.c
net/sched/cls_bpf.c
net/sched/cls_cgroup.c
net/sched/cls_flow.c
net/sched/cls_flower.c
net/sched/cls_fw.c
net/sched/cls_matchall.c
net/sched/cls_route.c
net/sched/cls_rsvp.h
net/sched/cls_tcindex.c
net/sched/cls_u32.c

index 086b291e9530b225ba0fa151e856ff0638a07502..f19f7f4a463cd9f84d1d8c132a749544243bab2d 100644 (file)
@@ -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);
index dc28fcb6f0a279d2ca7be08a0e1e90ebb08fa64c..64de26b7ad39b63fddddae57d71b86d304f158cd 100644 (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,
                      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);
index 9ed33e6840bd612b96b7e5fc15a6b2ac632b1ba9..c0069ac00e62d28a13cb0086d6657948317b68ca 100644 (file)
@@ -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,
index 025c40fef93d82a7fec026bc34a58b6dcae2d190..6836ccb9c45dcba1e0f9e89061d39a1e2409a28a 100644 (file)
@@ -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.
                                         */
index 998a2374f7ae98eef34885f4f08024ba3cefed15..7dd3a2dc5fa409d86e07964f7185e00f760254e6 100644 (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.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:
index e409a000571728f2d9a3e2158a63a922db376908..040807aa15b947ac04d59a788f546445ecce7c22 100644 (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,
                        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;
                }
index e19885d7fe2cba90b83a3345e201c0dc2b21c53b..94e78ac7a7487f4c3f0904c270f7c563db99ff6f 100644 (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,
                             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;
                }
index 4fa4fcb842ba7cee5b5d9b5a36caa2c83b02e6e2..a15ec95e69c3612594685c0e90fac63cb3d56ea0 100644 (file)
@@ -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;
                }
index 1b4b3514c94f2a29b46a4c481cfc057c4e864ec8..ad9df0cb4b98dda4e2df9ffd5ad57fee7aeb3710 100644 (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,
                       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;
                }
index b20c8ce59905b38024f7fc19cebf39a1dc2ee918..549374a2d0086dac3a371ec84748b6f4297207ac 100644 (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,
                           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;
                }
index 73c3926358a066bb383197cc56d2a75af82e66df..d8dce173df37415de9c939625cf32df9f6750222 100644 (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,
                         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;
                }
index a78cb79657182d6e1a87424f715cc151f29176f7..7df72a4197a3fc98f504086e1d2697a5c5b911da 100644 (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,
                         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;
        }
index a2ddea04183afbf9ddd30e43ad29c4feec56332a..7064a365a1a9834244549b110771d89e1b2895d0 100644 (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,
                        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 {
index ac7297f423559dd39c0227101cac2bffedbaf750..265b1443e252f1bda87f92fb4652298ad4358157 100644 (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,
                          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,
index 7153c67f641e1778b2661582e2f58cdb4c6d5a40..77ee80e3effca6e5173075054e168e735beb8514 100644 (file)
@@ -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;
        }
index d1486ea496a2cacaa6c141f12c13b3210743ecb7..e4529b428cf44a7c54c119d6ca37422a48e64120 100644 (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,
                         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;
        }
index 1ebd2a86d980fc631a5f970543993f37aebdf3b1..7dd6b586ba7f680ee555c1e0d20abca3f9e4583f 100644 (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,
-                       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;
                }
index b45304446e13d04b54c7b08d1d834ab1fcaad500..c6c862c459cc3b9220a96f5c6e6950b349e45fff 100644 (file)
@@ -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;
                }
index 0fab8de176d26775597eaedbdc3015e447f293f2..832157a840fc36961345c9374039c49e1dedfd50 100644 (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,
                               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;
        }
index 6a0c16e4351d717384af50b68abc860d5ef1ee77..230501eb9e069fbcb8de3889161e0cf9d8326b6b 100644 (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,
-                          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;
        }
index 726cc956d06fccd5a79b483a6063d0cc61bd8e68..cbbe1861d3a20c263fa6fe01a7113e1812cc7f7b 100644 (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,
                         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;
                }
index e5f3fb8b00e32a0cc6bcd65cc3fdb54bcb2e0d6f..605418538347482cc27812442df10ef73ce02732 100644 (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,
                            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;
                }
index 762ceec3e6f64e2f2aed8d75e1bc4595843b5223..ecb9ee6660954c1195cd682032138aae53a51ce8 100644 (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,
                           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;
index 85c0d0d5b9da5cdd884028387654090b6a0f7799..d9cd174eecb79baedebe1c2215a8eee7db66c910 100644 (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,
                           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;
index 71f2015c70ca59a62a3b112267320aadc70d6811..e4dc5a555bd85caefb1f6fb8cc6c0b330484261e 100644 (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,
                         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;
        }
index 7be5b9d2aead08752bf50275bda82fe29d6dd89d..69185e311422bf19ffbbdd83bf1a5a7b13dd30fa 100644 (file)
@@ -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;
index f256a7c69093ab610cb144f485e3b48667f4614b..8158fc9ee1ab089e78de825a1767c660ac24757c 100644 (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,
                           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)
index fa739efa59f46c65977be81a73ae5065e024c014..3b472bafdc9dfd75210f3cf5e73e89c8260a2a15 100644 (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,
                             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;
index fb881144fa015078c03e21ace0f9391ca0aea104..ed00001b528a6c63e7122fb38aa9ad9fb928acb7 100644 (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,
                             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;
 
index 87398af2715a3efc53ffa901ca828f4ab810d0c8..972303aa8edd6a753529cc4420f0a9e5ee8ebd59 100644 (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,
                       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;
 
index d7869a984881ed0d19ef0fe936b7014aa75a3912..23b21253b3c3306a28f49ef19df77d48f265dbf6 100644 (file)
@@ -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;
 
index ec945294626a8b3d1cd761b6a2636290fc47d659..8654b0ce997c1cb525222f51a8531e99a3799efb 100644 (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,
                        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;
 
index cafb84480bab8c431ee4dba2bbddbdf701042836..24f0046ce0b333ac1876ab1bdc026fbcbde4dfea 100644 (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,
                          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;
index 5efa3e7ace1524cee08f4cdea15867f4f0c3dd86..a35ab8c27866eeb3e9a7fb4112583b62b92dad92 100644 (file)
@@ -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;
 
index 27a4b6dbcf57e58d7aac0358eb8523508c1907ea..5cd9d6b143c44bf250ca1e53c384e3cf3fab57d2 100644 (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,
                       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;
index e9a8a2c86bbdd033b3dca556fcdb1e79b835b5cd..742c7d49a9581c185b649352034d548bd7fdf4c5 100644 (file)
@@ -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,
index 6e1abe8054483b32f14fb875f6e8d1aceeeee98a..4272814487f091f5dd97fe119d6cece0b99a427c 100644 (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,
                         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;