Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: Add encapsulation header offsets while SKB is not encrypted

Both esp4 and esp6 used to assume that the SKB payload is encrypted
and therefore the inner_network and inner_transport offsets are
not relevant.
When doing crypto offload in the NIC, this is no longer the case
and the NIC driver needs these offsets so it can do TX TCP checksum
offloading.
This patch sets the inner_network and inner_transport members of
the SKB, as well as encapsulation, to reflect the actual positions
of these headers, and removes them only once encryption is done
on the payload.

Signed-off-by: Ilan Tayari <ilant@mellanox.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Ilan Tayari and committed by
Steffen Klassert
f1bd7d65 f6e27114

+11
+2
net/ipv4/xfrm4_mode_transport.c
··· 24 24 struct iphdr *iph = ip_hdr(skb); 25 25 int ihl = iph->ihl * 4; 26 26 27 + skb_set_inner_transport_header(skb, skb_transport_offset(skb)); 28 + 27 29 skb_set_network_header(skb, -x->props.header_len); 28 30 skb->mac_header = skb->network_header + 29 31 offsetof(struct iphdr, protocol);
+3
net/ipv4/xfrm4_mode_tunnel.c
··· 33 33 struct iphdr *top_iph; 34 34 int flags; 35 35 36 + skb_set_inner_network_header(skb, skb_network_offset(skb)); 37 + skb_set_inner_transport_header(skb, skb_transport_offset(skb)); 38 + 36 39 skb_set_network_header(skb, -x->props.header_len); 37 40 skb->mac_header = skb->network_header + 38 41 offsetof(struct iphdr, protocol);
+1
net/ipv6/xfrm6_mode_transport.c
··· 27 27 int hdr_len; 28 28 29 29 iph = ipv6_hdr(skb); 30 + skb_set_inner_transport_header(skb, skb_transport_offset(skb)); 30 31 31 32 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 32 33 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
+3
net/ipv6/xfrm6_mode_tunnel.c
··· 36 36 struct ipv6hdr *top_iph; 37 37 int dsfield; 38 38 39 + skb_set_inner_network_header(skb, skb_network_offset(skb)); 40 + skb_set_inner_transport_header(skb, skb_transport_offset(skb)); 41 + 39 42 skb_set_network_header(skb, -x->props.header_len); 40 43 skb->mac_header = skb->network_header + 41 44 offsetof(struct ipv6hdr, nexthdr);
+2
net/xfrm/xfrm_output.c
··· 205 205 int err; 206 206 207 207 secpath_reset(skb); 208 + skb->encapsulation = 0; 208 209 209 210 if (xfrm_dev_offload_ok(skb, x)) { 210 211 struct sec_path *sp; ··· 219 218 if (skb->sp) 220 219 secpath_put(skb->sp); 221 220 skb->sp = sp; 221 + skb->encapsulation = 1; 222 222 223 223 sp->olen++; 224 224 sp->xvec[skb->sp->len++] = x;