|
@@ -296,12 +296,14 @@ int xfrm_unregister_type_offload(const struct xfrm_type_offload *type,
|
|
|
}
|
|
|
EXPORT_SYMBOL(xfrm_unregister_type_offload);
|
|
|
|
|
|
-static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned short family)
|
|
|
+static const struct xfrm_type_offload *
|
|
|
+xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
|
|
|
{
|
|
|
struct xfrm_state_afinfo *afinfo;
|
|
|
const struct xfrm_type_offload **typemap;
|
|
|
const struct xfrm_type_offload *type;
|
|
|
|
|
|
+retry:
|
|
|
afinfo = xfrm_state_get_afinfo(family);
|
|
|
if (unlikely(afinfo == NULL))
|
|
|
return NULL;
|
|
@@ -311,6 +313,12 @@ static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned
|
|
|
if ((type && !try_module_get(type->owner)))
|
|
|
type = NULL;
|
|
|
|
|
|
+ if (!type && try_load) {
|
|
|
+ request_module("xfrm-offload-%d-%d", family, proto);
|
|
|
+ try_load = 0;
|
|
|
+ goto retry;
|
|
|
+ }
|
|
|
+
|
|
|
rcu_read_unlock();
|
|
|
return type;
|
|
|
}
|
|
@@ -2165,7 +2173,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|
|
return mtu - x->props.header_len;
|
|
|
}
|
|
|
|
|
|
-int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
|
|
|
+int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
|
|
{
|
|
|
struct xfrm_state_afinfo *afinfo;
|
|
|
struct xfrm_mode *inner_mode;
|
|
@@ -2230,7 +2238,7 @@ 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);
|
|
|
+ x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload);
|
|
|
|
|
|
err = x->type->init_state(x);
|
|
|
if (err)
|
|
@@ -2258,7 +2266,7 @@ EXPORT_SYMBOL(__xfrm_init_state);
|
|
|
|
|
|
int xfrm_init_state(struct xfrm_state *x)
|
|
|
{
|
|
|
- return __xfrm_init_state(x, true);
|
|
|
+ return __xfrm_init_state(x, true, false);
|
|
|
}
|
|
|
|
|
|
EXPORT_SYMBOL(xfrm_init_state);
|