Skip to content

Commit 9d389d7

Browse files
committed
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 <[email protected]>
1 parent c7ef8f0 commit 9d389d7

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

include/net/xfrm.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ struct xfrm_state {
222222
struct xfrm_mode *inner_mode_iaf;
223223
struct xfrm_mode *outer_mode;
224224

225+
const struct xfrm_type_offload *type_offload;
226+
225227
/* Security context */
226228
struct xfrm_sec_ctx *security;
227229

@@ -314,12 +316,14 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
314316
int __xfrm_state_delete(struct xfrm_state *x);
315317

316318
struct xfrm_state_afinfo {
317-
unsigned int family;
318-
unsigned int proto;
319-
__be16 eth_proto;
320-
struct module *owner;
321-
const struct xfrm_type *type_map[IPPROTO_MAX];
322-
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
319+
unsigned int family;
320+
unsigned int proto;
321+
__be16 eth_proto;
322+
struct module *owner;
323+
const struct xfrm_type *type_map[IPPROTO_MAX];
324+
const struct xfrm_type_offload *type_offload_map[IPPROTO_MAX];
325+
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
326+
323327
int (*init_flags)(struct xfrm_state *x);
324328
void (*init_tempsel)(struct xfrm_selector *sel,
325329
const struct flowi *fl);
@@ -380,6 +384,18 @@ struct xfrm_type {
380384
int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
381385
int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
382386

387+
struct xfrm_type_offload {
388+
char *description;
389+
struct module *owner;
390+
u8 proto;
391+
void (*encap)(struct xfrm_state *, struct sk_buff *pskb);
392+
int (*input_tail)(struct xfrm_state *x, struct sk_buff *skb);
393+
int (*xmit)(struct xfrm_state *, struct sk_buff *pskb, netdev_features_t features);
394+
};
395+
396+
int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
397+
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
398+
383399
struct xfrm_mode {
384400
/*
385401
* Remove encapsulation header.

net/xfrm/xfrm_state.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,75 @@ static void xfrm_put_type(const struct xfrm_type *type)
251251
module_put(type->owner);
252252
}
253253

254+
static DEFINE_SPINLOCK(xfrm_type_offload_lock);
255+
int xfrm_register_type_offload(const struct xfrm_type_offload *type,
256+
unsigned short family)
257+
{
258+
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
259+
const struct xfrm_type_offload **typemap;
260+
int err = 0;
261+
262+
if (unlikely(afinfo == NULL))
263+
return -EAFNOSUPPORT;
264+
typemap = afinfo->type_offload_map;
265+
spin_lock_bh(&xfrm_type_offload_lock);
266+
267+
if (likely(typemap[type->proto] == NULL))
268+
typemap[type->proto] = type;
269+
else
270+
err = -EEXIST;
271+
spin_unlock_bh(&xfrm_type_offload_lock);
272+
rcu_read_unlock();
273+
return err;
274+
}
275+
EXPORT_SYMBOL(xfrm_register_type_offload);
276+
277+
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
278+
unsigned short family)
279+
{
280+
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
281+
const struct xfrm_type_offload **typemap;
282+
int err = 0;
283+
284+
if (unlikely(afinfo == NULL))
285+
return -EAFNOSUPPORT;
286+
typemap = afinfo->type_offload_map;
287+
spin_lock_bh(&xfrm_type_offload_lock);
288+
289+
if (unlikely(typemap[type->proto] != type))
290+
err = -ENOENT;
291+
else
292+
typemap[type->proto] = NULL;
293+
spin_unlock_bh(&xfrm_type_offload_lock);
294+
rcu_read_unlock();
295+
return err;
296+
}
297+
EXPORT_SYMBOL(xfrm_unregister_type_offload);
298+
299+
static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned short family)
300+
{
301+
struct xfrm_state_afinfo *afinfo;
302+
const struct xfrm_type_offload **typemap;
303+
const struct xfrm_type_offload *type;
304+
305+
afinfo = xfrm_state_get_afinfo(family);
306+
if (unlikely(afinfo == NULL))
307+
return NULL;
308+
typemap = afinfo->type_offload_map;
309+
310+
type = typemap[proto];
311+
if ((type && !try_module_get(type->owner)))
312+
type = NULL;
313+
314+
rcu_read_unlock();
315+
return type;
316+
}
317+
318+
static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
319+
{
320+
module_put(type->owner);
321+
}
322+
254323
static DEFINE_SPINLOCK(xfrm_mode_lock);
255324
int xfrm_register_mode(struct xfrm_mode *mode, int family)
256325
{
@@ -365,6 +434,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
365434
xfrm_put_mode(x->inner_mode_iaf);
366435
if (x->outer_mode)
367436
xfrm_put_mode(x->outer_mode);
437+
if (x->type_offload)
438+
xfrm_put_type_offload(x->type_offload);
368439
if (x->type) {
369440
x->type->destructor(x);
370441
xfrm_put_type(x->type);
@@ -2077,6 +2148,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
20772148
if (x->type == NULL)
20782149
goto error;
20792150

2151+
x->type_offload = xfrm_get_type_offload(x->id.proto, family);
2152+
20802153
err = x->type->init_state(x);
20812154
if (err)
20822155
goto error;

0 commit comments

Comments
 (0)