Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1158958a authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller
Browse files

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: default avatarVlad Buslov <vladbu@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 28c9eb90
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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 */
+45 −32
Original line number Diff line number Diff line
@@ -3282,24 +3282,47 @@ 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;
}
EXPORT_SYMBOL(tc_cleanup_flow_action);

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)) {