xfrm: add prep for esp beet mode offload
Like __xfrm_transport/mode_tunnel_prep(), this patch is to add __xfrm_mode_beet_prep() to fix the transport_header for gso segments, and reset skb mac_len, and pull skb data to the proto inside esp. This patch also fixes a panic, reported by ltp: # modprobe esp4_offload # runltp -f net_stress.ipsec_tcp [ 2452.780511] kernel BUG at net/core/skbuff.c:109! [ 2452.799851] Call Trace: [ 2452.800298] <IRQ> [ 2452.800705] skb_push.cold.98+0x14/0x20 [ 2452.801396] esp_xmit+0x17b/0x270 [esp4_offload] [ 2452.802799] validate_xmit_xfrm+0x22f/0x2e0 [ 2452.804285] __dev_queue_xmit+0x589/0x910 [ 2452.806264] __neigh_update+0x3d7/0xa50 [ 2452.806958] arp_process+0x259/0x810 [ 2452.807589] arp_rcv+0x18a/0x1c It was caused by the skb going to esp_xmit with a wrong transport header. Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Родитель
7f9e40eb18
Коммит
308491755f
|
@ -46,6 +46,25 @@ static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
|
|||
pskb_pull(skb, skb->mac_len + x->props.header_len);
|
||||
}
|
||||
|
||||
static void __xfrm_mode_beet_prep(struct xfrm_state *x, struct sk_buff *skb,
|
||||
unsigned int hsize)
|
||||
{
|
||||
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||
int phlen = 0;
|
||||
|
||||
if (xo->flags & XFRM_GSO_SEGMENT)
|
||||
skb->transport_header = skb->network_header + hsize;
|
||||
|
||||
skb_reset_mac_len(skb);
|
||||
if (x->sel.family != AF_INET6) {
|
||||
phlen = IPV4_BEET_PHMAXLEN;
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
phlen += sizeof(struct ipv6hdr) - sizeof(struct iphdr);
|
||||
}
|
||||
|
||||
pskb_pull(skb, skb->mac_len + hsize + (x->props.header_len - phlen));
|
||||
}
|
||||
|
||||
/* Adjust pointers into the packet when IPsec is done at layer2 */
|
||||
static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -66,9 +85,16 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
|
|||
return __xfrm_transport_prep(x, skb,
|
||||
sizeof(struct ipv6hdr));
|
||||
break;
|
||||
case XFRM_MODE_BEET:
|
||||
if (x->outer_mode.family == AF_INET)
|
||||
return __xfrm_mode_beet_prep(x, skb,
|
||||
sizeof(struct iphdr));
|
||||
if (x->outer_mode.family == AF_INET6)
|
||||
return __xfrm_mode_beet_prep(x, skb,
|
||||
sizeof(struct ipv6hdr));
|
||||
break;
|
||||
case XFRM_MODE_ROUTEOPTIMIZATION:
|
||||
case XFRM_MODE_IN_TRIGGER:
|
||||
case XFRM_MODE_BEET:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче