mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
parent
c7ef8f0c02
commit
9d389d7f84
2 changed files with 95 additions and 6 deletions
|
@ -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;
|
||||||
|
|
||||||
|
@ -314,12 +316,14 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
|
||||||
int __xfrm_state_delete(struct xfrm_state *x);
|
int __xfrm_state_delete(struct xfrm_state *x);
|
||||||
|
|
||||||
struct xfrm_state_afinfo {
|
struct xfrm_state_afinfo {
|
||||||
unsigned int family;
|
unsigned int family;
|
||||||
unsigned int proto;
|
unsigned int proto;
|
||||||
__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];
|
||||||
struct xfrm_mode *mode_map[XFRM_MODE_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);
|
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 {
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue