Skip to content

Commit

Permalink
net: sched: take reference to action dev before calling offloads
Browse files Browse the repository at this point in the history
In order to remove dependency on rtnl lock when calling hardware offload
API, take reference to action mirred dev when initializing flow_action
structure in tc_setup_flow_action(). Implement function
tc_cleanup_flow_action(), use it to release the device after hardware
offload API is done using it.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vlad Buslov authored and David S. Miller committed Aug 26, 2019
1 parent 9838b20 commit 5a6ff4b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)

int tc_setup_flow_action(struct flow_action *flow_action,
const struct tcf_exts *exts, bool rtnl_held);
void tc_cleanup_flow_action(struct flow_action *flow_action);

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,
Expand Down
32 changes: 32 additions & 0 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3265,6 +3265,27 @@ int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp,
}
EXPORT_SYMBOL(tc_setup_cb_reoffload);

void tc_cleanup_flow_action(struct flow_action *flow_action)
{
struct flow_action_entry *entry;
int i;

flow_action_for_each(i, entry, flow_action) {
switch (entry->id) {
case FLOW_ACTION_REDIRECT:
case FLOW_ACTION_MIRRED:
case FLOW_ACTION_REDIRECT_INGRESS:
case FLOW_ACTION_MIRRED_INGRESS:
if (entry->dev)
dev_put(entry->dev);
break;
default:
break;
}
}
}
EXPORT_SYMBOL(tc_cleanup_flow_action);

int tc_setup_flow_action(struct flow_action *flow_action,
const struct tcf_exts *exts, bool rtnl_held)
{
Expand Down Expand Up @@ -3294,15 +3315,23 @@ int tc_setup_flow_action(struct flow_action *flow_action,
} else if (is_tcf_mirred_egress_redirect(act)) {
entry->id = FLOW_ACTION_REDIRECT;
entry->dev = tcf_mirred_dev(act);
if (entry->dev)
dev_hold(entry->dev);
} else if (is_tcf_mirred_egress_mirror(act)) {
entry->id = FLOW_ACTION_MIRRED;
entry->dev = tcf_mirred_dev(act);
if (entry->dev)
dev_hold(entry->dev);
} else if (is_tcf_mirred_ingress_redirect(act)) {
entry->id = FLOW_ACTION_REDIRECT_INGRESS;
entry->dev = tcf_mirred_dev(act);
if (entry->dev)
dev_hold(entry->dev);
} else if (is_tcf_mirred_ingress_mirror(act)) {
entry->id = FLOW_ACTION_MIRRED_INGRESS;
entry->dev = tcf_mirred_dev(act);
if (entry->dev)
dev_hold(entry->dev);
} else if (is_tcf_vlan(act)) {
switch (tcf_vlan_action(act)) {
case TCA_VLAN_ACT_PUSH:
Expand Down Expand Up @@ -3410,6 +3439,9 @@ int tc_setup_flow_action(struct flow_action *flow_action,
if (!rtnl_held)
rtnl_unlock();

if (err)
tc_cleanup_flow_action(flow_action);

return err;
}
EXPORT_SYMBOL(tc_setup_flow_action);
Expand Down
2 changes: 2 additions & 0 deletions net/sched/cls_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,

err = tc_setup_cb_add(block, tp, TC_SETUP_CLSFLOWER, &cls_flower,
skip_sw, &f->flags, &f->in_hw_count, true);
tc_cleanup_flow_action(&cls_flower.rule->action);
kfree(cls_flower.rule);

if (err) {
Expand Down Expand Up @@ -1838,6 +1839,7 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
TC_SETUP_CLSFLOWER, &cls_flower,
cb_priv, &f->flags,
&f->in_hw_count);
tc_cleanup_flow_action(&cls_flower.rule->action);
kfree(cls_flower.rule);

if (err) {
Expand Down

0 comments on commit 5a6ff4b

Please sign in to comment.