mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 15:41:52 +02:00
Merge branch 'Support-PMTU-in-tunnel-mode-for-packet-offload'
Leon Romanovsky says: ==================== This series refactors the xdo_dev_offload_ok() to be global place for drivers to check if their offload can perform encryption for xmit packets. Such common place gives us an option to check MTU and PMTU at one place. ==================== Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
commit
9d381c7708
|
|
@ -126,7 +126,8 @@ been setup for offload, it first calls into xdo_dev_offload_ok() with
|
|||
the skb and the intended offload state to ask the driver if the offload
|
||||
will serviceable. This can check the packet information to be sure the
|
||||
offload can be supported (e.g. IPv4 or IPv6, no IPv4 options, etc) and
|
||||
return true of false to signify its support.
|
||||
return true or false to signify its support. In case driver doesn't implement
|
||||
this callback, the stack provides reasonable defaults.
|
||||
|
||||
Crypto offload mode:
|
||||
When ready to send, the driver needs to inspect the Tx packet for the
|
||||
|
|
|
|||
|
|
@ -673,22 +673,16 @@ static void bond_ipsec_free_sa(struct xfrm_state *xs)
|
|||
static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
|
||||
{
|
||||
struct net_device *real_dev;
|
||||
bool ok = false;
|
||||
|
||||
rcu_read_lock();
|
||||
real_dev = bond_ipsec_dev(xs);
|
||||
if (!real_dev)
|
||||
goto out;
|
||||
if (!real_dev || netif_is_bond_master(real_dev)) {
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!real_dev->xfrmdev_ops ||
|
||||
!real_dev->xfrmdev_ops->xdo_dev_offload_ok ||
|
||||
netif_is_bond_master(real_dev))
|
||||
goto out;
|
||||
|
||||
ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6538,26 +6538,6 @@ static void cxgb4_xfrm_free_state(struct xfrm_state *x)
|
|||
mutex_unlock(&uld_mutex);
|
||||
}
|
||||
|
||||
static bool cxgb4_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
||||
{
|
||||
struct adapter *adap = netdev2adap(x->xso.dev);
|
||||
bool ret = false;
|
||||
|
||||
if (!mutex_trylock(&uld_mutex)) {
|
||||
dev_dbg(adap->pdev_dev,
|
||||
"crypto uld critical resource is under use\n");
|
||||
return ret;
|
||||
}
|
||||
if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
|
||||
goto out_unlock;
|
||||
|
||||
ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_offload_ok(skb, x);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&uld_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cxgb4_advance_esn_state(struct xfrm_state *x)
|
||||
{
|
||||
struct adapter *adap = netdev2adap(x->xso.dev);
|
||||
|
|
@ -6583,7 +6563,6 @@ static const struct xfrmdev_ops cxgb4_xfrmdev_ops = {
|
|||
.xdo_dev_state_add = cxgb4_xfrm_add_state,
|
||||
.xdo_dev_state_delete = cxgb4_xfrm_del_state,
|
||||
.xdo_dev_state_free = cxgb4_xfrm_free_state,
|
||||
.xdo_dev_offload_ok = cxgb4_ipsec_offload_ok,
|
||||
.xdo_dev_state_advance_esn = cxgb4_advance_esn_state,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@
|
|||
static LIST_HEAD(uld_ctx_list);
|
||||
static DEFINE_MUTEX(dev_mutex);
|
||||
|
||||
static bool ch_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
|
||||
static int ch_ipsec_uld_state_change(void *handle, enum cxgb4_state new_state);
|
||||
static int ch_ipsec_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
static void *ch_ipsec_uld_add(const struct cxgb4_lld_info *infop);
|
||||
|
|
@ -85,7 +84,6 @@ static const struct xfrmdev_ops ch_ipsec_xfrmdev_ops = {
|
|||
.xdo_dev_state_add = ch_ipsec_xfrm_add_state,
|
||||
.xdo_dev_state_delete = ch_ipsec_xfrm_del_state,
|
||||
.xdo_dev_state_free = ch_ipsec_xfrm_free_state,
|
||||
.xdo_dev_offload_ok = ch_ipsec_offload_ok,
|
||||
.xdo_dev_state_advance_esn = ch_ipsec_advance_esn_state,
|
||||
};
|
||||
|
||||
|
|
@ -323,20 +321,6 @@ static void ch_ipsec_xfrm_free_state(struct xfrm_state *x)
|
|||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static bool ch_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
||||
{
|
||||
if (x->props.family == AF_INET) {
|
||||
/* Offload with IP options is not supported yet */
|
||||
if (ip_hdr(skb)->ihl > 5)
|
||||
return false;
|
||||
} else {
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ch_ipsec_advance_esn_state(struct xfrm_state *x)
|
||||
{
|
||||
/* do nothing */
|
||||
|
|
|
|||
|
|
@ -817,30 +817,9 @@ static void ixgbe_ipsec_del_sa(struct xfrm_state *xs)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbe_ipsec_offload_ok - can this packet use the xfrm hw offload
|
||||
* @skb: current data packet
|
||||
* @xs: pointer to transformer state struct
|
||||
**/
|
||||
static bool ixgbe_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
|
||||
{
|
||||
if (xs->props.family == AF_INET) {
|
||||
/* Offload with IPv4 options is not supported yet */
|
||||
if (ip_hdr(skb)->ihl != 5)
|
||||
return false;
|
||||
} else {
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
|
||||
.xdo_dev_state_add = ixgbe_ipsec_add_sa,
|
||||
.xdo_dev_state_delete = ixgbe_ipsec_del_sa,
|
||||
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -428,30 +428,9 @@ static void ixgbevf_ipsec_del_sa(struct xfrm_state *xs)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ixgbevf_ipsec_offload_ok - can this packet use the xfrm hw offload
|
||||
* @skb: current data packet
|
||||
* @xs: pointer to transformer state struct
|
||||
**/
|
||||
static bool ixgbevf_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
|
||||
{
|
||||
if (xs->props.family == AF_INET) {
|
||||
/* Offload with IPv4 options is not supported yet */
|
||||
if (ip_hdr(skb)->ihl != 5)
|
||||
return false;
|
||||
} else {
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops ixgbevf_xfrmdev_ops = {
|
||||
.xdo_dev_state_add = ixgbevf_ipsec_add_sa,
|
||||
.xdo_dev_state_delete = ixgbevf_ipsec_del_sa,
|
||||
.xdo_dev_offload_ok = ixgbevf_ipsec_offload_ok,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -744,24 +744,9 @@ static void cn10k_ipsec_del_state(struct xfrm_state *x)
|
|||
queue_work(pf->ipsec.sa_workq, &pf->ipsec.sa_work);
|
||||
}
|
||||
|
||||
static bool cn10k_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
||||
{
|
||||
if (x->props.family == AF_INET) {
|
||||
/* Offload with IPv4 options is not supported yet */
|
||||
if (ip_hdr(skb)->ihl > 5)
|
||||
return false;
|
||||
} else {
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops cn10k_ipsec_xfrmdev_ops = {
|
||||
.xdo_dev_state_add = cn10k_ipsec_add_state,
|
||||
.xdo_dev_state_delete = cn10k_ipsec_del_state,
|
||||
.xdo_dev_offload_ok = cn10k_ipsec_offload_ok,
|
||||
};
|
||||
|
||||
static void cn10k_ipsec_sa_wq_handler(struct work_struct *work)
|
||||
|
|
|
|||
|
|
@ -953,21 +953,6 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv)
|
|||
priv->ipsec = NULL;
|
||||
}
|
||||
|
||||
static bool mlx5e_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
||||
{
|
||||
if (x->props.family == AF_INET) {
|
||||
/* Offload with IPv4 options is not supported yet */
|
||||
if (ip_hdr(skb)->ihl > 5)
|
||||
return false;
|
||||
} else {
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mlx5e_xfrm_advance_esn_state(struct xfrm_state *x)
|
||||
{
|
||||
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
|
||||
|
|
@ -1196,7 +1181,6 @@ static const struct xfrmdev_ops mlx5e_ipsec_xfrmdev_ops = {
|
|||
.xdo_dev_state_add = mlx5e_xfrm_add_state,
|
||||
.xdo_dev_state_delete = mlx5e_xfrm_del_state,
|
||||
.xdo_dev_state_free = mlx5e_xfrm_free_state,
|
||||
.xdo_dev_offload_ok = mlx5e_ipsec_offload_ok,
|
||||
.xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state,
|
||||
|
||||
.xdo_dev_state_update_stats = mlx5e_xfrm_update_stats,
|
||||
|
|
|
|||
|
|
@ -565,20 +565,9 @@ static void nfp_net_xfrm_del_state(struct xfrm_state *x)
|
|||
xa_erase(&nn->xa_ipsec, x->xso.offload_handle - 1);
|
||||
}
|
||||
|
||||
static bool nfp_net_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
||||
{
|
||||
if (x->props.family == AF_INET)
|
||||
/* Offload with IPv4 options is not supported yet */
|
||||
return ip_hdr(skb)->ihl == 5;
|
||||
|
||||
/* Offload with IPv6 extension headers is not support yet */
|
||||
return !(ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr));
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops nfp_net_ipsec_xfrmdev_ops = {
|
||||
.xdo_dev_state_add = nfp_net_xfrm_add_state,
|
||||
.xdo_dev_state_delete = nfp_net_xfrm_del_state,
|
||||
.xdo_dev_offload_ok = nfp_net_ipsec_offload_ok,
|
||||
};
|
||||
|
||||
void nfp_net_ipsec_init(struct nfp_net *nn)
|
||||
|
|
|
|||
|
|
@ -217,20 +217,9 @@ static void nsim_ipsec_del_sa(struct xfrm_state *xs)
|
|||
ipsec->count--;
|
||||
}
|
||||
|
||||
static bool nsim_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
|
||||
{
|
||||
struct netdevsim *ns = netdev_priv(xs->xso.real_dev);
|
||||
struct nsim_ipsec *ipsec = &ns->ipsec;
|
||||
|
||||
ipsec->ok++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops nsim_xfrmdev_ops = {
|
||||
.xdo_dev_state_add = nsim_ipsec_add_sa,
|
||||
.xdo_dev_state_delete = nsim_ipsec_del_sa,
|
||||
.xdo_dev_offload_ok = nsim_ipsec_offload_ok,
|
||||
};
|
||||
|
||||
bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ struct nsim_ipsec {
|
|||
struct dentry *pfile;
|
||||
u32 count;
|
||||
u32 tx;
|
||||
u32 ok;
|
||||
};
|
||||
|
||||
#define NSIM_MACSEC_MAX_SECY_COUNT 3
|
||||
|
|
|
|||
|
|
@ -464,6 +464,15 @@ struct xfrm_type_offload {
|
|||
|
||||
int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
|
||||
void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
|
||||
void xfrm_set_type_offload(struct xfrm_state *x);
|
||||
static inline void xfrm_unset_type_offload(struct xfrm_state *x)
|
||||
{
|
||||
if (!x->type_offload)
|
||||
return;
|
||||
|
||||
module_put(x->type_offload->owner);
|
||||
x->type_offload = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct xfrm_mode_cbs - XFRM mode callbacks
|
||||
|
|
@ -1760,8 +1769,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
|
|||
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
|
||||
int xfrm_init_replay(struct xfrm_state *x, struct netlink_ext_ack *extack);
|
||||
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
||||
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
|
||||
struct netlink_ext_ack *extack);
|
||||
int __xfrm_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack);
|
||||
int xfrm_init_state(struct xfrm_state *x);
|
||||
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
|
||||
int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
|
||||
|
|
@ -1773,6 +1781,15 @@ int xfrm_trans_queue(struct sk_buff *skb,
|
|||
struct sk_buff *));
|
||||
int xfrm_output_resume(struct sock *sk, struct sk_buff *skb, int err);
|
||||
int xfrm_output(struct sock *sk, struct sk_buff *skb);
|
||||
int xfrm4_tunnel_check_size(struct sk_buff *skb);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
int xfrm6_tunnel_check_size(struct sk_buff *skb);
|
||||
#else
|
||||
static inline int xfrm6_tunnel_check_size(struct sk_buff *skb)
|
||||
{
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_PKTGEN)
|
||||
int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb);
|
||||
|
|
|
|||
|
|
@ -244,11 +244,6 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
|||
xfrm_address_t *daddr;
|
||||
bool is_packet_offload;
|
||||
|
||||
if (!x->type_offload) {
|
||||
NL_SET_ERR_MSG(extack, "Type doesn't support offload");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (xuo->flags &
|
||||
~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND | XFRM_OFFLOAD_PACKET)) {
|
||||
NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request");
|
||||
|
|
@ -310,6 +305,13 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
xfrm_set_type_offload(x);
|
||||
if (!x->type_offload) {
|
||||
NL_SET_ERR_MSG(extack, "Type doesn't support offload");
|
||||
dev_put(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xso->dev = dev;
|
||||
netdev_tracker_alloc(dev, &xso->dev_tracker, GFP_ATOMIC);
|
||||
xso->real_dev = dev;
|
||||
|
|
@ -332,6 +334,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
|||
netdev_put(dev, &xso->dev_tracker);
|
||||
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
|
||||
|
||||
xfrm_unset_type_offload(x);
|
||||
/* User explicitly requested packet offload mode and configured
|
||||
* policy in addition to the XFRM state. So be civil to users,
|
||||
* and return an error instead of taking fallback path.
|
||||
|
|
@ -415,14 +418,12 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
|||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
|
||||
struct net_device *dev = x->xso.dev;
|
||||
bool check_tunnel_size;
|
||||
|
||||
if (!x->type_offload ||
|
||||
(x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED && x->encap))
|
||||
if (x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED)
|
||||
return false;
|
||||
|
||||
if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET ||
|
||||
((!dev || (dev == xfrm_dst_path(dst)->dev)) &&
|
||||
!xdst->child->xfrm)) {
|
||||
if ((dev == xfrm_dst_path(dst)->dev) && !xdst->child->xfrm) {
|
||||
mtu = xfrm_state_mtu(x, xdst->child_mtu_cached);
|
||||
if (skb->len <= mtu)
|
||||
goto ok;
|
||||
|
|
@ -434,8 +435,29 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
|
|||
return false;
|
||||
|
||||
ok:
|
||||
if (dev && dev->xfrmdev_ops && dev->xfrmdev_ops->xdo_dev_offload_ok)
|
||||
return x->xso.dev->xfrmdev_ops->xdo_dev_offload_ok(skb, x);
|
||||
check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
|
||||
x->props.mode == XFRM_MODE_TUNNEL;
|
||||
switch (x->props.family) {
|
||||
case AF_INET:
|
||||
/* Check for IPv4 options */
|
||||
if (ip_hdr(skb)->ihl != 5)
|
||||
return false;
|
||||
if (check_tunnel_size && xfrm4_tunnel_check_size(skb))
|
||||
return false;
|
||||
break;
|
||||
case AF_INET6:
|
||||
/* Check for IPv6 extensions */
|
||||
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
|
||||
return false;
|
||||
if (check_tunnel_size && xfrm6_tunnel_check_size(skb))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->xfrmdev_ops->xdo_dev_offload_ok)
|
||||
return dev->xfrmdev_ops->xdo_dev_offload_ok(skb, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_output);
|
||||
|
||||
static int xfrm4_tunnel_check_size(struct sk_buff *skb)
|
||||
int xfrm4_tunnel_check_size(struct sk_buff *skb)
|
||||
{
|
||||
int mtu, ret = 0;
|
||||
|
||||
|
|
@ -812,6 +812,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm4_tunnel_check_size);
|
||||
|
||||
static int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -834,7 +835,7 @@ static int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static int xfrm6_tunnel_check_size(struct sk_buff *skb)
|
||||
int xfrm6_tunnel_check_size(struct sk_buff *skb)
|
||||
{
|
||||
int mtu, ret = 0;
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
|
|
@ -864,6 +865,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm6_tunnel_check_size);
|
||||
#endif
|
||||
|
||||
static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
|
|
|
|||
|
|
@ -424,18 +424,18 @@ void 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, bool try_load)
|
||||
void xfrm_set_type_offload(struct xfrm_state *x)
|
||||
{
|
||||
const struct xfrm_type_offload *type = NULL;
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
bool try_load = true;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_state_get_afinfo(family);
|
||||
afinfo = xfrm_state_get_afinfo(x->props.family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
switch (proto) {
|
||||
switch (x->id.proto) {
|
||||
case IPPROTO_ESP:
|
||||
type = afinfo->type_offload_esp;
|
||||
break;
|
||||
|
|
@ -449,18 +449,16 @@ xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
|
|||
rcu_read_unlock();
|
||||
|
||||
if (!type && try_load) {
|
||||
request_module("xfrm-offload-%d-%d", family, proto);
|
||||
request_module("xfrm-offload-%d-%d", x->props.family,
|
||||
x->id.proto);
|
||||
try_load = false;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
|
||||
{
|
||||
module_put(type->owner);
|
||||
out:
|
||||
x->type_offload = type;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_set_type_offload);
|
||||
|
||||
static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] = {
|
||||
[XFRM_MODE_BEET] = {
|
||||
|
|
@ -609,8 +607,6 @@ static void ___xfrm_state_destroy(struct xfrm_state *x)
|
|||
kfree(x->coaddr);
|
||||
kfree(x->replay_esn);
|
||||
kfree(x->preplay_esn);
|
||||
if (x->type_offload)
|
||||
xfrm_put_type_offload(x->type_offload);
|
||||
if (x->type) {
|
||||
x->type->destructor(x);
|
||||
xfrm_put_type(x->type);
|
||||
|
|
@ -784,6 +780,8 @@ void xfrm_dev_state_free(struct xfrm_state *x)
|
|||
struct xfrm_dev_offload *xso = &x->xso;
|
||||
struct net_device *dev = READ_ONCE(xso->dev);
|
||||
|
||||
xfrm_unset_type_offload(x);
|
||||
|
||||
if (dev && dev->xfrmdev_ops) {
|
||||
spin_lock_bh(&xfrm_state_dev_gc_lock);
|
||||
if (!hlist_unhashed(&x->dev_gclist))
|
||||
|
|
@ -3122,8 +3120,7 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_state_mtu);
|
||||
|
||||
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
|
||||
struct netlink_ext_ack *extack)
|
||||
int __xfrm_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode;
|
||||
const struct xfrm_mode *outer_mode;
|
||||
|
|
@ -3178,8 +3175,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
|
|||
goto error;
|
||||
}
|
||||
|
||||
x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload);
|
||||
|
||||
err = x->type->init_state(x, extack);
|
||||
if (err)
|
||||
goto error;
|
||||
|
|
@ -3192,12 +3187,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
|
|||
}
|
||||
|
||||
x->outer_mode = *outer_mode;
|
||||
if (init_replay) {
|
||||
err = xfrm_init_replay(x, extack);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (x->nat_keepalive_interval) {
|
||||
if (x->dir != XFRM_SA_DIR_OUT) {
|
||||
NL_SET_ERR_MSG(extack, "NAT keepalive is only supported for outbound SAs");
|
||||
|
|
@ -3229,11 +3218,16 @@ int xfrm_init_state(struct xfrm_state *x)
|
|||
{
|
||||
int err;
|
||||
|
||||
err = __xfrm_init_state(x, true, false, NULL);
|
||||
if (!err)
|
||||
x->km.state = XFRM_STATE_VALID;
|
||||
err = __xfrm_init_state(x, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return err;
|
||||
err = xfrm_init_replay(x, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
x->km.state = XFRM_STATE_VALID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xfrm_init_state);
|
||||
|
|
|
|||
|
|
@ -919,7 +919,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
|
|||
goto error;
|
||||
}
|
||||
|
||||
err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV], extack);
|
||||
err = __xfrm_init_state(x, extack);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user