diff options
author | Vlad Buslov <vladbu@mellanox.com> | 2019-09-13 11:28:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-09-16 03:18:02 -0400 |
commit | 1158958a218bb55d1c358200d7f82808d11bf929 (patch) | |
tree | 3fca9616bf020edceb8c13f528846231eec134bc | |
parent | 28c9eb9042a954d4e9fbec91484bddce280f1beb (diff) |
net: sched: extend flow_action_entry with destructor
Generalize flow_action_entry cleanup by extending the structure with
pointer to destructor function. Set the destructor in
tc_setup_flow_action(). Refactor tc_cleanup_flow_action() to call
entry->destructor() instead of using switch that dispatches by entry->id
and manually executes cleanup.
This refactoring is necessary for following patches in this series that
require destructor to use tc_action->ops callbacks that can't be easily
obtained in tc_cleanup_flow_action().
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/flow_offload.h | 6 | ||||
-rw-r--r-- | net/sched/cls_api.c | 77 |
2 files changed, 50 insertions, 33 deletions
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index fc881875f856..86c567f531f3 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h | |||
@@ -154,8 +154,12 @@ enum flow_action_mangle_base { | |||
154 | FLOW_ACT_MANGLE_HDR_TYPE_UDP, | 154 | FLOW_ACT_MANGLE_HDR_TYPE_UDP, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | typedef void (*action_destr)(void *priv); | ||
158 | |||
157 | struct flow_action_entry { | 159 | struct flow_action_entry { |
158 | enum flow_action_id id; | 160 | enum flow_action_id id; |
161 | action_destr destructor; | ||
162 | void *destructor_priv; | ||
159 | union { | 163 | union { |
160 | u32 chain_index; /* FLOW_ACTION_GOTO */ | 164 | u32 chain_index; /* FLOW_ACTION_GOTO */ |
161 | struct net_device *dev; /* FLOW_ACTION_REDIRECT */ | 165 | struct net_device *dev; /* FLOW_ACTION_REDIRECT */ |
@@ -170,7 +174,7 @@ struct flow_action_entry { | |||
170 | u32 mask; | 174 | u32 mask; |
171 | u32 val; | 175 | u32 val; |
172 | } mangle; | 176 | } mangle; |
173 | const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */ | 177 | struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */ |
174 | u32 csum_flags; /* FLOW_ACTION_CSUM */ | 178 | u32 csum_flags; /* FLOW_ACTION_CSUM */ |
175 | u32 mark; /* FLOW_ACTION_MARK */ | 179 | u32 mark; /* FLOW_ACTION_MARK */ |
176 | u16 ptype; /* FLOW_ACTION_PTYPE */ | 180 | u16 ptype; /* FLOW_ACTION_PTYPE */ |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 05c4fe1c3ca2..c668195379bd 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -3282,25 +3282,48 @@ void tc_cleanup_flow_action(struct flow_action *flow_action) | |||
3282 | struct flow_action_entry *entry; | 3282 | struct flow_action_entry *entry; |
3283 | int i; | 3283 | int i; |
3284 | 3284 | ||
3285 | flow_action_for_each(i, entry, flow_action) { | 3285 | flow_action_for_each(i, entry, flow_action) |
3286 | switch (entry->id) { | 3286 | if (entry->destructor) |
3287 | case FLOW_ACTION_REDIRECT: | 3287 | entry->destructor(entry->destructor_priv); |
3288 | case FLOW_ACTION_MIRRED: | ||
3289 | case FLOW_ACTION_REDIRECT_INGRESS: | ||
3290 | case FLOW_ACTION_MIRRED_INGRESS: | ||
3291 | if (entry->dev) | ||
3292 | dev_put(entry->dev); | ||
3293 | break; | ||
3294 | case FLOW_ACTION_TUNNEL_ENCAP: | ||
3295 | kfree(entry->tunnel); | ||
3296 | break; | ||
3297 | default: | ||
3298 | break; | ||
3299 | } | ||
3300 | } | ||
3301 | } | 3288 | } |
3302 | EXPORT_SYMBOL(tc_cleanup_flow_action); | 3289 | EXPORT_SYMBOL(tc_cleanup_flow_action); |
3303 | 3290 | ||
3291 | static void tcf_mirred_put_dev(void *priv) | ||
3292 | { | ||
3293 | struct net_device *dev = priv; | ||
3294 | |||
3295 | dev_put(dev); | ||
3296 | } | ||
3297 | |||
3298 | static void tcf_mirred_get_dev(struct flow_action_entry *entry, | ||
3299 | const struct tc_action *act) | ||
3300 | { | ||
3301 | entry->dev = tcf_mirred_dev(act); | ||
3302 | if (!entry->dev) | ||
3303 | return; | ||
3304 | dev_hold(entry->dev); | ||
3305 | entry->destructor = tcf_mirred_put_dev; | ||
3306 | entry->destructor_priv = entry->dev; | ||
3307 | } | ||
3308 | |||
3309 | static void tcf_tunnel_encap_put_tunnel(void *priv) | ||
3310 | { | ||
3311 | struct ip_tunnel_info *tunnel = priv; | ||
3312 | |||
3313 | kfree(tunnel); | ||
3314 | } | ||
3315 | |||
3316 | static int tcf_tunnel_encap_get_tunnel(struct flow_action_entry *entry, | ||
3317 | const struct tc_action *act) | ||
3318 | { | ||
3319 | entry->tunnel = tcf_tunnel_info_copy(act); | ||
3320 | if (!entry->tunnel) | ||
3321 | return -ENOMEM; | ||
3322 | entry->destructor = tcf_tunnel_encap_put_tunnel; | ||
3323 | entry->destructor_priv = entry->tunnel; | ||
3324 | return 0; | ||
3325 | } | ||
3326 | |||
3304 | int tc_setup_flow_action(struct flow_action *flow_action, | 3327 | int tc_setup_flow_action(struct flow_action *flow_action, |
3305 | const struct tcf_exts *exts, bool rtnl_held) | 3328 | const struct tcf_exts *exts, bool rtnl_held) |
3306 | { | 3329 | { |
@@ -3329,24 +3352,16 @@ int tc_setup_flow_action(struct flow_action *flow_action, | |||
3329 | entry->chain_index = tcf_gact_goto_chain_index(act); | 3352 | entry->chain_index = tcf_gact_goto_chain_index(act); |
3330 | } else if (is_tcf_mirred_egress_redirect(act)) { | 3353 | } else if (is_tcf_mirred_egress_redirect(act)) { |
3331 | entry->id = FLOW_ACTION_REDIRECT; | 3354 | entry->id = FLOW_ACTION_REDIRECT; |
3332 | entry->dev = tcf_mirred_dev(act); | 3355 | tcf_mirred_get_dev(entry, act); |
3333 | if (entry->dev) | ||
3334 | dev_hold(entry->dev); | ||
3335 | } else if (is_tcf_mirred_egress_mirror(act)) { | 3356 | } else if (is_tcf_mirred_egress_mirror(act)) { |
3336 | entry->id = FLOW_ACTION_MIRRED; | 3357 | entry->id = FLOW_ACTION_MIRRED; |
3337 | entry->dev = tcf_mirred_dev(act); | 3358 | tcf_mirred_get_dev(entry, act); |
3338 | if (entry->dev) | ||
3339 | dev_hold(entry->dev); | ||
3340 | } else if (is_tcf_mirred_ingress_redirect(act)) { | 3359 | } else if (is_tcf_mirred_ingress_redirect(act)) { |
3341 | entry->id = FLOW_ACTION_REDIRECT_INGRESS; | 3360 | entry->id = FLOW_ACTION_REDIRECT_INGRESS; |
3342 | entry->dev = tcf_mirred_dev(act); | 3361 | tcf_mirred_get_dev(entry, act); |
3343 | if (entry->dev) | ||
3344 | dev_hold(entry->dev); | ||
3345 | } else if (is_tcf_mirred_ingress_mirror(act)) { | 3362 | } else if (is_tcf_mirred_ingress_mirror(act)) { |
3346 | entry->id = FLOW_ACTION_MIRRED_INGRESS; | 3363 | entry->id = FLOW_ACTION_MIRRED_INGRESS; |
3347 | entry->dev = tcf_mirred_dev(act); | 3364 | tcf_mirred_get_dev(entry, act); |
3348 | if (entry->dev) | ||
3349 | dev_hold(entry->dev); | ||
3350 | } else if (is_tcf_vlan(act)) { | 3365 | } else if (is_tcf_vlan(act)) { |
3351 | switch (tcf_vlan_action(act)) { | 3366 | switch (tcf_vlan_action(act)) { |
3352 | case TCA_VLAN_ACT_PUSH: | 3367 | case TCA_VLAN_ACT_PUSH: |
@@ -3370,11 +3385,9 @@ int tc_setup_flow_action(struct flow_action *flow_action, | |||
3370 | } | 3385 | } |
3371 | } else if (is_tcf_tunnel_set(act)) { | 3386 | } else if (is_tcf_tunnel_set(act)) { |
3372 | entry->id = FLOW_ACTION_TUNNEL_ENCAP; | 3387 | entry->id = FLOW_ACTION_TUNNEL_ENCAP; |
3373 | entry->tunnel = tcf_tunnel_info_copy(act); | 3388 | err = tcf_tunnel_encap_get_tunnel(entry, act); |
3374 | if (!entry->tunnel) { | 3389 | if (err) |
3375 | err = -ENOMEM; | ||
3376 | goto err_out; | 3390 | goto err_out; |
3377 | } | ||
3378 | } else if (is_tcf_tunnel_release(act)) { | 3391 | } else if (is_tcf_tunnel_release(act)) { |
3379 | entry->id = FLOW_ACTION_TUNNEL_DECAP; | 3392 | entry->id = FLOW_ACTION_TUNNEL_DECAP; |
3380 | } else if (is_tcf_pedit(act)) { | 3393 | } else if (is_tcf_pedit(act)) { |