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

Commit 1104d9ba authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

lwtunnel: Add destroy state operation



Users of lwt tunnels may set up some secondary state in build_state
function. Add a corresponding destroy_state function to allow users to
clean up state. This destroy state function is called from lwstate_free.
Also, we now free lwstate using kfree_rcu so user can assume structure
is not freed before rcu.

Acked-by: default avatarRoopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: default avatarTom Herbert <tom@herbertland.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 02dc7658
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct lwtunnel_state {
	int		(*orig_input)(struct sk_buff *);
	int             len;
	__u16		headroom;
	struct		rcu_head rcu;
	__u8            data[0];
};

@@ -36,6 +37,7 @@ struct lwtunnel_encap_ops {
	int (*build_state)(struct net_device *dev, struct nlattr *encap,
			   unsigned int family, const void *cfg,
			   struct lwtunnel_state **ts);
	void (*destroy_state)(struct lwtunnel_state *lws);
	int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
	int (*input)(struct sk_buff *skb);
	int (*fill_encap)(struct sk_buff *skb,
@@ -46,10 +48,7 @@ struct lwtunnel_encap_ops {
};

#ifdef CONFIG_LWTUNNEL
static inline void lwtstate_free(struct lwtunnel_state *lws)
{
	kfree(lws);
}
void lwtstate_free(struct lwtunnel_state *lws);

static inline struct lwtunnel_state *
lwtstate_get(struct lwtunnel_state *lws)
+13 −0
Original line number Diff line number Diff line
@@ -130,6 +130,19 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
}
EXPORT_SYMBOL(lwtunnel_build_state);

void lwtstate_free(struct lwtunnel_state *lws)
{
	const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];

	if (ops->destroy_state) {
		ops->destroy_state(lws);
		kfree_rcu(lws, rcu);
	} else {
		kfree(lws);
	}
}
EXPORT_SYMBOL(lwtstate_free);

int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
{
	const struct lwtunnel_encap_ops *ops;