Skip to content

Commit 45a98ef

Browse files
raed-salemklassert
authored andcommitted
net/xfrm: IPsec tunnel mode fix inner_ipproto setting in sec_path
The inner_ipproto saves the inner IP protocol of the plain text packet. This allows vendor's IPsec feature making offload decision at skb's features_check and configuring hardware at ndo_start_xmit, current code implenetation did not handle the case where IPsec is used in tunnel mode. Fix by handling the case when IPsec is used in tunnel mode by reading the protocol of the plain text packet IP protocol. Fixes: fa45352 ("net/xfrm: Add inner_ipproto into sec_path") Signed-off-by: Raed Salem <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 68ac0f3 commit 45a98ef

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

net/xfrm/xfrm_output.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -647,17 +647,38 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
647647
* This requires hardware to know the inner packet type to calculate
648648
* the inner header checksum. Save inner ip protocol here to avoid
649649
* traversing the packet in the vendor's xmit code.
650-
* If the encap type is IPIP, just save skb->inner_ipproto. Otherwise,
651-
* get the ip protocol from the IP header.
650+
* For IPsec tunnel mode save the ip protocol from the IP header of the
651+
* plain text packet. Otherwise If the encap type is IPIP, just save
652+
* skb->inner_ipproto in any other case get the ip protocol from the IP
653+
* header.
652654
*/
653-
static void xfrm_get_inner_ipproto(struct sk_buff *skb)
655+
static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
654656
{
655657
struct xfrm_offload *xo = xfrm_offload(skb);
656658
const struct ethhdr *eth;
657659

658660
if (!xo)
659661
return;
660662

663+
if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
664+
switch (x->outer_mode.family) {
665+
case AF_INET:
666+
xo->inner_ipproto = ip_hdr(skb)->protocol;
667+
break;
668+
case AF_INET6:
669+
xo->inner_ipproto = ipv6_hdr(skb)->nexthdr;
670+
break;
671+
default:
672+
break;
673+
}
674+
675+
return;
676+
}
677+
678+
/* non-Tunnel Mode */
679+
if (!skb->encapsulation)
680+
return;
681+
661682
if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) {
662683
xo->inner_ipproto = skb->inner_ipproto;
663684
return;
@@ -712,8 +733,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
712733
sp->xvec[sp->len++] = x;
713734
xfrm_state_hold(x);
714735

715-
if (skb->encapsulation)
716-
xfrm_get_inner_ipproto(skb);
736+
xfrm_get_inner_ipproto(skb, x);
717737
skb->encapsulation = 1;
718738

719739
if (skb_is_gso(skb)) {

0 commit comments

Comments
 (0)