datapath: Add support for lwtunnel
[cascardo/ovs.git] / datapath / linux / compat / include / linux / if_vlan.h
1 #ifndef __LINUX_IF_VLAN_WRAPPER_H
2 #define __LINUX_IF_VLAN_WRAPPER_H 1
3
4 #include <linux/skbuff.h>
5 #include <linux/version.h>
6 #include_next <linux/if_vlan.h>
7
8 #ifndef HAVE_VLAN_INSERT_TAG_SET_PROTO
9 /*
10  * The behavior of __vlan_put_tag()/vlan_insert_tag_set_proto() has changed
11  * over time:
12  *
13  *      - In 2.6.26 and earlier, it adjusted both MAC and network header
14  *        pointers.  (The latter didn't make any sense.)
15  *
16  *      - In 2.6.27 and 2.6.28, it did not adjust any header pointers at all.
17  *
18  *      - In 2.6.29 and later, it adjusts the MAC header pointer only.
19  *
20  *      - In 3.19 and later, it was renamed to vlan_insert_tag_set_proto()
21  *
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
24  * acceptable.
25  */
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,
29                                                             u16 vlan_tci)
30 {
31         struct vlan_ethhdr *veth;
32
33         if (skb_cow_head(skb, VLAN_HLEN) < 0) {
34                 kfree_skb(skb);
35                 return NULL;
36         }
37         veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
38
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;
42
43         /* first, the ethernet type */
44         veth->h_vlan_proto = htons(ETH_P_8021Q);
45
46         /* now, the TCI */
47         veth->h_vlan_TCI = htons(vlan_tci);
48
49         skb->protocol = htons(ETH_P_8021Q);
50
51         return skb;
52 }
53 #endif
54
55 #ifndef HAVE_VLAN_HWACCEL_PUSH_INSIDE
56
57 /*
58  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
59  * @skb: skbuff to tag
60  *
61  * Pushes the VLAN tag from @skb->vlan_tci inside to the payload.
62  *
63  * Following the skb_unshare() example, in case of error, the calling function
64  * doesn't have to worry about freeing the original skb.
65  */
66 static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb)
67 {
68         skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
69                                         vlan_tx_tag_get(skb));
70         if (likely(skb))
71                 skb->vlan_tci = 0;
72         return skb;
73 }
74 /*
75  * vlan_hwaccel_push_inside - pushes vlan tag to the payload
76  * @skb: skbuff to tag
77  *
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.
80  *
81  * Following the skb_unshare() example, in case of error, the calling function
82  * doesn't have to worry about freeing the original skb.
83  */
84 static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb)
85 {
86         if (vlan_tx_tag_present(skb))
87                 skb = __vlan_hwaccel_push_inside(skb);
88         return skb;
89 }
90 #endif
91
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,
94                                                      __be16 vlan_proto,
95                                                      u16 vlan_tci)
96 {
97         return __vlan_hwaccel_put_tag(skb, vlan_tci);
98 }
99
100 #define __vlan_hwaccel_put_tag rpl___vlan_hwaccel_put_tag
101 #endif
102
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
110 #endif
111
112 #ifndef HAVE_VLAN_SET_ENCAP_PROTO
113 static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr)
114 {
115         __be16 proto;
116         unsigned char *rawp;
117
118         /*
119          * Was a VLAN packet, grab the encapsulated protocol, which the layer
120          * three protocols care about.
121          */
122
123         proto = vhdr->h_vlan_encapsulated_proto;
124         if (ntohs(proto) >= 1536) {
125                 skb->protocol = proto;
126                 return;
127         }
128
129         rawp = skb->data;
130         if (*(unsigned short *) rawp == 0xFFFF)
131                 /*
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.
137                  */
138                 skb->protocol = htons(ETH_P_802_3);
139         else
140                 /*
141                  * Real 802.2 LLC
142                  */
143                 skb->protocol = htons(ETH_P_802_2);
144 }
145 #endif
146
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.
150  */
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)
153 {
154         struct vlan_ethhdr *veth;
155
156         if (skb_cow_head(skb, VLAN_HLEN) < 0)
157                 return -ENOMEM;
158
159         veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
160
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;
164
165         /* first, the ethernet type */
166         veth->h_vlan_proto = htons(ETH_P_8021Q);
167
168         /* now, the TCI */
169         veth->h_vlan_TCI = htons(vlan_tci);
170
171         return 0;
172 }
173 #endif
174
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)
178 #endif
179
180 #ifndef HAVE_VLAN_GET_PROTOCOL
181
182 static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
183                                          int *depth)
184 {
185         unsigned int vlan_depth = skb->mac_len;
186
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
189          * ETH_HLEN otherwise
190          */
191         if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
192                 if (vlan_depth) {
193                         if (WARN_ON(vlan_depth < VLAN_HLEN))
194                                 return 0;
195                         vlan_depth -= VLAN_HLEN;
196                 } else {
197                         vlan_depth = ETH_HLEN;
198                 }
199                 do {
200                         struct vlan_hdr *vh;
201
202                         if (unlikely(!pskb_may_pull(skb,
203                                                     vlan_depth + VLAN_HLEN)))
204                                 return 0;
205
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));
211         }
212
213         if (depth)
214                 *depth = vlan_depth;
215
216         return type;
217 }
218
219 /**
220  * vlan_get_protocol - get protocol EtherType.
221  * @skb: skbuff to query
222  *
223  * Returns the EtherType of the packet, regardless of whether it is
224  * vlan encapsulated (normal or hardware accelerated) or not.
225  */
226 static inline __be16 vlan_get_protocol(struct sk_buff *skb)
227 {
228         return __vlan_get_protocol(skb, skb->protocol, NULL);
229 }
230
231 #endif
232 #endif  /* linux/if_vlan.h wrapper */