datapath: Fix few mpls issues.
[cascardo/ovs.git] / datapath / linux / compat / gso.h
1 #ifndef __LINUX_GSO_WRAPPER_H
2 #define __LINUX_GSO_WRAPPER_H
3
4 #include <linux/version.h>
5 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
6
7 #include <linux/netdevice.h>
8 #include <linux/skbuff.h>
9 #include <net/protocol.h>
10
11 #include "datapath.h"
12
13 struct ovs_gso_cb {
14         struct ovs_skb_cb dp_cb;
15         void (*fix_segment)(struct sk_buff *);
16         sk_buff_data_t  inner_mac_header;       /* Offset from skb->head */
17 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
18         __be16          inner_protocol;
19 #endif
20         u16             inner_network_header;   /* Offset from
21                                                  * inner_mac_header */
22 };
23 #define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)->cb)
24
25 #define skb_inner_network_header rpl_skb_inner_network_header
26
27 #ifdef NET_SKBUFF_DATA_USES_OFFSET
28 #define skb_inner_mac_header rpl_skb_inner_mac_header
29 static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
30 {
31         return skb->head + OVS_GSO_CB(skb)->inner_mac_header;
32 }
33
34 #else
35
36 #define skb_inner_mac_header rpl_skb_inner_mac_header
37 static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
38 {
39         return OVS_GSO_CB(skb)->inner_mac_header;
40 }
41
42 #endif
43
44 #define skb_inner_network_header rpl_skb_inner_network_header
45 static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
46 {
47         return skb_inner_mac_header(skb) +
48                 OVS_GSO_CB(skb)->inner_network_header;
49 }
50
51 #define skb_inner_network_offset rpl_skb_inner_network_offset
52 static inline int skb_inner_network_offset(const struct sk_buff *skb)
53 {
54         return skb_inner_network_header(skb) - skb->data;
55 }
56
57 #define skb_reset_inner_headers rpl_skb_reset_inner_headers
58 static inline void skb_reset_inner_headers(struct sk_buff *skb)
59 {
60         BUILD_BUG_ON(sizeof(struct ovs_gso_cb) > FIELD_SIZEOF(struct sk_buff, cb));
61         OVS_GSO_CB(skb)->inner_network_header = skb->network_header -
62                 skb->mac_header;
63         OVS_GSO_CB(skb)->inner_mac_header = skb->mac_header;
64
65         OVS_GSO_CB(skb)->fix_segment = NULL;
66 }
67
68 #endif /* 3.12 */
69
70 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
71 #define ip_local_out rpl_ip_local_out
72 int ip_local_out(struct sk_buff *skb);
73
74 #define skb_inner_mac_offset rpl_skb_inner_mac_offset
75 static inline int skb_inner_mac_offset(const struct sk_buff *skb)
76 {
77         return skb_inner_mac_header(skb) - skb->data;
78 }
79 #endif /* 3.16 */
80
81 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
82 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
83         OVS_GSO_CB(skb)->inner_protocol = htons(0);
84 }
85
86 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
87                                               __be16 ethertype) {
88         OVS_GSO_CB(skb)->inner_protocol = ethertype;
89 }
90
91 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
92 {
93         return OVS_GSO_CB(skb)->inner_protocol;
94 }
95
96 #else
97
98 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
99         /* Nothing to do. The inner_protocol is either zero or
100          * has been set to a value by another user.
101          * Either way it may be considered initialised.
102          */
103 }
104
105 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
106 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
107                                               __be16 ethertype)
108 {
109         skb->inner_protocol = ethertype;
110 }
111 #else
112 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
113                                               __be16 ethertype)
114 {
115         skb_set_inner_protocol(skb, ethertype);
116 }
117 #endif
118
119 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
120 {
121         return skb->inner_protocol;
122 }
123 #endif /* 3.11 */
124 #endif