Commit 95e27a4d authored by John Hurley's avatar John Hurley Committed by David S. Miller

net: sched: ensure tc flower reoffload takes filter ref

Recent changes to TC flower remove the requirement for rtnl lock when
accessing and modifying filters. Refcounts now ensure access and deletion
do not happen concurrently. However, the reoffload function which cycles
through all filters and replays them to registered hw drivers is not
protected.

Use the fl_get_next_filter() function to cycle the filters for reoffload
and ensure the ref taken by this function is put when done with each
filter.
Signed-off-by: default avatarJohn Hurley <john.hurley@netronome.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarVlad Buslov <vladbu@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 847d44ef
...@@ -1683,41 +1683,41 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg, ...@@ -1683,41 +1683,41 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
void *cb_priv, struct netlink_ext_ack *extack) void *cb_priv, struct netlink_ext_ack *extack)
{ {
struct cls_fl_head *head = fl_head_dereference(tp);
struct tc_cls_flower_offload cls_flower = {}; struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = tp->chain->block; struct tcf_block *block = tp->chain->block;
struct fl_flow_mask *mask; unsigned long handle = 0;
struct cls_fl_filter *f; struct cls_fl_filter *f;
int err; int err;
list_for_each_entry(mask, &head->masks, list) { while ((f = fl_get_next_filter(tp, &handle))) {
list_for_each_entry(f, &mask->filters, list) {
if (tc_skip_hw(f->flags)) if (tc_skip_hw(f->flags))
continue; goto next_flow;
cls_flower.rule = cls_flower.rule =
flow_rule_alloc(tcf_exts_num_actions(&f->exts)); flow_rule_alloc(tcf_exts_num_actions(&f->exts));
if (!cls_flower.rule) if (!cls_flower.rule) {
__fl_put(f);
return -ENOMEM; return -ENOMEM;
}
tc_cls_common_offload_init(&cls_flower.common, tp, tc_cls_common_offload_init(&cls_flower.common, tp, f->flags,
f->flags, extack); extack);
cls_flower.command = add ? cls_flower.command = add ?
TC_CLSFLOWER_REPLACE : TC_CLSFLOWER_DESTROY; TC_CLSFLOWER_REPLACE : TC_CLSFLOWER_DESTROY;
cls_flower.cookie = (unsigned long)f; cls_flower.cookie = (unsigned long)f;
cls_flower.rule->match.dissector = &mask->dissector; cls_flower.rule->match.dissector = &f->mask->dissector;
cls_flower.rule->match.mask = &mask->key; cls_flower.rule->match.mask = &f->mask->key;
cls_flower.rule->match.key = &f->mkey; cls_flower.rule->match.key = &f->mkey;
err = tc_setup_flow_action(&cls_flower.rule->action, err = tc_setup_flow_action(&cls_flower.rule->action, &f->exts);
&f->exts);
if (err) { if (err) {
kfree(cls_flower.rule); kfree(cls_flower.rule);
if (tc_skip_sw(f->flags)) { if (tc_skip_sw(f->flags)) {
NL_SET_ERR_MSG_MOD(extack, "Failed to setup flow action"); NL_SET_ERR_MSG_MOD(extack, "Failed to setup flow action");
__fl_put(f);
return err; return err;
} }
continue; goto next_flow;
} }
cls_flower.classid = f->res.classid; cls_flower.classid = f->res.classid;
...@@ -1726,16 +1726,20 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, ...@@ -1726,16 +1726,20 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
kfree(cls_flower.rule); kfree(cls_flower.rule);
if (err) { if (err) {
if (add && tc_skip_sw(f->flags)) if (add && tc_skip_sw(f->flags)) {
__fl_put(f);
return err; return err;
continue; }
goto next_flow;
} }
spin_lock(&tp->lock); spin_lock(&tp->lock);
tc_cls_offload_cnt_update(block, &f->in_hw_count, tc_cls_offload_cnt_update(block, &f->in_hw_count, &f->flags,
&f->flags, add); add);
spin_unlock(&tp->lock); spin_unlock(&tp->lock);
} next_flow:
handle++;
__fl_put(f);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment