Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[platform/kernel/linux-starfive.git] / net / xfrm / xfrm_device.c
index e2db468..6cc7f7f 100644 (file)
@@ -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;
        }
 }