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>
This commit is contained in:
parent
28c9eb9042
commit
1158958a21
@ -154,8 +154,12 @@ enum flow_action_mangle_base {
|
||||
FLOW_ACT_MANGLE_HDR_TYPE_UDP,
|
||||
};
|
||||
|
||||
typedef void (*action_destr)(void *priv);
|
||||
|
||||
struct flow_action_entry {
|
||||
enum flow_action_id id;
|
||||
action_destr destructor;
|
||||
void *destructor_priv;
|
||||
union {
|
||||
u32 chain_index; /* FLOW_ACTION_GOTO */
|
||||
struct net_device *dev; /* FLOW_ACTION_REDIRECT */
|
||||
@ -170,7 +174,7 @@ struct flow_action_entry {
|
||||
u32 mask;
|
||||
u32 val;
|
||||
} mangle;
|
||||
const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */
|
||||
struct ip_tunnel_info *tunnel; /* FLOW_ACTION_TUNNEL_ENCAP */
|
||||
u32 csum_flags; /* FLOW_ACTION_CSUM */
|
||||
u32 mark; /* FLOW_ACTION_MARK */
|
||||
u16 ptype; /* FLOW_ACTION_PTYPE */
|
||||
|
@ -3282,25 +3282,48 @@ 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;
|
||||
case FLOW_ACTION_TUNNEL_ENCAP:
|
||||
kfree(entry->tunnel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
flow_action_for_each(i, entry, flow_action)
|
||||
if (entry->destructor)
|
||||
entry->destructor(entry->destructor_priv);
|
||||
}
|
||||
EXPORT_SYMBOL(tc_cleanup_flow_action);
|
||||
|
||||
static void tcf_mirred_put_dev(void *priv)
|
||||
{
|
||||
struct net_device *dev = priv;
|
||||
|
||||
dev_put(dev);
|
||||
}
|
||||
|
||||
static void tcf_mirred_get_dev(struct flow_action_entry *entry,
|
||||
const struct tc_action *act)
|
||||
{
|
||||
entry->dev = tcf_mirred_dev(act);
|
||||
if (!entry->dev)
|
||||
return;
|
||||
dev_hold(entry->dev);
|
||||
entry->destructor = tcf_mirred_put_dev;
|
||||
entry->destructor_priv = entry->dev;
|
||||
}
|
||||
|
||||
static void tcf_tunnel_encap_put_tunnel(void *priv)
|
||||
{
|
||||
struct ip_tunnel_info *tunnel = priv;
|
||||
|
||||
kfree(tunnel);
|
||||
}
|
||||
|
||||
static int tcf_tunnel_encap_get_tunnel(struct flow_action_entry *entry,
|
||||
const struct tc_action *act)
|
||||
{
|
||||
entry->tunnel = tcf_tunnel_info_copy(act);
|
||||
if (!entry->tunnel)
|
||||
return -ENOMEM;
|
||||
entry->destructor = tcf_tunnel_encap_put_tunnel;
|
||||
entry->destructor_priv = entry->tunnel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tc_setup_flow_action(struct flow_action *flow_action,
|
||||
const struct tcf_exts *exts, bool rtnl_held)
|
||||
{
|
||||
@ -3329,24 +3352,16 @@ int tc_setup_flow_action(struct flow_action *flow_action,
|
||||
entry->chain_index = tcf_gact_goto_chain_index(act);
|
||||
} 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);
|
||||
tcf_mirred_get_dev(entry, act);
|
||||
} 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);
|
||||
tcf_mirred_get_dev(entry, act);
|
||||
} 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);
|
||||
tcf_mirred_get_dev(entry, act);
|
||||
} 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);
|
||||
tcf_mirred_get_dev(entry, act);
|
||||
} else if (is_tcf_vlan(act)) {
|
||||
switch (tcf_vlan_action(act)) {
|
||||
case TCA_VLAN_ACT_PUSH:
|
||||
@ -3370,11 +3385,9 @@ int tc_setup_flow_action(struct flow_action *flow_action,
|
||||
}
|
||||
} else if (is_tcf_tunnel_set(act)) {
|
||||
entry->id = FLOW_ACTION_TUNNEL_ENCAP;
|
||||
entry->tunnel = tcf_tunnel_info_copy(act);
|
||||
if (!entry->tunnel) {
|
||||
err = -ENOMEM;
|
||||
err = tcf_tunnel_encap_get_tunnel(entry, act);
|
||||
if (err)
|
||||
goto err_out;
|
||||
}
|
||||
} else if (is_tcf_tunnel_release(act)) {
|
||||
entry->id = FLOW_ACTION_TUNNEL_DECAP;
|
||||
} else if (is_tcf_pedit(act)) {
|
||||
|
Loading…
Reference in New Issue
Block a user