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

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
...@@ -222,6 +222,8 @@ struct xfrm_state { ...@@ -222,6 +222,8 @@ struct xfrm_state {
struct xfrm_mode *inner_mode_iaf; struct xfrm_mode *inner_mode_iaf;
struct xfrm_mode *outer_mode; struct xfrm_mode *outer_mode;
const struct xfrm_type_offload *type_offload;
/* Security context */ /* Security context */
struct xfrm_sec_ctx *security; struct xfrm_sec_ctx *security;
...@@ -319,7 +321,9 @@ struct xfrm_state_afinfo { ...@@ -319,7 +321,9 @@ struct xfrm_state_afinfo {
__be16 eth_proto; __be16 eth_proto;
struct module *owner; struct module *owner;
const struct xfrm_type *type_map[IPPROTO_MAX]; 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]; struct xfrm_mode *mode_map[XFRM_MODE_MAX];
int (*init_flags)(struct xfrm_state *x); int (*init_flags)(struct xfrm_state *x);
void (*init_tempsel)(struct xfrm_selector *sel, void (*init_tempsel)(struct xfrm_selector *sel,
const struct flowi *fl); const struct flowi *fl);
...@@ -380,6 +384,18 @@ struct xfrm_type { ...@@ -380,6 +384,18 @@ struct xfrm_type {
int xfrm_register_type(const struct xfrm_type *type, unsigned short family); int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
int xfrm_unregister_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 { struct xfrm_mode {
/* /*
* Remove encapsulation header. * Remove encapsulation header.
......
...@@ -251,6 +251,75 @@ static void xfrm_put_type(const struct xfrm_type *type) ...@@ -251,6 +251,75 @@ static void xfrm_put_type(const struct xfrm_type *type)
module_put(type->owner); 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); static DEFINE_SPINLOCK(xfrm_mode_lock);
int xfrm_register_mode(struct xfrm_mode *mode, int family) int xfrm_register_mode(struct xfrm_mode *mode, int family)
{ {
...@@ -365,6 +434,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) ...@@ -365,6 +434,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
xfrm_put_mode(x->inner_mode_iaf); xfrm_put_mode(x->inner_mode_iaf);
if (x->outer_mode) if (x->outer_mode)
xfrm_put_mode(x->outer_mode); xfrm_put_mode(x->outer_mode);
if (x->type_offload)
xfrm_put_type_offload(x->type_offload);
if (x->type) { if (x->type) {
x->type->destructor(x); x->type->destructor(x);
xfrm_put_type(x->type); xfrm_put_type(x->type);
...@@ -2077,6 +2148,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay) ...@@ -2077,6 +2148,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
if (x->type == NULL) if (x->type == NULL)
goto error; goto error;
x->type_offload = xfrm_get_type_offload(x->id.proto, family);
err = x->type->init_state(x); err = x->type->init_state(x);
if (err) if (err)
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment