aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/rtnetlink.c3
-rw-r--r--net/core/skbuff.c53
3 files changed, 56 insertions, 2 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1c15b189c52b..b65a5051361f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3602,7 +3602,7 @@ another_round:
3602 3602
3603 if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || 3603 if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
3604 skb->protocol == cpu_to_be16(ETH_P_8021AD)) { 3604 skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
3605 skb = vlan_untag(skb); 3605 skb = skb_vlan_untag(skb);
3606 if (unlikely(!skb)) 3606 if (unlikely(!skb))
3607 goto unlock; 3607 goto unlock;
3608 } 3608 }
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8d39071f32d7..f0493e3b7471 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -804,7 +804,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
804 (nla_total_size(sizeof(struct ifla_vf_mac)) + 804 (nla_total_size(sizeof(struct ifla_vf_mac)) +
805 nla_total_size(sizeof(struct ifla_vf_vlan)) + 805 nla_total_size(sizeof(struct ifla_vf_vlan)) +
806 nla_total_size(sizeof(struct ifla_vf_spoofchk)) + 806 nla_total_size(sizeof(struct ifla_vf_spoofchk)) +
807 nla_total_size(sizeof(struct ifla_vf_rate))); 807 nla_total_size(sizeof(struct ifla_vf_rate)) +
808 nla_total_size(sizeof(struct ifla_vf_link_state)));
808 return size; 809 return size;
809 } else 810 } else
810 return 0; 811 return 0;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 224506a6fa80..163b673f9e62 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -62,6 +62,7 @@
62#include <linux/scatterlist.h> 62#include <linux/scatterlist.h>
63#include <linux/errqueue.h> 63#include <linux/errqueue.h>
64#include <linux/prefetch.h> 64#include <linux/prefetch.h>
65#include <linux/if_vlan.h>
65 66
66#include <net/protocol.h> 67#include <net/protocol.h>
67#include <net/dst.h> 68#include <net/dst.h>
@@ -3973,3 +3974,55 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
3973 return shinfo->gso_size; 3974 return shinfo->gso_size;
3974} 3975}
3975EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); 3976EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
3977
3978static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
3979{
3980 if (skb_cow(skb, skb_headroom(skb)) < 0) {
3981 kfree_skb(skb);
3982 return NULL;
3983 }
3984
3985 memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
3986 skb->mac_header += VLAN_HLEN;
3987 return skb;
3988}
3989
3990struct sk_buff *skb_vlan_untag(struct sk_buff *skb)
3991{
3992 struct vlan_hdr *vhdr;
3993 u16 vlan_tci;
3994
3995 if (unlikely(vlan_tx_tag_present(skb))) {
3996 /* vlan_tci is already set-up so leave this for another time */
3997 return skb;
3998 }
3999
4000 skb = skb_share_check(skb, GFP_ATOMIC);
4001 if (unlikely(!skb))
4002 goto err_free;
4003
4004 if (unlikely(!pskb_may_pull(skb, VLAN_HLEN)))
4005 goto err_free;
4006
4007 vhdr = (struct vlan_hdr *)skb->data;
4008 vlan_tci = ntohs(vhdr->h_vlan_TCI);
4009 __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci);
4010
4011 skb_pull_rcsum(skb, VLAN_HLEN);
4012 vlan_set_encap_proto(skb, vhdr);
4013
4014 skb = skb_reorder_vlan_header(skb);
4015 if (unlikely(!skb))
4016 goto err_free;
4017
4018 skb_reset_network_header(skb);
4019 skb_reset_transport_header(skb);
4020 skb_reset_mac_len(skb);
4021
4022 return skb;
4023
4024err_free:
4025 kfree_skb(skb);
4026 return NULL;
4027}
4028EXPORT_SYMBOL(skb_vlan_untag);