datapath: Add Stateless TCP Tunneling protocol.
[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,18,0)
6
7 #include <linux/netdevice.h>
8 #include <linux/skbuff.h>
9 #include <net/protocol.h>
10
11 #include "datapath.h"
12 typedef void (*gso_fix_segment_t)(struct sk_buff *);
13
14 struct ovs_gso_cb {
15         struct ovs_skb_cb dp_cb;
16         gso_fix_segment_t fix_segment;
17 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
18         __be16          inner_protocol;
19 #endif
20 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
21         unsigned int    inner_mac_header;
22 #endif
23 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
24         unsigned int    inner_network_header;
25 #endif
26 };
27 #define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)->cb)
28
29 static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
30 {
31         OVS_GSO_CB(skb)->fix_segment = NULL;
32 }
33 #else
34 static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
35 {
36
37 }
38 #endif
39
40 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
41 static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
42 {
43         return skb->head + OVS_GSO_CB(skb)->inner_mac_header;
44 }
45
46 static inline void skb_set_inner_mac_header(const struct sk_buff *skb,
47                                             int offset)
48 {
49         OVS_GSO_CB(skb)->inner_mac_header = (skb->data - skb->head) + offset;
50 }
51 #endif
52
53 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
54 static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
55 {
56         return skb->head + OVS_GSO_CB(skb)->inner_network_header;
57 }
58
59 static inline int skb_inner_network_offset(const struct sk_buff *skb)
60 {
61         return skb_inner_network_header(skb) - skb->data;
62 }
63
64 /* We don't actually store the transport offset on backports because
65  * we don't use it anywhere. Slightly rename this version to avoid
66  * future users from picking it up accidentially.
67  */
68 static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
69 {
70         return 0;
71 }
72
73 static inline void skb_set_inner_network_header(const struct sk_buff *skb,
74                                                 int offset)
75 {
76         OVS_GSO_CB(skb)->inner_network_header = (skb->data - skb->head)
77                                                 + offset;
78 }
79
80 static inline void skb_set_inner_transport_header(const struct sk_buff *skb,
81                                                   int offset)
82 { }
83
84 #else
85
86 static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
87 {
88         return skb_inner_transport_header(skb) - skb->data;
89 }
90
91 #endif
92
93 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
94 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
95         OVS_GSO_CB(skb)->inner_protocol = htons(0);
96 }
97
98 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
99                                               __be16 ethertype) {
100         OVS_GSO_CB(skb)->inner_protocol = ethertype;
101 }
102
103 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
104 {
105         return OVS_GSO_CB(skb)->inner_protocol;
106 }
107
108 #else
109
110 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
111         /* Nothing to do. The inner_protocol is either zero or
112          * has been set to a value by another user.
113          * Either way it may be considered initialised.
114          */
115 }
116
117 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
118 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
119                                               __be16 ethertype)
120 {
121         skb->inner_protocol = ethertype;
122 }
123 #else
124 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
125                                               __be16 ethertype)
126 {
127         skb_set_inner_protocol(skb, ethertype);
128 }
129 #endif
130
131 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
132 {
133         return skb->inner_protocol;
134 }
135 #endif /* 3.11 */
136
137 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
138 #define ip_local_out rpl_ip_local_out
139 int rpl_ip_local_out(struct sk_buff *skb);
140
141 static inline int skb_inner_mac_offset(const struct sk_buff *skb)
142 {
143         return skb_inner_mac_header(skb) - skb->data;
144 }
145
146 #define skb_reset_inner_headers rpl_skb_reset_inner_headers
147 static inline void skb_reset_inner_headers(struct sk_buff *skb)
148 {
149         BUILD_BUG_ON(sizeof(struct ovs_gso_cb) > FIELD_SIZEOF(struct sk_buff, cb));
150         skb_set_inner_mac_header(skb, skb_mac_header(skb) - skb->data);
151         skb_set_inner_network_header(skb, skb_network_offset(skb));
152         skb_set_inner_transport_header(skb, skb_transport_offset(skb));
153 }
154 #endif /* 3.18 */
155
156 #endif