]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
net: sched: take rtnl lock in tc_setup_flow_action()
authorVlad Buslov <vladbu@mellanox.com>
Mon, 26 Aug 2019 13:45:03 +0000 (16:45 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Aug 2019 21:17:43 +0000 (14:17 -0700)
In order to allow using new flow_action infrastructure from unlocked
classifiers, modify tc_setup_flow_action() to accept new 'rtnl_held'
argument. Take rtnl lock before accessing tc_action data. This is necessary
to protect from concurrent action replace.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/pkt_cls.h
net/sched/cls_api.c
net/sched/cls_flower.c
net/sched/cls_matchall.c

index 612232492f6739289d94b215ef33914fe7a98bbe..a48824bc148972c1af02737747df857bd4456272 100644 (file)
@@ -504,7 +504,7 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
 }
 
 int tc_setup_flow_action(struct flow_action *flow_action,
-                        const struct tcf_exts *exts);
+                        const struct tcf_exts *exts, bool rtnl_held);
 int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
                     void *type_data, bool err_stop, bool rtnl_held);
 int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp,
index 3c103cf9fd0d69c4bf76c5516342dc5b779c38fb..8751bb8a682ff9783e060bc4b027a5e6b7d39ee7 100644 (file)
@@ -3266,14 +3266,17 @@ int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp,
 EXPORT_SYMBOL(tc_setup_cb_reoffload);
 
 int tc_setup_flow_action(struct flow_action *flow_action,
-                        const struct tcf_exts *exts)
+                        const struct tcf_exts *exts, bool rtnl_held)
 {
        const struct tc_action *act;
-       int i, j, k;
+       int i, j, k, err = 0;
 
        if (!exts)
                return 0;
 
+       if (!rtnl_held)
+               rtnl_lock();
+
        j = 0;
        tcf_exts_for_each_action(i, act, exts) {
                struct flow_action_entry *entry;
@@ -3318,6 +3321,7 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                                entry->vlan.prio = tcf_vlan_push_prio(act);
                                break;
                        default:
+                               err = -EOPNOTSUPP;
                                goto err_out;
                        }
                } else if (is_tcf_tunnel_set(act)) {
@@ -3335,6 +3339,7 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                                        entry->id = FLOW_ACTION_ADD;
                                        break;
                                default:
+                                       err = -EOPNOTSUPP;
                                        goto err_out;
                                }
                                entry->mangle.htype = tcf_pedit_htype(act, k);
@@ -3393,15 +3398,19 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                        entry->id = FLOW_ACTION_PTYPE;
                        entry->ptype = tcf_skbedit_ptype(act);
                } else {
+                       err = -EOPNOTSUPP;
                        goto err_out;
                }
 
                if (!is_tcf_pedit(act))
                        j++;
        }
-       return 0;
+
 err_out:
-       return -EOPNOTSUPP;
+       if (!rtnl_held)
+               rtnl_unlock();
+
+       return err;
 }
 EXPORT_SYMBOL(tc_setup_flow_action);
 
index 5cb694469b517626667e9a9419a7ff116d0024ee..fb305bd45d9317fc0a2593f712b43c0338b71f78 100644 (file)
@@ -452,7 +452,8 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
        cls_flower.rule->match.key = &f->mkey;
        cls_flower.classid = f->res.classid;
 
-       err = tc_setup_flow_action(&cls_flower.rule->action, &f->exts);
+       err = tc_setup_flow_action(&cls_flower.rule->action, &f->exts,
+                                  true);
        if (err) {
                kfree(cls_flower.rule);
                if (skip_sw)
@@ -1819,7 +1820,8 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                cls_flower.rule->match.mask = &f->mask->key;
                cls_flower.rule->match.key = &f->mkey;
 
-               err = tc_setup_flow_action(&cls_flower.rule->action, &f->exts);
+               err = tc_setup_flow_action(&cls_flower.rule->action, &f->exts,
+                                          true);
                if (err) {
                        kfree(cls_flower.rule);
                        if (tc_skip_sw(f->flags)) {
index 911d1ea28bb2305a97bf9b18a43154c3d813c1bd..3266f25011ccaa29f5ddbc18a47f4df0d644bb4b 100644 (file)
@@ -97,7 +97,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
        cls_mall.command = TC_CLSMATCHALL_REPLACE;
        cls_mall.cookie = cookie;
 
-       err = tc_setup_flow_action(&cls_mall.rule->action, &head->exts);
+       err = tc_setup_flow_action(&cls_mall.rule->action, &head->exts, true);
        if (err) {
                kfree(cls_mall.rule);
                mall_destroy_hw_filter(tp, head, cookie, NULL);
@@ -300,7 +300,7 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                TC_CLSMATCHALL_REPLACE : TC_CLSMATCHALL_DESTROY;
        cls_mall.cookie = (unsigned long)head;
 
-       err = tc_setup_flow_action(&cls_mall.rule->action, &head->exts);
+       err = tc_setup_flow_action(&cls_mall.rule->action, &head->exts, true);
        if (err) {
                kfree(cls_mall.rule);
                if (add && tc_skip_sw(head->flags)) {