]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/xfrm4_mode_transport.c
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
[karo-tx-linux.git] / net / ipv4 / xfrm4_mode_transport.c
index 4acc0508c5ebc65dc392de50a207901b2ea8d305..3d36644890bb6d3b0a755c811c60e920ad5cd8b8 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/dst.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
+#include <net/protocol.h>
 
 /* Add encapsulation header.
  *
@@ -23,6 +24,8 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
        struct iphdr *iph = ip_hdr(skb);
        int ihl = iph->ihl * 4;
 
+       skb_set_inner_transport_header(skb, skb_transport_offset(skb));
+
        skb_set_network_header(skb, -x->props.header_len);
        skb->mac_header = skb->network_header +
                          offsetof(struct iphdr, protocol);
@@ -56,9 +59,40 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 }
 
+static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
+                                                  struct sk_buff *skb,
+                                                  netdev_features_t features)
+{
+       const struct net_offload *ops;
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+       struct xfrm_offload *xo = xfrm_offload(skb);
+
+       skb->transport_header += x->props.header_len;
+       ops = rcu_dereference(inet_offloads[xo->proto]);
+       if (likely(ops && ops->callbacks.gso_segment))
+               segs = ops->callbacks.gso_segment(skb, features);
+
+       return segs;
+}
+
+static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
+{
+       struct xfrm_offload *xo = xfrm_offload(skb);
+
+       skb_reset_mac_len(skb);
+       pskb_pull(skb, skb->mac_len + sizeof(struct iphdr) + x->props.header_len);
+
+       if (xo->flags & XFRM_GSO_SEGMENT) {
+                skb_reset_transport_header(skb);
+                skb->transport_header -= x->props.header_len;
+       }
+}
+
 static struct xfrm_mode xfrm4_transport_mode = {
        .input = xfrm4_transport_input,
        .output = xfrm4_transport_output,
+       .gso_segment = xfrm4_transport_gso_segment,
+       .xmit = xfrm4_transport_xmit,
        .owner = THIS_MODULE,
        .encap = XFRM_MODE_TRANSPORT,
 };