From 15255a43e6c917813800702e100267046e240cc0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 19 Nov 2014 14:05:00 +0100 Subject: [PATCH] vlan: introduce __vlan_insert_tag helper which does not free skb There's a need for helper which inserts vlan tag but does not free the skb in case of an error. Suggested-by: Pravin Shelar Signed-off-by: Jiri Pirko Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 291e6706876e..515a35e2a48a 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -281,6 +281,40 @@ static inline bool vlan_hw_offload_capable(netdev_features_t features, return false; } +/** + * __vlan_insert_tag - regular VLAN tag inserting + * @skb: skbuff to tag + * @vlan_proto: VLAN encapsulation protocol + * @vlan_tci: VLAN TCI to insert + * + * Inserts the VLAN tag into @skb as part of the payload + * Returns error if skb_cow_head failes. + * + * Does not change skb->protocol so this function can be used during receive. + */ +static inline int __vlan_insert_tag(struct sk_buff *skb, + __be16 vlan_proto, u16 vlan_tci) +{ + struct vlan_ethhdr *veth; + + if (skb_cow_head(skb, VLAN_HLEN) < 0) + return -ENOMEM; + + veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); + + /* Move the mac addresses to the beginning of the new header. */ + memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); + skb->mac_header -= VLAN_HLEN; + + /* first, the ethernet type */ + veth->h_vlan_proto = vlan_proto; + + /* now, the TCI */ + veth->h_vlan_TCI = htons(vlan_tci); + + return 0; +} + /** * vlan_insert_tag - regular VLAN tag inserting * @skb: skbuff to tag @@ -298,24 +332,13 @@ static inline bool vlan_hw_offload_capable(netdev_features_t features, static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) { - struct vlan_ethhdr *veth; + int err; - if (skb_cow_head(skb, VLAN_HLEN) < 0) { + err = __vlan_insert_tag(skb, vlan_proto, vlan_tci); + if (err) { dev_kfree_skb_any(skb); return NULL; } - veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); - - /* Move the mac addresses to the beginning of the new header. */ - memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); - skb->mac_header -= VLAN_HLEN; - - /* first, the ethernet type */ - veth->h_vlan_proto = vlan_proto; - - /* now, the TCI */ - veth->h_vlan_TCI = htons(vlan_tci); - return skb; }