Correct .gbs.conf settings
[platform/adaptation/renesas_rcar/renesas_kernel.git] / net / core / skbuff.c
index 90b96a1..baf6fc4 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/scatterlist.h>
 #include <linux/errqueue.h>
 #include <linux/prefetch.h>
+#include <linux/if_vlan.h>
 
 #include <net/protocol.h>
 #include <net/dst.h>
@@ -2881,12 +2882,13 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
        int pos;
        int dummy;
 
+       __skb_push(head_skb, doffset);
        proto = skb_network_protocol(head_skb, &dummy);
        if (unlikely(!proto))
                return ERR_PTR(-EINVAL);
 
        csum = !!can_checksum_protocol(features, proto);
-       __skb_push(head_skb, doffset);
+
        headroom = skb_headroom(head_skb);
        pos = skb_headlen(head_skb);
 
@@ -2967,9 +2969,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
                tail = nskb;
 
                __copy_skb_header(nskb, head_skb);
-               nskb->mac_len = head_skb->mac_len;
 
                skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
+               skb_reset_mac_len(nskb);
 
                skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
                                                 nskb->data - tnl_hlen,
@@ -3076,7 +3078,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        if (unlikely(p->len + len >= 65536))
                return -E2BIG;
 
-       lp = NAPI_GRO_CB(p)->last ?: p;
+       lp = NAPI_GRO_CB(p)->last;
        pinfo = skb_shinfo(lp);
 
        if (headlen <= offset) {
@@ -3138,6 +3140,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
                NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
                goto done;
        }
+       /* switch back to head shinfo */
+       pinfo = skb_shinfo(p);
+
        if (pinfo->frag_list)
                goto merge;
        if (skb_gro_len(p) != pinfo->gso_size)
@@ -3192,7 +3197,7 @@ merge:
 
        __skb_pull(skb, offset);
 
-       if (!NAPI_GRO_CB(p)->last)
+       if (NAPI_GRO_CB(p)->last == p)
                skb_shinfo(p)->frag_list = skb;
        else
                NAPI_GRO_CB(p)->last->next = skb;
@@ -3951,12 +3956,66 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet);
 unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
 {
        const struct skb_shared_info *shinfo = skb_shinfo(skb);
-       unsigned int hdr_len;
 
        if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-               hdr_len = tcp_hdrlen(skb);
-       else
-               hdr_len = sizeof(struct udphdr);
-       return hdr_len + shinfo->gso_size;
+               return tcp_hdrlen(skb) + shinfo->gso_size;
+
+       /* UFO sets gso_size to the size of the fragmentation
+        * payload, i.e. the size of the L4 (UDP) header is already
+        * accounted for.
+        */
+       return shinfo->gso_size;
 }
 EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
+
+static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
+{
+       if (skb_cow(skb, skb_headroom(skb)) < 0) {
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
+       skb->mac_header += VLAN_HLEN;
+       return skb;
+}
+
+struct sk_buff *skb_vlan_untag(struct sk_buff *skb)
+{
+       struct vlan_hdr *vhdr;
+       u16 vlan_tci;
+
+       if (unlikely(vlan_tx_tag_present(skb))) {
+               /* vlan_tci is already set-up so leave this for another time */
+               return skb;
+       }
+
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (unlikely(!skb))
+               goto err_free;
+
+       if (unlikely(!pskb_may_pull(skb, VLAN_HLEN)))
+               goto err_free;
+
+       vhdr = (struct vlan_hdr *)skb->data;
+       vlan_tci = ntohs(vhdr->h_vlan_TCI);
+       __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci);
+
+       skb_pull_rcsum(skb, VLAN_HLEN);
+       vlan_set_encap_proto(skb, vhdr);
+
+       skb = skb_reorder_vlan_header(skb);
+       if (unlikely(!skb))
+               goto err_free;
+
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
+       skb_reset_mac_len(skb);
+
+       return skb;
+
+err_free:
+       kfree_skb(skb);
+       return NULL;
+}
+EXPORT_SYMBOL(skb_vlan_untag);