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,
|
FLOW_ACT_MANGLE_HDR_TYPE_UDP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*action_destr)(void *priv);
|
||||||
|
|
||||||
struct flow_action_entry {
|
struct flow_action_entry {
|
||||||
enum flow_action_id id;
|
enum flow_action_id id;
|
||||||
|
action_destr destructor;
|
||||||
|
void *destructor_priv;
|
||||||
union {
|
union {
|
||||||
u32 chain_index; /* FLOW_ACTION_GOTO */
|
u32 chain_index; /* FLOW_ACTION_GOTO */
|
||||||
struct net_device *dev; /* FLOW_ACTION_REDIRECT */
|
struct net_device *dev; /* FLOW_ACTION_REDIRECT */
|
||||||
|
@ -170,7 +174,7 @@ struct flow_action_entry {
|
||||||
u32 mask;
|
u32 mask;
|
||||||
u32 val;
|
u32 val;
|
||||||
} mangle;
|
} 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 csum_flags; /* FLOW_ACTION_CSUM */
|
||||||
u32 mark; /* FLOW_ACTION_MARK */
|
u32 mark; /* FLOW_ACTION_MARK */
|
||||||
u16 ptype; /* FLOW_ACTION_PTYPE */
|
u16 ptype; /* FLOW_ACTION_PTYPE */
|
||||||
|
|
|
@ -3282,25 +3282,48 @@ void tc_cleanup_flow_action(struct flow_action *flow_action)
|
||||||
struct flow_action_entry *entry;
|
struct flow_action_entry *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
flow_action_for_each(i, entry, flow_action) {
|
flow_action_for_each(i, entry, flow_action)
|
||||||
switch (entry->id) {
|
if (entry->destructor)
|
||||||
case FLOW_ACTION_REDIRECT:
|
entry->destructor(entry->destructor_priv);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tc_cleanup_flow_action);
|
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,
|
int tc_setup_flow_action(struct flow_action *flow_action,
|
||||||
const struct tcf_exts *exts, bool rtnl_held)
|
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);
|
entry->chain_index = tcf_gact_goto_chain_index(act);
|
||||||
} else if (is_tcf_mirred_egress_redirect(act)) {
|
} else if (is_tcf_mirred_egress_redirect(act)) {
|
||||||
entry->id = FLOW_ACTION_REDIRECT;
|
entry->id = FLOW_ACTION_REDIRECT;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
tcf_mirred_get_dev(entry, act);
|
||||||
if (entry->dev)
|
|
||||||
dev_hold(entry->dev);
|
|
||||||
} else if (is_tcf_mirred_egress_mirror(act)) {
|
} else if (is_tcf_mirred_egress_mirror(act)) {
|
||||||
entry->id = FLOW_ACTION_MIRRED;
|
entry->id = FLOW_ACTION_MIRRED;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
tcf_mirred_get_dev(entry, act);
|
||||||
if (entry->dev)
|
|
||||||
dev_hold(entry->dev);
|
|
||||||
} else if (is_tcf_mirred_ingress_redirect(act)) {
|
} else if (is_tcf_mirred_ingress_redirect(act)) {
|
||||||
entry->id = FLOW_ACTION_REDIRECT_INGRESS;
|
entry->id = FLOW_ACTION_REDIRECT_INGRESS;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
tcf_mirred_get_dev(entry, act);
|
||||||
if (entry->dev)
|
|
||||||
dev_hold(entry->dev);
|
|
||||||
} else if (is_tcf_mirred_ingress_mirror(act)) {
|
} else if (is_tcf_mirred_ingress_mirror(act)) {
|
||||||
entry->id = FLOW_ACTION_MIRRED_INGRESS;
|
entry->id = FLOW_ACTION_MIRRED_INGRESS;
|
||||||
entry->dev = tcf_mirred_dev(act);
|
tcf_mirred_get_dev(entry, act);
|
||||||
if (entry->dev)
|
|
||||||
dev_hold(entry->dev);
|
|
||||||
} else if (is_tcf_vlan(act)) {
|
} else if (is_tcf_vlan(act)) {
|
||||||
switch (tcf_vlan_action(act)) {
|
switch (tcf_vlan_action(act)) {
|
||||||
case TCA_VLAN_ACT_PUSH:
|
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)) {
|
} else if (is_tcf_tunnel_set(act)) {
|
||||||
entry->id = FLOW_ACTION_TUNNEL_ENCAP;
|
entry->id = FLOW_ACTION_TUNNEL_ENCAP;
|
||||||
entry->tunnel = tcf_tunnel_info_copy(act);
|
err = tcf_tunnel_encap_get_tunnel(entry, act);
|
||||||
if (!entry->tunnel) {
|
if (err)
|
||||||
err = -ENOMEM;
|
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
|
||||||
} else if (is_tcf_tunnel_release(act)) {
|
} else if (is_tcf_tunnel_release(act)) {
|
||||||
entry->id = FLOW_ACTION_TUNNEL_DECAP;
|
entry->id = FLOW_ACTION_TUNNEL_DECAP;
|
||||||
} else if (is_tcf_pedit(act)) {
|
} else if (is_tcf_pedit(act)) {
|
||||||
|
|
Loading…
Reference in New Issue