1 #ifndef __LINUX_IF_VLAN_WRAPPER_H
2 #define __LINUX_IF_VLAN_WRAPPER_H 1
4 #include <linux/skbuff.h>
5 #include <linux/version.h>
6 #include_next <linux/if_vlan.h>
8 #ifndef HAVE_VLAN_INSERT_TAG_SET_PROTO
10 * The behavior of __vlan_put_tag()/vlan_insert_tag_set_proto() has changed
13 * - In 2.6.26 and earlier, it adjusted both MAC and network header
14 * pointers. (The latter didn't make any sense.)
16 * - In 2.6.27 and 2.6.28, it did not adjust any header pointers at all.
18 * - In 2.6.29 and later, it adjusts the MAC header pointer only.
20 * - In 3.19 and later, it was renamed to vlan_insert_tag_set_proto()
22 * This is the version from 2.6.33. We unconditionally substitute this version
23 * to avoid the need to guess whether the version in the kernel tree is
26 #define vlan_insert_tag_set_proto(skb, proto, vlan_tci) \
27 rpl_vlan_insert_tag_set_proto(skb, vlan_tci)
28 static inline struct sk_buff *rpl_vlan_insert_tag_set_proto(struct sk_buff *skb,
31 struct vlan_ethhdr *veth;
33 if (skb_cow_head(skb, VLAN_HLEN) < 0) {
37 veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
39 /* Move the mac addresses to the beginning of the new header. */
40 memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
41 skb->mac_header -= VLAN_HLEN;
43 /* first, the ethernet type */
44 veth->h_vlan_proto = htons(ETH_P_8021Q);
47 veth->h_vlan_TCI = htons(vlan_tci);
49 skb->protocol = htons(ETH_P_8021Q);
55 #ifndef HAVE_VLAN_HWACCEL_PUSH_INSIDE
58 * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
61 * Pushes the VLAN tag from @skb->vlan_tci inside to the payload.
63 * Following the skb_unshare() example, in case of error, the calling function
64 * doesn't have to worry about freeing the original skb.
66 static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb)
68 skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
69 vlan_tx_tag_get(skb));
75 * vlan_hwaccel_push_inside - pushes vlan tag to the payload
78 * Checks is tag is present in @skb->vlan_tci and if it is, it pushes the
79 * VLAN tag from @skb->vlan_tci inside to the payload.
81 * Following the skb_unshare() example, in case of error, the calling function
82 * doesn't have to worry about freeing the original skb.
84 static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb)
86 if (vlan_tx_tag_present(skb))
87 skb = __vlan_hwaccel_push_inside(skb);
92 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
93 static inline struct sk_buff *rpl___vlan_hwaccel_put_tag(struct sk_buff *skb,
97 return __vlan_hwaccel_put_tag(skb, vlan_tci);
100 #define __vlan_hwaccel_put_tag rpl___vlan_hwaccel_put_tag
103 /* All of these were introduced in a single commit preceding 2.6.33, so
104 * presumably all of them or none of them are present. */
105 #ifndef VLAN_PRIO_MASK
106 #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
107 #define VLAN_PRIO_SHIFT 13
108 #define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
109 #define VLAN_TAG_PRESENT VLAN_CFI_MASK
112 #ifndef HAVE_VLAN_SET_ENCAP_PROTO
113 static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr)
119 * Was a VLAN packet, grab the encapsulated protocol, which the layer
120 * three protocols care about.
123 proto = vhdr->h_vlan_encapsulated_proto;
124 if (ntohs(proto) >= 1536) {
125 skb->protocol = proto;
130 if (*(unsigned short *) rawp == 0xFFFF)
132 * This is a magic hack to spot IPX packets. Older Novell
133 * breaks the protocol design and runs IPX over 802.3 without
134 * an 802.2 LLC layer. We look for FFFF which isn't a used
135 * 802.2 SSAP/DSAP. This won't work for fault tolerant netware
136 * but does for the rest.
138 skb->protocol = htons(ETH_P_802_3);
143 skb->protocol = htons(ETH_P_802_2);
147 #ifndef HAVE___VLAN_INSERT_TAG
148 /* Kernels which don't have __vlan_insert_tag() also don't have skb->vlan_proto
149 * so ignore the proto paramter.
151 #define __vlan_insert_tag(skb, proto, tci) rpl_vlan_insert_tag(skb, tci)
152 static inline int rpl_vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci)
154 struct vlan_ethhdr *veth;
156 if (skb_cow_head(skb, VLAN_HLEN) < 0)
159 veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
161 /* Move the mac addresses to the beginning of the new header. */
162 memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
163 skb->mac_header -= VLAN_HLEN;
165 /* first, the ethernet type */
166 veth->h_vlan_proto = htons(ETH_P_8021Q);
169 veth->h_vlan_TCI = htons(vlan_tci);
175 #ifndef skb_vlan_tag_present
176 #define skb_vlan_tag_present(skb) vlan_tx_tag_present(skb)
177 #define skb_vlan_tag_get(skb) vlan_tx_tag_get(skb)
180 #ifndef HAVE_VLAN_GET_PROTOCOL
182 static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
185 unsigned int vlan_depth = skb->mac_len;
187 /* if type is 802.1Q/AD then the header should already be
188 * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
191 if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
193 if (WARN_ON(vlan_depth < VLAN_HLEN))
195 vlan_depth -= VLAN_HLEN;
197 vlan_depth = ETH_HLEN;
202 if (unlikely(!pskb_may_pull(skb,
203 vlan_depth + VLAN_HLEN)))
206 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
207 type = vh->h_vlan_encapsulated_proto;
208 vlan_depth += VLAN_HLEN;
209 } while (type == htons(ETH_P_8021Q) ||
210 type == htons(ETH_P_8021AD));
220 * vlan_get_protocol - get protocol EtherType.
221 * @skb: skbuff to query
223 * Returns the EtherType of the packet, regardless of whether it is
224 * vlan encapsulated (normal or hardware accelerated) or not.
226 static inline __be16 vlan_get_protocol(struct sk_buff *skb)
228 return __vlan_get_protocol(skb, skb->protocol, NULL);
232 #endif /* linux/if_vlan.h wrapper */