netdev
[Top] [All Lists]

[PATCH 2/6][8021q][2.6] Export VLAN tag get/set functionality

To: netdev@xxxxxxxxxxx, bonding-devel@xxxxxxxxxxxxxxxxxxxxx
Subject: [PATCH 2/6][8021q][2.6] Export VLAN tag get/set functionality
From: Shmuel Hen <shmulik.hen@xxxxxxxxx>
Date: Thu, 22 Jan 2004 17:59:52 +0200
Organization: Intel Corporation
Sender: netdev-bounce@xxxxxxxxxxx
User-agent: KMail/1.5
Enable intermediate network drivers like bonding to get or set a
VLAN tag in an skb without a need to know about how tagging is done
according to a network adapter's capabilities.


diff -Nuarp a/include/linux/if_vlan.h b/include/linux/if_vlan.h
--- a/include/linux/if_vlan.h   Wed Jan 21 16:56:09 2004
+++ b/include/linux/if_vlan.h   Wed Jan 21 16:56:11 2004
@@ -200,6 +200,152 @@ static inline int vlan_hwaccel_receive_s
 {
        return __vlan_hwaccel_rx(skb, grp, vlan_tag, 1);
 }
+
+/**
+ * __vlan_put_tag - regular VLAN tag inserting
+ * @skb: skbuff to tag
+ * @tag: VLAN tag 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.
+ */
+static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, unsigned 
short tag)
+{
+       struct vlan_ethhdr *veth;
+
+       if (skb_headroom(skb) < VLAN_HLEN) {
+               struct sk_buff *sk_tmp = skb;
+               skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
+               kfree_skb(sk_tmp);
+               if (!skb) {
+                       printk(KERN_ERR "vlan: failed to realloc headroom\n");
+                       return NULL;
+               }
+       } else {
+               skb = skb_unshare(skb, GFP_ATOMIC);
+               if (!skb) {
+                       printk(KERN_ERR "vlan: failed to unshare skbuff\n");
+                       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 * VLAN_ETH_ALEN);
+
+       /* first, the ethernet type */
+       veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
+
+       /* now, the tag */
+       veth->h_vlan_TCI = htons(tag);
+
+       skb->protocol = __constant_htons(ETH_P_8021Q);
+       skb->mac.raw -= VLAN_HLEN;
+       skb->nh.raw -= VLAN_HLEN;
+
+       return skb;
+}
+
+/**
+ * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
+ * @skb: skbuff to tag
+ * @tag: VLAN tag to insert
+ *
+ * Puts the VLAN tag in @skb->cb[] and lets the device do the rest
+ */
+static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, 
unsigned short tag)
+{
+       struct vlan_skb_tx_cookie *cookie;
+
+       cookie = VLAN_TX_SKB_CB(skb);
+       cookie->magic = VLAN_TX_COOKIE_MAGIC;
+       cookie->vlan_tag = tag;
+
+       return skb;
+}
+
+#define HAVE_VLAN_PUT_TAG
+
+/**
+ * vlan_put_tag - inserts VLAN tag according to device features
+ * @skb: skbuff to tag
+ * @tag: VLAN tag to insert
+ *
+ * Assumes skb->dev is the target that will xmit this frame.
+ * Returns a VLAN tagged skb.
+ */
+static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, unsigned short 
tag)
+{
+       if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
+               return __vlan_hwaccel_put_tag(skb, tag);
+       } else {
+               return __vlan_put_tag(skb, tag);
+       }
+}
+
+/**
+ * __vlan_get_tag - get the VLAN ID that is part of the payload
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if the skb is not of VLAN type
+ */
+static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+{
+       struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
+
+       if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
+               return -EINVAL;
+       }
+
+       *tag = ntohs(veth->h_vlan_TCI);
+
+       return 0;
+}
+
+/**
+ * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if @skb->cb[] is not set correctly
+ */
+static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short 
*tag)
+{
+       struct vlan_skb_tx_cookie *cookie;
+
+       cookie = VLAN_TX_SKB_CB(skb);
+       if (cookie->magic == VLAN_TX_COOKIE_MAGIC) {
+               *tag = cookie->vlan_tag;
+               return 0;
+       } else {
+               *tag = 0;
+               return -EINVAL;
+       }
+}
+
+#define HAVE_VLAN_GET_TAG
+
+/**
+ * vlan_get_tag - get the VLAN ID from the skb
+ * @skb: skbuff to query
+ * @tag: buffer to store vlaue
+ * 
+ * Returns error if the skb is not VLAN tagged
+ */
+static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+{
+       if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
+               return __vlan_hwaccel_get_tag(skb, tag);
+       } else {
+               return __vlan_get_tag(skb, tag);
+       }
+}
+
 #endif /* __KERNEL__ */
 
 /* VLAN IOCTLs are found in sockios.h */


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH 2/6][8021q][2.6] Export VLAN tag get/set functionality, Shmuel Hen <=