From: Shmuel Hen <shmulik.hen@intel.com>
To: "David S. Miller" <davem@redhat.com>
Cc: <netdev@oss.sgi.com>, "Jeff Garzik" <jgarzik@pobox.com>
Subject: [PATCH] [8021q] Export VLAN tag get/set functionality (resend)
Date: Thu, 5 Feb 2004 15:59:22 +0200 [thread overview]
Message-ID: <200402051559.27597.shmulik.hen@intel.com> (raw)
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.
Tested for patch application and compilation against linux-2.6.2.
--
| Shmulik Hen Advanced Network Services |
| Israel Design Center, Jerusalem |
| LAN Access Division, Platform Networking |
| Intel Communications Group, Intel corp. |
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 */
next reply other threads:[~2004-02-05 13:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-05 13:59 Shmuel Hen [this message]
2004-02-07 0:25 ` [PATCH] [8021q] Export VLAN tag get/set functionality (resend) David S. Miller
-- strict thread matches above, loose matches on Subject: below --
2004-02-05 14:24 Shmuel Hen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200402051559.27597.shmulik.hen@intel.com \
--to=shmulik.hen@intel.com \
--cc=davem@redhat.com \
--cc=jgarzik@pobox.com \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.