]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ipv6/ip6_offload.c
net: define gso types for IPx over IPv4 and IPv6
[mirror_ubuntu-artful-kernel.git] / net / ipv6 / ip6_offload.c
index 82e9f30760283aca2f3d9468573aea607bd5bf6b..787e55f4796cf5a8772b18dd8338692fa82bee21 100644 (file)
@@ -63,27 +63,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        int proto;
        struct frag_hdr *fptr;
        unsigned int unfrag_ip6hlen;
+       unsigned int payload_len;
        u8 *prevhdr;
        int offset = 0;
        bool encap, udpfrag;
        int nhoff;
 
-       if (unlikely(skb_shinfo(skb)->gso_type &
-                    ~(SKB_GSO_TCPV4 |
-                      SKB_GSO_UDP |
-                      SKB_GSO_DODGY |
-                      SKB_GSO_TCP_ECN |
-                      SKB_GSO_GRE |
-                      SKB_GSO_GRE_CSUM |
-                      SKB_GSO_IPIP |
-                      SKB_GSO_SIT |
-                      SKB_GSO_UDP_TUNNEL |
-                      SKB_GSO_UDP_TUNNEL_CSUM |
-                      SKB_GSO_TUNNEL_REMCSUM |
-                      SKB_GSO_TCPV6 |
-                      0)))
-               goto out;
-
        skb_reset_network_header(skb);
        nhoff = skb_network_header(skb) - skb_mac_header(skb);
        if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
@@ -101,7 +86,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
 
        if (skb->encapsulation &&
-           skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
+           skb_shinfo(skb)->gso_type & (SKB_GSO_IPXIP4 | SKB_GSO_IPXIP6))
                udpfrag = proto == IPPROTO_UDP && encap;
        else
                udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
@@ -117,7 +102,13 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
        for (skb = segs; skb; skb = skb->next) {
                ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff);
-               ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h));
+               if (skb_is_gso(skb))
+                       payload_len = skb_shinfo(skb)->gso_size +
+                                     SKB_GSO_CB(skb)->data_offset +
+                                     skb->head - (unsigned char *)(ipv6h + 1);
+               else
+                       payload_len = skb->len - nhoff - sizeof(*ipv6h);
+               ipv6h->payload_len = htons(payload_len);
                skb->network_header = (u8 *)ipv6h - skb->head;
 
                if (udpfrag) {
@@ -239,10 +230,14 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
                NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
                NAPI_GRO_CB(p)->flush |= flush;
 
-               /* Clear flush_id, there's really no concept of ID in IPv6. */
-               NAPI_GRO_CB(p)->flush_id = 0;
+               /* If the previous IP ID value was based on an atomic
+                * datagram we can overwrite the value and ignore it.
+                */
+               if (NAPI_GRO_CB(skb)->is_atomic)
+                       NAPI_GRO_CB(p)->flush_id = 0;
        }
 
+       NAPI_GRO_CB(skb)->is_atomic = true;
        NAPI_GRO_CB(skb)->flush |= flush;
 
        skb_gro_postpull_rcsum(skb, iph, nlen);
@@ -299,7 +294,7 @@ out_unlock:
 static int sit_gro_complete(struct sk_buff *skb, int nhoff)
 {
        skb->encapsulation = 1;
-       skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
+       skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
        return ipv6_gro_complete(skb, nhoff);
 }
 
@@ -325,8 +320,6 @@ static int __init ipv6_offload_init(void)
 
        if (tcpv6_offload_init() < 0)
                pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
-       if (udp_offload_init() < 0)
-               pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
        if (ipv6_exthdrs_offload_init() < 0)
                pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);