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

Commit 9d389d7f authored by Steffen Klassert's avatar Steffen Klassert
Browse files

xfrm: Add a xfrm type offload.



We add a struct  xfrm_type_offload so that we have the offloaded
codepath separated to the non offloaded codepath. With this the
non offloade and the offloaded codepath can coexist.

Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent c7ef8f0c
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -222,6 +222,8 @@ struct xfrm_state {
	struct xfrm_mode	*inner_mode_iaf;
	struct xfrm_mode	*outer_mode;

	const struct xfrm_type_offload	*type_offload;

	/* Security context */
	struct xfrm_sec_ctx	*security;

@@ -319,7 +321,9 @@ struct xfrm_state_afinfo {
	__be16				eth_proto;
	struct module			*owner;
	const struct xfrm_type		*type_map[IPPROTO_MAX];
	const struct xfrm_type_offload	*type_offload_map[IPPROTO_MAX];
	struct xfrm_mode		*mode_map[XFRM_MODE_MAX];

	int			(*init_flags)(struct xfrm_state *x);
	void			(*init_tempsel)(struct xfrm_selector *sel,
						const struct flowi *fl);
@@ -380,6 +384,18 @@ struct xfrm_type {
int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);

struct xfrm_type_offload {
	char		*description;
	struct module	*owner;
	u8		proto;
	void		(*encap)(struct xfrm_state *, struct sk_buff *pskb);
	int		(*input_tail)(struct xfrm_state *x, struct sk_buff *skb);
	int		(*xmit)(struct xfrm_state *, struct sk_buff *pskb, netdev_features_t features);
};

int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);

struct xfrm_mode {
	/*
	 * Remove encapsulation header.
+73 −0
Original line number Diff line number Diff line
@@ -251,6 +251,75 @@ static void xfrm_put_type(const struct xfrm_type *type)
	module_put(type->owner);
}

static DEFINE_SPINLOCK(xfrm_type_offload_lock);
int xfrm_register_type_offload(const struct xfrm_type_offload *type,
			       unsigned short family)
{
	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
	const struct xfrm_type_offload **typemap;
	int err = 0;

	if (unlikely(afinfo == NULL))
		return -EAFNOSUPPORT;
	typemap = afinfo->type_offload_map;
	spin_lock_bh(&xfrm_type_offload_lock);

	if (likely(typemap[type->proto] == NULL))
		typemap[type->proto] = type;
	else
		err = -EEXIST;
	spin_unlock_bh(&xfrm_type_offload_lock);
	rcu_read_unlock();
	return err;
}
EXPORT_SYMBOL(xfrm_register_type_offload);

int xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
				 unsigned short family)
{
	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
	const struct xfrm_type_offload **typemap;
	int err = 0;

	if (unlikely(afinfo == NULL))
		return -EAFNOSUPPORT;
	typemap = afinfo->type_offload_map;
	spin_lock_bh(&xfrm_type_offload_lock);

	if (unlikely(typemap[type->proto] != type))
		err = -ENOENT;
	else
		typemap[type->proto] = NULL;
	spin_unlock_bh(&xfrm_type_offload_lock);
	rcu_read_unlock();
	return err;
}
EXPORT_SYMBOL(xfrm_unregister_type_offload);

static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned short family)
{
	struct xfrm_state_afinfo *afinfo;
	const struct xfrm_type_offload **typemap;
	const struct xfrm_type_offload *type;

	afinfo = xfrm_state_get_afinfo(family);
	if (unlikely(afinfo == NULL))
		return NULL;
	typemap = afinfo->type_offload_map;

	type = typemap[proto];
	if ((type && !try_module_get(type->owner)))
		type = NULL;

	rcu_read_unlock();
	return type;
}

static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
{
	module_put(type->owner);
}

static DEFINE_SPINLOCK(xfrm_mode_lock);
int xfrm_register_mode(struct xfrm_mode *mode, int family)
{
@@ -365,6 +434,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
		xfrm_put_mode(x->inner_mode_iaf);
	if (x->outer_mode)
		xfrm_put_mode(x->outer_mode);
	if (x->type_offload)
		xfrm_put_type_offload(x->type_offload);
	if (x->type) {
		x->type->destructor(x);
		xfrm_put_type(x->type);
@@ -2077,6 +2148,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
	if (x->type == NULL)
		goto error;

	x->type_offload = xfrm_get_type_offload(x->id.proto, family);

	err = x->type->init_state(x);
	if (err)
		goto error;