|
@@ -300,30 +300,34 @@ static inline bool vlan_hw_offload_capable(netdev_features_t features,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * __vlan_insert_tag - regular VLAN tag inserting
|
|
|
+ * __vlan_insert_inner_tag - inner VLAN tag inserting
|
|
|
* @skb: skbuff to tag
|
|
|
* @vlan_proto: VLAN encapsulation protocol
|
|
|
* @vlan_tci: VLAN TCI to insert
|
|
|
+ * @mac_len: MAC header length including outer vlan headers
|
|
|
*
|
|
|
- * Inserts the VLAN tag into @skb as part of the payload
|
|
|
+ * Inserts the VLAN tag into @skb as part of the payload at offset mac_len
|
|
|
* 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)
|
|
|
+static inline int __vlan_insert_inner_tag(struct sk_buff *skb,
|
|
|
+ __be16 vlan_proto, u16 vlan_tci,
|
|
|
+ unsigned int mac_len)
|
|
|
{
|
|
|
struct vlan_ethhdr *veth;
|
|
|
|
|
|
if (skb_cow_head(skb, VLAN_HLEN) < 0)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- veth = skb_push(skb, VLAN_HLEN);
|
|
|
+ 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);
|
|
|
+ /* Move the mac header sans proto to the beginning of the new header. */
|
|
|
+ memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN);
|
|
|
skb->mac_header -= VLAN_HLEN;
|
|
|
|
|
|
+ veth = (struct vlan_ethhdr *)(skb->data + mac_len - ETH_HLEN);
|
|
|
+
|
|
|
/* first, the ethernet type */
|
|
|
veth->h_vlan_proto = vlan_proto;
|
|
|
|
|
@@ -334,12 +338,30 @@ static inline int __vlan_insert_tag(struct sk_buff *skb,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * vlan_insert_tag - regular VLAN tag inserting
|
|
|
+ * __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)
|
|
|
+{
|
|
|
+ return __vlan_insert_inner_tag(skb, vlan_proto, vlan_tci, ETH_HLEN);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * vlan_insert_inner_tag - inner VLAN tag inserting
|
|
|
+ * @skb: skbuff to tag
|
|
|
+ * @vlan_proto: VLAN encapsulation protocol
|
|
|
+ * @vlan_tci: VLAN TCI to insert
|
|
|
+ * @mac_len: MAC header length including outer vlan headers
|
|
|
+ *
|
|
|
+ * Inserts the VLAN tag into @skb as part of the payload at offset mac_len
|
|
|
* Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
|
|
|
*
|
|
|
* Following the skb_unshare() example, in case of error, the calling function
|
|
@@ -347,12 +369,14 @@ static inline int __vlan_insert_tag(struct sk_buff *skb,
|
|
|
*
|
|
|
* Does not change skb->protocol so this function can be used during receive.
|
|
|
*/
|
|
|
-static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
|
|
|
- __be16 vlan_proto, u16 vlan_tci)
|
|
|
+static inline struct sk_buff *vlan_insert_inner_tag(struct sk_buff *skb,
|
|
|
+ __be16 vlan_proto,
|
|
|
+ u16 vlan_tci,
|
|
|
+ unsigned int mac_len)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- err = __vlan_insert_tag(skb, vlan_proto, vlan_tci);
|
|
|
+ err = __vlan_insert_inner_tag(skb, vlan_proto, vlan_tci, mac_len);
|
|
|
if (err) {
|
|
|
dev_kfree_skb_any(skb);
|
|
|
return NULL;
|
|
@@ -360,6 +384,26 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
|
|
|
return skb;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 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 a VLAN tagged skb. If a new skb is created, @skb is freed.
|
|
|
+ *
|
|
|
+ * Following the skb_unshare() example, in case of error, the calling function
|
|
|
+ * doesn't have to worry about freeing the original skb.
|
|
|
+ *
|
|
|
+ * Does not change skb->protocol so this function can be used during receive.
|
|
|
+ */
|
|
|
+static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
|
|
|
+ __be16 vlan_proto, u16 vlan_tci)
|
|
|
+{
|
|
|
+ return vlan_insert_inner_tag(skb, vlan_proto, vlan_tci, ETH_HLEN);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* vlan_insert_tag_set_proto - regular VLAN tag inserting
|
|
|
* @skb: skbuff to tag
|