mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
ipsec-next-2025-03-24
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmfg9oUACgkQrB3Eaf9P W7d8eRAAhUdQztUoVjNfRBScD34EHEBq8ruFMgbHcXkkdhg223CUaTYKqz3dYE1E 04OCSwe7yxFFSs7CKR4dRMSzcx7uH/ISPprk45g+wwoIzBCYOWjLBzS5qmamtSYu E3sI/QZaVUU7mFDg5n3sr5nkCNz+LtTL2dUbOgi5AOqY9h7LZRzLBEB1RCVOioVO 14vDRBJ5RGIvmNx3pd0sRhB4BySUw1GQVTYLSFaL/V2JZcRu3yGhKT8q637fdKcS blvdf5q4CYyu5i3p9LHhsg33D8fYUotBVFtzw3QaM1G9MdyhMF4WUbeZCa2kkk7J N7j2N0WDjP7crKQkPbm9ATQiruF2zvPcYJqgIHKuNhWY35KNIFARWxbP8KGJJFUI EqUUKuT0lUi39hULmm5YEqCGWLNQldTBOOZL1fccRj2DZelx4uhQsnt5B2yimUCD 7QJGH0Vx6NJAutuCgTXQtmD0qO2XYi50XLmh4K+HZ1M3DkSGohcYSz+aj8IIY/wT +yT55uRoONqDbh9kOLHab0WWE6R+XJyY5rKnz6XpzyTPh0OwoxrbVXJF045NYIpB tSl9ykVpymvWNT56nsfXEOm5THZhdvL+uDS/QV4rtF9En4TEJU0dGbhESvriuu2j g6EAQpYJqL9OwA5aKVZCGlHf7siji7Z/uc57DADZ8mtmDXVMqco= =9RMg -----END PGP SIGNATURE----- Merge tag 'ipsec-next-2025-03-24' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next Steffen Klassert says: ==================== pull request (net-next): ipsec-next 2025-03-24 1) Prevent setting high order sequence number bits input in non-ESN mode. From Leon Romanovsky. 2) Support PMTU handling in tunnel mode for packet offload. From Leon Romanovsky. 3) Make xfrm_state_lookup_byaddr lockless. From Florian Westphal. 4) Remove unnecessary NULL check in xfrm_lookup_with_ifid(). From Dan Carpenter. * tag 'ipsec-next-2025-03-24' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next: xfrm: Remove unnecessary NULL check in xfrm_lookup_with_ifid() xfrm: state: make xfrm_state_lookup_byaddr lockless xfrm: check for PMTU in tunnel mode for packet offload xfrm: provide common xdo_dev_offload_ok callback implementation xfrm: rely on XFRM offload xfrm: simplify SA initialization routine xfrm: delay initialization of offload path till its actually requested xfrm: prevent high SEQ input in non-ESN mode ==================== Link: https://patch.msgid.link/20250324061855.4116819-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
586b7b3ebb
17 changed files with 102 additions and 193 deletions
|
@ -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
|
||||
|
|
|
@ -674,22 +674,16 @@ out:
|
|||
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 @@ out_unlock:
|
|||
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)
|
||||
|
|
|
@ -966,21 +966,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);
|
||||
|
@ -1247,7 +1232,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;
|
||||
}
|
||||
|
|
|
@ -827,7 +827,7 @@ out:
|
|||
}
|
||||
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;
|
||||
|
||||
|
@ -853,6 +853,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)
|
||||
{
|
||||
|
@ -875,7 +876,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);
|
||||
|
@ -905,6 +906,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)
|
||||
|
|
|
@ -3294,7 +3294,7 @@ no_transform:
|
|||
|
||||
ok:
|
||||
xfrm_pols_put(pols, drop_pols);
|
||||
if (dst && dst->xfrm &&
|
||||
if (dst->xfrm &&
|
||||
(dst->xfrm->props.mode == XFRM_MODE_TUNNEL ||
|
||||
dst->xfrm->props.mode == XFRM_MODE_IPTFS))
|
||||
dst->flags |= DST_XFRM_TUNNEL;
|
||||
|
|
|
@ -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 @@ retry:
|
|||
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))
|
||||
|
@ -2315,12 +2313,12 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
|
|||
struct xfrm_hash_state_ptrs state_ptrs;
|
||||
struct xfrm_state *x;
|
||||
|
||||
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||
rcu_read_lock();
|
||||
|
||||
xfrm_hash_ptrs_get(net, &state_ptrs);
|
||||
|
||||
x = __xfrm_state_lookup_byaddr(&state_ptrs, mark, daddr, saddr, proto, family);
|
||||
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
|
||||
rcu_read_unlock();
|
||||
return x;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
|
||||
|
@ -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);
|
||||
|
|
|
@ -178,6 +178,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
|
|||
"Replay seq and seq_hi should be 0 for output SA");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rs->oseq_hi && !(p->flags & XFRM_STATE_ESN)) {
|
||||
NL_SET_ERR_MSG(
|
||||
extack,
|
||||
"Replay oseq_hi should be 0 in non-ESN mode for output SA");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rs->bmp_len) {
|
||||
NL_SET_ERR_MSG(extack, "Replay bmp_len should 0 for output SA");
|
||||
return -EINVAL;
|
||||
|
@ -190,6 +196,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
|
|||
"Replay oseq and oseq_hi should be 0 for input SA");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rs->seq_hi && !(p->flags & XFRM_STATE_ESN)) {
|
||||
NL_SET_ERR_MSG(
|
||||
extack,
|
||||
"Replay seq_hi should be 0 in non-ESN mode for input SA");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -907,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…
Add table
Reference in a new issue