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 <pshelar@nicira.com>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 291e670..515a35e2 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -282,6 +282,40 @@
}
/**
+ * __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
* @vlan_proto: VLAN encapsulation protocol
@@ -298,24 +332,13 @@
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;
}