diff options
author | Vlad Buslov <vladbu@mellanox.com> | 2019-08-26 09:45:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-08-26 17:17:43 -0400 |
commit | 5a6ff4b13d598573fc954f672cd2a267b76a01ec (patch) | |
tree | 5d0222c2eb4a232f49a9b4f33dddd57ccf982586 | |
parent | 9838b20a7fb28c69fa66ac8e68d967ffe1d0ecad (diff) |
net: sched: take reference to action dev before calling offloads
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>
-rw-r--r-- | include/net/pkt_cls.h | 2 | ||||
-rw-r--r-- | net/sched/cls_api.c | 32 | ||||
-rw-r--r-- | net/sched/cls_flower.c | 2 |
3 files changed, 36 insertions, 0 deletions
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index a48824bc1489..e553fc80eb23 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h | |||
@@ -505,6 +505,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex) | |||
505 | 505 | ||
506 | int tc_setup_flow_action(struct flow_action *flow_action, | 506 | int tc_setup_flow_action(struct flow_action *flow_action, |
507 | const struct tcf_exts *exts, bool rtnl_held); | 507 | const struct tcf_exts *exts, bool rtnl_held); |
508 | void tc_cleanup_flow_action(struct flow_action *flow_action); | ||
509 | |||
508 | int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, | 510 | int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type, |
509 | void *type_data, bool err_stop, bool rtnl_held); | 511 | void *type_data, bool err_stop, bool rtnl_held); |
510 | int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp, | 512 | int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp, |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 8751bb8a682f..d988737693e4 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -3265,6 +3265,27 @@ int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp, | |||
3265 | } | 3265 | } |
3266 | EXPORT_SYMBOL(tc_setup_cb_reoffload); | 3266 | EXPORT_SYMBOL(tc_setup_cb_reoffload); |
3267 | 3267 | ||
3268 | void tc_cleanup_flow_action(struct flow_action *flow_action) | ||
3269 | { | ||
3270 | struct flow_action_entry *entry; | ||
3271 | int i; | ||
3272 | |||
3273 | flow_action_for_each(i, entry, flow_action) { | ||
3274 | switch (entry->id) { | ||
3275 | case FLOW_ACTION_REDIRECT: | ||
3276 | case FLOW_ACTION_MIRRED: | ||
3277 | case FLOW_ACTION_REDIRECT_INGRESS: | ||
3278 | case FLOW_ACTION_MIRRED_INGRESS: | ||
3279 | if (entry->dev) | ||
3280 | dev_put(entry->dev); | ||
3281 | break; | ||
3282 | default: | ||
3283 | break; | ||
3284 | } | ||
3285 | } | ||
3286 | } | ||
3287 | EXPORT_SYMBOL(tc_cleanup_flow_action); | ||
3288 | |||
3268 | int tc_setup_flow_action(struct flow_action *flow_action, | 3289 | int tc_setup_flow_action(struct flow_action *flow_action, |
3269 | const struct tcf_exts *exts, bool rtnl_held) | 3290 | const struct tcf_exts *exts, bool rtnl_held) |
3270 | { | 3291 | { |
@@ -3294,15 +3315,23 @@ int tc_setup_flow_action(struct flow_action *flow_action, | |||
3294 | } else if (is_tcf_mirred_egress_redirect(act)) { | 3315 | } else if (is_tcf_mirred_egress_redirect(act)) { |
3295 | entry->id = FLOW_ACTION_REDIRECT; | 3316 | entry->id = FLOW_ACTION_REDIRECT; |
3296 | entry->dev = tcf_mirred_dev(act); | 3317 | entry->dev = tcf_mirred_dev(act); |
3318 | if (entry->dev) | ||
3319 | dev_hold(entry->dev); | ||
3297 | } else if (is_tcf_mirred_egress_mirror(act)) { | 3320 | } else if (is_tcf_mirred_egress_mirror(act)) { |
3298 | entry->id = FLOW_ACTION_MIRRED; | 3321 | entry->id = FLOW_ACTION_MIRRED; |
3299 | entry->dev = tcf_mirred_dev(act); | 3322 | entry->dev = tcf_mirred_dev(act); |
3323 | if (entry->dev) | ||
3324 | dev_hold(entry->dev); | ||
3300 | } else if (is_tcf_mirred_ingress_redirect(act)) { | 3325 | } else if (is_tcf_mirred_ingress_redirect(act)) { |
3301 | entry->id = FLOW_ACTION_REDIRECT_INGRESS; | 3326 | entry->id = FLOW_ACTION_REDIRECT_INGRESS; |
3302 | entry->dev = tcf_mirred_dev(act); | 3327 | entry->dev = tcf_mirred_dev(act); |
3328 | if (entry->dev) | ||
3329 | dev_hold(entry->dev); | ||
3303 | } else if (is_tcf_mirred_ingress_mirror(act)) { | 3330 | } else if (is_tcf_mirred_ingress_mirror(act)) { |
3304 | entry->id = FLOW_ACTION_MIRRED_INGRESS; | 3331 | entry->id = FLOW_ACTION_MIRRED_INGRESS; |
3305 | entry->dev = tcf_mirred_dev(act); | 3332 | entry->dev = tcf_mirred_dev(act); |
3333 | if (entry->dev) | ||
3334 | dev_hold(entry->dev); | ||
3306 | } else if (is_tcf_vlan(act)) { | 3335 | } else if (is_tcf_vlan(act)) { |
3307 | switch (tcf_vlan_action(act)) { | 3336 | switch (tcf_vlan_action(act)) { |
3308 | case TCA_VLAN_ACT_PUSH: | 3337 | case TCA_VLAN_ACT_PUSH: |
@@ -3410,6 +3439,9 @@ err_out: | |||
3410 | if (!rtnl_held) | 3439 | if (!rtnl_held) |
3411 | rtnl_unlock(); | 3440 | rtnl_unlock(); |
3412 | 3441 | ||
3442 | if (err) | ||
3443 | tc_cleanup_flow_action(flow_action); | ||
3444 | |||
3413 | return err; | 3445 | return err; |
3414 | } | 3446 | } |
3415 | EXPORT_SYMBOL(tc_setup_flow_action); | 3447 | EXPORT_SYMBOL(tc_setup_flow_action); |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index fb305bd45d93..2852fe6f50d2 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
@@ -465,6 +465,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, | |||
465 | 465 | ||
466 | err = tc_setup_cb_add(block, tp, TC_SETUP_CLSFLOWER, &cls_flower, | 466 | err = tc_setup_cb_add(block, tp, TC_SETUP_CLSFLOWER, &cls_flower, |
467 | skip_sw, &f->flags, &f->in_hw_count, true); | 467 | skip_sw, &f->flags, &f->in_hw_count, true); |
468 | tc_cleanup_flow_action(&cls_flower.rule->action); | ||
468 | kfree(cls_flower.rule); | 469 | kfree(cls_flower.rule); |
469 | 470 | ||
470 | if (err) { | 471 | if (err) { |
@@ -1838,6 +1839,7 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb, | |||
1838 | TC_SETUP_CLSFLOWER, &cls_flower, | 1839 | TC_SETUP_CLSFLOWER, &cls_flower, |
1839 | cb_priv, &f->flags, | 1840 | cb_priv, &f->flags, |
1840 | &f->in_hw_count); | 1841 | &f->in_hw_count); |
1842 | tc_cleanup_flow_action(&cls_flower.rule->action); | ||
1841 | kfree(cls_flower.rule); | 1843 | kfree(cls_flower.rule); |
1842 | 1844 | ||
1843 | if (err) { | 1845 | if (err) { |