@@ -251,6 +251,75 @@ static void xfrm_put_type(const struct xfrm_type *type)
251
251
module_put (type -> owner );
252
252
}
253
253
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
+
254
323
static DEFINE_SPINLOCK (xfrm_mode_lock );
255
324
int xfrm_register_mode (struct xfrm_mode * mode , int family )
256
325
{
@@ -365,6 +434,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
365
434
xfrm_put_mode (x -> inner_mode_iaf );
366
435
if (x -> outer_mode )
367
436
xfrm_put_mode (x -> outer_mode );
437
+ if (x -> type_offload )
438
+ xfrm_put_type_offload (x -> type_offload );
368
439
if (x -> type ) {
369
440
x -> type -> destructor (x );
370
441
xfrm_put_type (x -> type );
@@ -2077,6 +2148,8 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
2077
2148
if (x -> type == NULL )
2078
2149
goto error ;
2079
2150
2151
+ x -> type_offload = xfrm_get_type_offload (x -> id .proto , family );
2152
+
2080
2153
err = x -> type -> init_state (x );
2081
2154
if (err )
2082
2155
goto error ;
0 commit comments