2 * Copyright (c) 2011 Nicira Networks.
3 * Distributed under the terms of the GNU GPL version 2.
5 * Significant portions of this file may be copied from parts of the Linux
6 * kernel, by Linus Torvalds and others.
12 #include <linux/if_vlan.h>
13 #include <linux/skbuff.h>
14 #include <linux/version.h>
17 * DOC: VLAN tag manipulation.
19 * &struct sk_buff handling of VLAN tags has evolved over time:
21 * In 2.6.26 and earlier, VLAN tags did not have any generic representation in
22 * an skb, other than as a raw 802.1Q header inside the packet data.
24 * In 2.6.27 &struct sk_buff added a @vlan_tci member. Between 2.6.27 and
25 * 2.6.32, its value was the raw contents of the 802.1Q TCI field, or zero if
26 * no 802.1Q header was present. This worked OK except for the corner case of
27 * an 802.1Q header with an all-0-bits TCI, which could not be represented.
29 * In 2.6.33, @vlan_tci semantics changed. Now, if an 802.1Q header is
30 * present, then the VLAN_TAG_PRESENT bit is always set. This fixes the
31 * all-0-bits TCI corner case.
33 * For compatibility we emulate the 2.6.33+ behavior on earlier kernel
34 * versions. The client must not access @vlan_tci directly. Instead, use
35 * vlan_get_tci() to read it or vlan_set_tci() to write it, with semantics
36 * equivalent to those on 2.6.33+.
39 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
40 #define NEED_VLAN_FIELD
43 #ifndef NEED_VLAN_FIELD
44 static inline void vlan_copy_skb_tci(struct sk_buff *skb) { }
46 static inline u16 vlan_get_tci(struct sk_buff *skb)
48 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
50 return skb->vlan_tci | VLAN_TAG_PRESENT;
55 static inline void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci)
57 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
58 vlan_tci &= ~VLAN_TAG_PRESENT;
60 skb->vlan_tci = vlan_tci;
63 void vlan_copy_skb_tci(struct sk_buff *skb);
64 u16 vlan_get_tci(struct sk_buff *skb);
65 void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci);
67 #undef vlan_tx_tag_present
68 bool vlan_tx_tag_present(struct sk_buff *skb);
70 #undef vlan_tx_tag_get
71 u16 vlan_tx_tag_get(struct sk_buff *skb);
73 #define __vlan_hwaccel_put_tag rpl__vlan_hwaccel_put_tag
74 struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci);
75 #endif /* NEED_VLAN_FIELD */
77 static inline int vlan_deaccel_tag(struct sk_buff *skb)
79 if (!vlan_tx_tag_present(skb))
82 skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));