datapath: compat: introduce ovs_iptunnel_handle_offloads()
[cascardo/ovs.git] / datapath / linux / compat / gso.c
1 /*
2  * Copyright (c) 2007-2013 Nicira, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16  * 02110-1301, USA
17  */
18
19 #include <linux/version.h>
20 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
21
22 #include <linux/module.h>
23 #include <linux/if.h>
24 #include <linux/if_tunnel.h>
25 #include <linux/if_vlan.h>
26 #include <linux/icmp.h>
27 #include <linux/in.h>
28 #include <linux/ip.h>
29 #include <linux/kernel.h>
30 #include <linux/kmod.h>
31 #include <linux/netdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/spinlock.h>
34
35 #include <net/gre.h>
36 #include <net/icmp.h>
37 #include <net/mpls.h>
38 #include <net/protocol.h>
39 #include <net/route.h>
40 #include <net/xfrm.h>
41
42 #include "gso.h"
43 #include "vlan.h"
44
45 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) && \
46         !defined(HAVE_VLAN_BUG_WORKAROUND)
47 #include <linux/module.h>
48
49 static int vlan_tso __read_mostly;
50 module_param(vlan_tso, int, 0644);
51 MODULE_PARM_DESC(vlan_tso, "Enable TSO for VLAN packets");
52 #else
53 #define vlan_tso true
54 #endif
55
56 static bool dev_supports_vlan_tx(struct net_device *dev)
57 {
58 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
59         return true;
60 #elif defined(HAVE_VLAN_BUG_WORKAROUND)
61         return dev->features & NETIF_F_HW_VLAN_TX;
62 #else
63         /* Assume that the driver is buggy. */
64         return false;
65 #endif
66 }
67
68 /* Strictly this is not needed and will be optimised out
69  * as this code is guarded by if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0).
70  * It is here to make things explicit should the compatibility
71  * code be extended in some way prior extending its life-span
72  * beyond v3.16.
73  */
74 static bool supports_mpls_gso(void)
75 {
76 /* MPLS GSO was introduced in v3.11, however it was not correctly
77  * activated using mpls_features until v3.16. */
78 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
79         return true;
80 #else
81         return false;
82 #endif
83 }
84
85 int rpl_dev_queue_xmit(struct sk_buff *skb)
86 {
87 #undef dev_queue_xmit
88         int err = -ENOMEM;
89         bool vlan, mpls;
90
91         vlan = mpls = false;
92
93         /* Avoid traversing any VLAN tags that are present to determine if
94          * the ethtype is MPLS. Instead compare the mac_len (end of L2) and
95          * skb_network_offset() (beginning of L3) whose inequality will
96          * indicate the presence of an MPLS label stack. */
97         if (skb->mac_len != skb_network_offset(skb) && !supports_mpls_gso())
98                 mpls = true;
99
100         if (vlan_tx_tag_present(skb) && !dev_supports_vlan_tx(skb->dev))
101                 vlan = true;
102
103         if (vlan || mpls) {
104                 int features;
105
106                 features = netif_skb_features(skb);
107
108                 if (vlan) {
109                         if (!vlan_tso)
110                                 features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
111                                               NETIF_F_UFO | NETIF_F_FSO);
112
113                         skb = __vlan_put_tag(skb, skb->vlan_proto,
114                                              vlan_tx_tag_get(skb));
115                         if (unlikely(!skb))
116                                 return err;
117                         vlan_set_tci(skb, 0);
118                 }
119
120                 /* As of v3.11 the kernel provides an mpls_features field in
121                  * struct net_device which allows devices to advertise which
122                  * features its supports for MPLS. This value defaults to
123                  * NETIF_F_SG and as of v3.16.
124                  *
125                  * This compatibility code is intended for kernels older
126                  * than v3.16 that do not support MPLS GSO and do not
127                  * use mpls_features. Thus this code uses NETIF_F_SG
128                  * directly in place of mpls_features.
129                  */
130                 if (mpls)
131                         features &= NETIF_F_SG;
132
133                 if (netif_needs_gso(skb, features)) {
134                         struct sk_buff *nskb;
135
136                         nskb = skb_gso_segment(skb, features);
137                         if (!nskb) {
138                                 if (unlikely(skb_cloned(skb) &&
139                                     pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
140                                         goto drop;
141
142                                 skb_shinfo(skb)->gso_type &= ~SKB_GSO_DODGY;
143                                 goto xmit;
144                         }
145
146                         if (IS_ERR(nskb)) {
147                                 err = PTR_ERR(nskb);
148                                 goto drop;
149                         }
150                         consume_skb(skb);
151                         skb = nskb;
152
153                         do {
154                                 nskb = skb->next;
155                                 skb->next = NULL;
156                                 err = dev_queue_xmit(skb);
157                                 skb = nskb;
158                         } while (skb);
159
160                         return err;
161                 }
162         }
163 xmit:
164         return dev_queue_xmit(skb);
165
166 drop:
167         kfree_skb(skb);
168         return err;
169 }
170
171 static __be16 __skb_network_protocol(struct sk_buff *skb)
172 {
173         __be16 type = skb->protocol;
174         int vlan_depth = ETH_HLEN;
175
176         while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
177                 struct vlan_hdr *vh;
178
179                 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
180                         return 0;
181
182                 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
183                 type = vh->h_vlan_encapsulated_proto;
184                 vlan_depth += VLAN_HLEN;
185         }
186
187         if (eth_p_mpls(type))
188                 type = ovs_skb_get_inner_protocol(skb);
189
190         return type;
191 }
192
193 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
194 static void tnl_fix_segment(struct sk_buff *skb)
195 {
196         if (OVS_GSO_CB(skb)->fix_segment)
197                 OVS_GSO_CB(skb)->fix_segment(skb);
198 }
199 #else
200 static void tnl_fix_segment(struct sk_buff *skb) { }
201 #endif
202
203 static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
204                                            netdev_features_t features,
205                                            bool tx_path)
206 {
207         struct iphdr *iph = ip_hdr(skb);
208         int pkt_hlen = skb_inner_network_offset(skb); /* inner l2 + tunnel hdr. */
209         int mac_offset = skb_inner_mac_offset(skb);
210         struct sk_buff *skb1 = skb;
211         struct sk_buff *segs;
212         __be16 proto = skb->protocol;
213         char cb[sizeof(skb->cb)];
214
215         /* setup whole inner packet to get protocol. */
216         __skb_pull(skb, mac_offset);
217         skb->protocol = __skb_network_protocol(skb);
218
219         /* setup l3 packet to gso, to get around segmentation bug on older kernel.*/
220         __skb_pull(skb, (pkt_hlen - mac_offset));
221         skb_reset_mac_header(skb);
222         skb_reset_network_header(skb);
223         skb_reset_transport_header(skb);
224
225         /* From 3.9 kernel skb->cb is used by skb gso. Therefore
226          * make copy of it to restore it back. */
227         memcpy(cb, skb->cb, sizeof(cb));
228
229         segs = __skb_gso_segment(skb, 0, tx_path);
230         if (!segs || IS_ERR(segs))
231                 goto free;
232
233         skb = segs;
234         while (skb) {
235                 __skb_push(skb, pkt_hlen);
236                 skb_reset_mac_header(skb);
237                 skb_reset_network_header(skb);
238                 skb_set_transport_header(skb, sizeof(struct iphdr));
239                 skb->mac_len = 0;
240
241                 memcpy(ip_hdr(skb), iph, pkt_hlen);
242                 memcpy(skb->cb, cb, sizeof(cb));
243                 tnl_fix_segment(skb);
244
245                 skb->protocol = proto;
246                 skb = skb->next;
247         }
248 free:
249         consume_skb(skb1);
250         return segs;
251 }
252
253 int rpl_ip_local_out(struct sk_buff *skb)
254 {
255         int ret = NETDEV_TX_OK;
256         int id = -1;
257
258         if (skb_is_gso(skb)) {
259                 struct iphdr *iph;
260
261                 iph = ip_hdr(skb);
262                 id = ntohs(iph->id);
263                 skb = tnl_skb_gso_segment(skb, 0, false);
264                 if (!skb || IS_ERR(skb))
265                         return 0;
266         }  else if (skb->ip_summed == CHECKSUM_PARTIAL) {
267                 int err;
268
269                 err = skb_checksum_help(skb);
270                 if (unlikely(err))
271                         return 0;
272         }
273
274         while (skb) {
275                 struct sk_buff *next_skb = skb->next;
276                 struct iphdr *iph;
277                 int err;
278
279                 skb->next = NULL;
280
281                 iph = ip_hdr(skb);
282                 if (id >= 0)
283                         iph->id = htons(id++);
284
285                 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
286
287 #undef ip_local_out
288                 err = ip_local_out(skb);
289                 if (unlikely(net_xmit_eval(err)))
290                         ret = err;
291
292                 skb = next_skb;
293         }
294         return ret;
295 }
296 #endif /* 3.16 */
297
298 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
299 struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
300                                              bool csum_help,
301                                              void (*fix_segment)(struct sk_buff *))
302 {
303         int err;
304
305         /* XXX: synchronize inner header reset for compat and non compat code
306          * so that we can do it here.
307          */
308         /*
309          skb_reset_inner_headers(skb);
310          */
311
312         /* OVS compat code does not maintain encapsulation bit.
313          * skb->encapsulation = 1; */
314
315         if (skb_is_gso(skb)) {
316                 if (skb_is_encapsulated(skb)) {
317                         err = -ENOSYS;
318                         goto error;
319                 }
320
321                 OVS_GSO_CB(skb)->fix_segment = fix_segment;
322                 return skb;
323         }
324
325         /* If packet is not gso and we are resolving any partial checksum,
326          * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL
327          * on the outer header without confusing devices that implement
328          * NETIF_F_IP_CSUM with encapsulation.
329          */
330         /*
331         if (csum_help)
332                 skb->encapsulation = 0;
333         */
334
335         if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) {
336                 err = skb_checksum_help(skb);
337                 if (unlikely(err))
338                         goto error;
339         } else if (skb->ip_summed != CHECKSUM_PARTIAL)
340                 skb->ip_summed = CHECKSUM_NONE;
341
342         return skb;
343 error:
344         kfree_skb(skb);
345         return ERR_PTR(err);
346 }
347 #endif /* 3.12 */