Skip to content

Commit 8476165

Browse files
author
Paolo Abeni
committed
Merge tag 'ipsec-2025-03-19' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2025-03-19 1) Fix tunnel mode TX datapath in packet offload mode by directly putting it to the xmit path. From Alexandre Cassen. 2) Force software GSO only in tunnel mode in favor of potential HW GSO. From Cosmin Ratiu. ipsec-2025-03-19 * tag 'ipsec-2025-03-19' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm_output: Force software GSO only in tunnel mode xfrm: fix tunnel mode TX datapath in packet offload mode ==================== Link: https://patch.msgid.link/20250319065513.987135-1-steffen.klassert@secunet.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 2fdf088 + 0aae286 commit 8476165

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

net/xfrm/xfrm_output.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,40 @@ int xfrm_output_resume(struct sock *sk, struct sk_buff *skb, int err)
612612
}
613613
EXPORT_SYMBOL_GPL(xfrm_output_resume);
614614

615+
static int xfrm_dev_direct_output(struct sock *sk, struct xfrm_state *x,
616+
struct sk_buff *skb)
617+
{
618+
struct dst_entry *dst = skb_dst(skb);
619+
struct net *net = xs_net(x);
620+
int err;
621+
622+
dst = skb_dst_pop(skb);
623+
if (!dst) {
624+
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
625+
kfree_skb(skb);
626+
return -EHOSTUNREACH;
627+
}
628+
skb_dst_set(skb, dst);
629+
nf_reset_ct(skb);
630+
631+
err = skb_dst(skb)->ops->local_out(net, sk, skb);
632+
if (unlikely(err != 1)) {
633+
kfree_skb(skb);
634+
return err;
635+
}
636+
637+
/* In transport mode, network destination is
638+
* directly reachable, while in tunnel mode,
639+
* inner packet network may not be. In packet
640+
* offload type, HW is responsible for hard
641+
* header packet mangling so directly xmit skb
642+
* to netdevice.
643+
*/
644+
skb->dev = x->xso.dev;
645+
__skb_push(skb, skb->dev->hard_header_len);
646+
return dev_queue_xmit(skb);
647+
}
648+
615649
static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
616650
{
617651
return xfrm_output_resume(sk, skb, 1);
@@ -735,6 +769,13 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
735769
return -EHOSTUNREACH;
736770
}
737771

772+
/* Exclusive direct xmit for tunnel mode, as
773+
* some filtering or matching rules may apply
774+
* in transport mode.
775+
*/
776+
if (x->props.mode == XFRM_MODE_TUNNEL)
777+
return xfrm_dev_direct_output(sk, x, skb);
778+
738779
return xfrm_output_resume(sk, skb, 0);
739780
}
740781

@@ -758,7 +799,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
758799
skb->encapsulation = 1;
759800

760801
if (skb_is_gso(skb)) {
761-
if (skb->inner_protocol)
802+
if (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL)
762803
return xfrm_output_gso(net, sk, skb);
763804

764805
skb_shinfo(skb)->gso_type |= SKB_GSO_ESP;

0 commit comments

Comments
 (0)