Merge lp:~moha/ubuntu/trusty/openvswitch/fix-for-1315306 into lp:ubuntu/trusty/openvswitch
- Trusty (14.04)
- fix-for-1315306
- Merge into trusty
Proposed by
Mohanjith
Status: | Work in progress |
---|---|
Proposed branch: | lp:~moha/ubuntu/trusty/openvswitch/fix-for-1315306 |
Merge into: | lp:ubuntu/trusty/openvswitch |
Diff against target: |
570 lines (+550/-0) 3 files modified
debian/changelog (+6/-0) debian/patches/1315306-gre-patch.patch (+543/-0) debian/patches/series (+1/-0) |
To merge this branch: | bzr merge lp:~moha/ubuntu/trusty/openvswitch/fix-for-1315306 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Needs Fixing | ||
Review via email: mp+218510@code.launchpad.net |
Commit message
Description of the change
When use gre vport, openvswitch register a gre_cisco_protocol but
does not supply a err_handler with it. The gre_cisco_err() in
net/ipv4/
gre_cisco_protocol implementation, and call ->err_handler() without
existence check, cause the kernel crash.
This patch provide a err_handler to fix this bug.
To post a comment you must log in.
Unmerged revisions
- 61. By Mohanjith Sudirikku Hannadige <email address hidden>
-
debian/
patches/ 1315306- gre-patch. patch: supply a dummy err_handler of gre_cisco_protocol to prevent kernel crash
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2014-02-23 13:49:27 +0000 |
3 | +++ debian/changelog 2014-05-06 21:06:26 +0000 |
4 | @@ -1,3 +1,9 @@ |
5 | +openvswitch (2.0.1+git20140120-0ubuntu3) UNRELEASED; urgency=medium |
6 | + |
7 | + * debian/patches/1315306-gre-patch.patch: supply a dummy err_handler of gre_cisco_protocol to prevent kernel crash |
8 | + |
9 | + -- Mohanjith Sudirikku Hannadige <moha@codemaster.fi> Tue, 06 May 2014 20:51:14 +0000 |
10 | + |
11 | openvswitch (2.0.1+git20140120-0ubuntu2) trusty; urgency=medium |
12 | |
13 | * Rebuild to drop files installed into /usr/share/pyshared. |
14 | |
15 | === added file 'debian/patches/1315306-gre-patch.patch' |
16 | --- debian/patches/1315306-gre-patch.patch 1970-01-01 00:00:00 +0000 |
17 | +++ debian/patches/1315306-gre-patch.patch 2014-05-06 21:06:26 +0000 |
18 | @@ -0,0 +1,543 @@ |
19 | +## Description: add some description |
20 | +## Origin/Author: add some origin or author |
21 | +## Bug: bug URL |
22 | +Index: openvswitch.moha/datapath/linux/compat/include/net/gre.h |
23 | +=================================================================== |
24 | +--- openvswitch.moha.orig/datapath/linux/compat/include/net/gre.h 2014-05-06 20:49:51.459706000 +0000 |
25 | ++++ openvswitch.moha/datapath/linux/compat/include/net/gre.h 2014-05-06 20:50:57.258957000 +0000 |
26 | +@@ -80,6 +80,8 @@ |
27 | + |
28 | + struct gre_cisco_protocol { |
29 | + int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi); |
30 | ++ int (*err_handler)(struct sk_buff *skb, u32 info, |
31 | ++ const struct tnl_ptk_info *tpi); |
32 | + u8 priority; |
33 | + }; |
34 | + |
35 | +Index: openvswitch.moha/datapath/linux/compat/include/net/gre.h.orig |
36 | +=================================================================== |
37 | +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
38 | ++++ openvswitch.moha/datapath/linux/compat/include/net/gre.h.orig 2014-05-06 20:49:51.459706000 +0000 |
39 | +@@ -0,0 +1,116 @@ |
40 | ++#ifndef __LINUX_GRE_WRAPPER_H |
41 | ++#define __LINUX_GRE_WRAPPER_H |
42 | ++ |
43 | ++#include <linux/skbuff.h> |
44 | ++#include <net/ip_tunnels.h> |
45 | ++ |
46 | ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) |
47 | ++#include_next <net/gre.h> |
48 | ++ |
49 | ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) */ |
50 | ++ |
51 | ++#define GREPROTO_CISCO 0 |
52 | ++#define GREPROTO_MAX 2 |
53 | ++ |
54 | ++struct gre_protocol { |
55 | ++ int (*handler)(struct sk_buff *skb); |
56 | ++}; |
57 | ++ |
58 | ++int gre_add_protocol(const struct gre_protocol *proto, u8 version); |
59 | ++int gre_del_protocol(const struct gre_protocol *proto, u8 version); |
60 | ++ |
61 | ++#endif |
62 | ++ |
63 | ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) |
64 | ++struct gre_base_hdr { |
65 | ++ __be16 flags; |
66 | ++ __be16 protocol; |
67 | ++}; |
68 | ++#define GRE_HEADER_SECTION 4 |
69 | ++ |
70 | ++static inline __be16 gre_flags_to_tnl_flags(__be16 flags) |
71 | ++{ |
72 | ++ __be16 tflags = 0; |
73 | ++ |
74 | ++ if (flags & GRE_CSUM) |
75 | ++ tflags |= TUNNEL_CSUM; |
76 | ++ if (flags & GRE_ROUTING) |
77 | ++ tflags |= TUNNEL_ROUTING; |
78 | ++ if (flags & GRE_KEY) |
79 | ++ tflags |= TUNNEL_KEY; |
80 | ++ if (flags & GRE_SEQ) |
81 | ++ tflags |= TUNNEL_SEQ; |
82 | ++ if (flags & GRE_STRICT) |
83 | ++ tflags |= TUNNEL_STRICT; |
84 | ++ if (flags & GRE_REC) |
85 | ++ tflags |= TUNNEL_REC; |
86 | ++ if (flags & GRE_VERSION) |
87 | ++ tflags |= TUNNEL_VERSION; |
88 | ++ |
89 | ++ return tflags; |
90 | ++} |
91 | ++ |
92 | ++static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) |
93 | ++{ |
94 | ++ __be16 flags = 0; |
95 | ++ |
96 | ++ if (tflags & TUNNEL_CSUM) |
97 | ++ flags |= GRE_CSUM; |
98 | ++ if (tflags & TUNNEL_ROUTING) |
99 | ++ flags |= GRE_ROUTING; |
100 | ++ if (tflags & TUNNEL_KEY) |
101 | ++ flags |= GRE_KEY; |
102 | ++ if (tflags & TUNNEL_SEQ) |
103 | ++ flags |= GRE_SEQ; |
104 | ++ if (tflags & TUNNEL_STRICT) |
105 | ++ flags |= GRE_STRICT; |
106 | ++ if (tflags & TUNNEL_REC) |
107 | ++ flags |= GRE_REC; |
108 | ++ if (tflags & TUNNEL_VERSION) |
109 | ++ flags |= GRE_VERSION; |
110 | ++ |
111 | ++ return flags; |
112 | ++} |
113 | ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */ |
114 | ++ |
115 | ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) |
116 | ++/* GRE demux not available, implement our own demux. */ |
117 | ++#define MAX_GRE_PROTO_PRIORITY 255 |
118 | ++#define gre_cisco_protocol rpl_gre_cisco_protocol |
119 | ++ |
120 | ++struct gre_cisco_protocol { |
121 | ++ int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi); |
122 | ++ u8 priority; |
123 | ++}; |
124 | ++ |
125 | ++#define gre_cisco_register rpl_gre_cisco_register |
126 | ++int gre_cisco_register(struct gre_cisco_protocol *proto); |
127 | ++ |
128 | ++#define gre_cisco_unregister rpl_gre_cisco_unregister |
129 | ++int gre_cisco_unregister(struct gre_cisco_protocol *proto); |
130 | ++ |
131 | ++#endif |
132 | ++ |
133 | ++#define gre_build_header rpl_gre_build_header |
134 | ++void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, |
135 | ++ int hdr_len); |
136 | ++ |
137 | ++#define gre_handle_offloads rpl_gre_handle_offloads |
138 | ++struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum); |
139 | ++ |
140 | ++#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen |
141 | ++static inline int ip_gre_calc_hlen(__be16 o_flags) |
142 | ++{ |
143 | ++ int addend = 4; |
144 | ++ |
145 | ++ if (o_flags & TUNNEL_CSUM) |
146 | ++ addend += 4; |
147 | ++ if (o_flags & TUNNEL_KEY) |
148 | ++ addend += 4; |
149 | ++ if (o_flags & TUNNEL_SEQ) |
150 | ++ addend += 4; |
151 | ++ return addend; |
152 | ++} |
153 | ++ |
154 | ++ |
155 | ++#endif |
156 | +Index: openvswitch.moha/datapath/vport-gre.c |
157 | +=================================================================== |
158 | +--- openvswitch.moha.orig/datapath/vport-gre.c 2014-05-06 20:49:51.459706000 +0000 |
159 | ++++ openvswitch.moha/datapath/vport-gre.c 2014-05-06 20:50:57.262957000 +0000 |
160 | +@@ -118,6 +118,25 @@ |
161 | + return PACKET_RCVD; |
162 | + } |
163 | + |
164 | ++/* Called with rcu_read_lock and BH disabled. */ |
165 | ++static int gre_err(struct sk_buff *skb, u32 info, |
166 | ++ const struct tnl_ptk_info *tpi) |
167 | ++{ |
168 | ++ struct ovs_net *ovs_net; |
169 | ++ struct vport *vport; |
170 | ++ |
171 | ++ ovs_net = net_generic(dev_net(skb->dev), ovs_net_id); |
172 | ++ if ((tpi->flags & TUNNEL_KEY) && (tpi->flags & TUNNEL_SEQ)) |
173 | ++ vport = rcu_dereference(ovs_net->vport_net.gre64_vport); |
174 | ++ else |
175 | ++ vport = rcu_dereference(ovs_net->vport_net.gre_vport); |
176 | ++ |
177 | ++ if (unlikely(!vport)) |
178 | ++ return PACKET_REJECT; |
179 | ++ else |
180 | ++ return PACKET_RCVD; |
181 | ++} |
182 | ++ |
183 | + static int __send(struct vport *vport, struct sk_buff *skb, |
184 | + int tunnel_hlen, |
185 | + __be32 seq, __be16 gre64_flag) |
186 | +@@ -190,6 +209,7 @@ |
187 | + |
188 | + static struct gre_cisco_protocol gre_protocol = { |
189 | + .handler = gre_rcv, |
190 | ++ .err_handler = gre_err, |
191 | + .priority = 1, |
192 | + }; |
193 | + |
194 | +Index: openvswitch.moha/datapath/vport-gre.c.orig |
195 | +=================================================================== |
196 | +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
197 | ++++ openvswitch.moha/datapath/vport-gre.c.orig 2014-05-06 20:49:51.459706000 +0000 |
198 | +@@ -0,0 +1,363 @@ |
199 | ++/* |
200 | ++ * Copyright (c) 2007-2012 Nicira, Inc. |
201 | ++ * |
202 | ++ * This program is free software; you can redistribute it and/or |
203 | ++ * modify it under the terms of version 2 of the GNU General Public |
204 | ++ * License as published by the Free Software Foundation. |
205 | ++ * |
206 | ++ * This program is distributed in the hope that it will be useful, but |
207 | ++ * WITHOUT ANY WARRANTY; without even the implied warranty of |
208 | ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
209 | ++ * General Public License for more details. |
210 | ++ * |
211 | ++ * You should have received a copy of the GNU General Public License |
212 | ++ * along with this program; if not, write to the Free Software |
213 | ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
214 | ++ * 02110-1301, USA |
215 | ++ */ |
216 | ++ |
217 | ++#include <linux/kconfig.h> |
218 | ++#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) |
219 | ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
220 | ++ |
221 | ++#include <linux/if.h> |
222 | ++#include <linux/skbuff.h> |
223 | ++#include <linux/ip.h> |
224 | ++#include <linux/if_tunnel.h> |
225 | ++#include <linux/if_vlan.h> |
226 | ++#include <linux/in.h> |
227 | ++#include <linux/if_vlan.h> |
228 | ++#include <linux/in.h> |
229 | ++#include <linux/in_route.h> |
230 | ++#include <linux/inetdevice.h> |
231 | ++#include <linux/jhash.h> |
232 | ++#include <linux/list.h> |
233 | ++#include <linux/kernel.h> |
234 | ++#include <linux/workqueue.h> |
235 | ++#include <linux/rculist.h> |
236 | ++#include <net/net_namespace.h> |
237 | ++#include <net/netns/generic.h> |
238 | ++#include <net/route.h> |
239 | ++#include <net/xfrm.h> |
240 | ++ |
241 | ++#include <net/icmp.h> |
242 | ++#include <net/ip.h> |
243 | ++#include <net/ip_tunnels.h> |
244 | ++#include <net/gre.h> |
245 | ++#include <net/protocol.h> |
246 | ++ |
247 | ++#include "datapath.h" |
248 | ++#include "vport.h" |
249 | ++ |
250 | ++/* Returns the least-significant 32 bits of a __be64. */ |
251 | ++static __be32 be64_get_low32(__be64 x) |
252 | ++{ |
253 | ++#ifdef __BIG_ENDIAN |
254 | ++ return (__force __be32)x; |
255 | ++#else |
256 | ++ return (__force __be32)((__force u64)x >> 32); |
257 | ++#endif |
258 | ++} |
259 | ++ |
260 | ++static __be16 filter_tnl_flags(__be16 flags) |
261 | ++{ |
262 | ++ return flags & (TUNNEL_CSUM | TUNNEL_KEY); |
263 | ++} |
264 | ++ |
265 | ++static struct sk_buff *__build_header(struct sk_buff *skb, |
266 | ++ int tunnel_hlen, |
267 | ++ __be32 seq, __be16 gre64_flag) |
268 | ++{ |
269 | ++ const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key; |
270 | ++ struct tnl_ptk_info tpi; |
271 | ++ |
272 | ++ skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); |
273 | ++ if (IS_ERR(skb)) |
274 | ++ return NULL; |
275 | ++ |
276 | ++ tpi.flags = filter_tnl_flags(tun_key->tun_flags) | gre64_flag; |
277 | ++ |
278 | ++ tpi.proto = htons(ETH_P_TEB); |
279 | ++ tpi.key = be64_get_low32(tun_key->tun_id); |
280 | ++ tpi.seq = seq; |
281 | ++ gre_build_header(skb, &tpi, tunnel_hlen); |
282 | ++ |
283 | ++ return skb; |
284 | ++} |
285 | ++ |
286 | ++static __be64 key_to_tunnel_id(__be32 key, __be32 seq) |
287 | ++{ |
288 | ++#ifdef __BIG_ENDIAN |
289 | ++ return (__force __be64)((__force u64)seq << 32 | (__force u32)key); |
290 | ++#else |
291 | ++ return (__force __be64)((__force u64)key << 32 | (__force u32)seq); |
292 | ++#endif |
293 | ++} |
294 | ++ |
295 | ++/* Called with rcu_read_lock and BH disabled. */ |
296 | ++static int gre_rcv(struct sk_buff *skb, |
297 | ++ const struct tnl_ptk_info *tpi) |
298 | ++{ |
299 | ++ struct ovs_key_ipv4_tunnel tun_key; |
300 | ++ struct ovs_net *ovs_net; |
301 | ++ struct vport *vport; |
302 | ++ __be64 key; |
303 | ++ |
304 | ++ ovs_net = net_generic(dev_net(skb->dev), ovs_net_id); |
305 | ++ if ((tpi->flags & TUNNEL_KEY) && (tpi->flags & TUNNEL_SEQ)) |
306 | ++ vport = rcu_dereference(ovs_net->vport_net.gre64_vport); |
307 | ++ else |
308 | ++ vport = rcu_dereference(ovs_net->vport_net.gre_vport); |
309 | ++ if (unlikely(!vport)) |
310 | ++ return PACKET_REJECT; |
311 | ++ |
312 | ++ key = key_to_tunnel_id(tpi->key, tpi->seq); |
313 | ++ ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key, filter_tnl_flags(tpi->flags)); |
314 | ++ |
315 | ++ ovs_vport_receive(vport, skb, &tun_key); |
316 | ++ return PACKET_RCVD; |
317 | ++} |
318 | ++ |
319 | ++static int __send(struct vport *vport, struct sk_buff *skb, |
320 | ++ int tunnel_hlen, |
321 | ++ __be32 seq, __be16 gre64_flag) |
322 | ++{ |
323 | ++ struct net *net = ovs_dp_get_net(vport->dp); |
324 | ++ struct rtable *rt; |
325 | ++ int min_headroom; |
326 | ++ __be16 df; |
327 | ++ __be32 saddr; |
328 | ++ int err; |
329 | ++ |
330 | ++ /* Route lookup */ |
331 | ++ saddr = OVS_CB(skb)->tun_key->ipv4_src; |
332 | ++ rt = find_route(ovs_dp_get_net(vport->dp), |
333 | ++ &saddr, |
334 | ++ OVS_CB(skb)->tun_key->ipv4_dst, |
335 | ++ IPPROTO_GRE, |
336 | ++ OVS_CB(skb)->tun_key->ipv4_tos, |
337 | ++ skb->mark); |
338 | ++ if (IS_ERR(rt)) { |
339 | ++ err = PTR_ERR(rt); |
340 | ++ goto error; |
341 | ++ } |
342 | ++ |
343 | ++ min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len |
344 | ++ + tunnel_hlen + sizeof(struct iphdr) |
345 | ++ + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); |
346 | ++ |
347 | ++ if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { |
348 | ++ int head_delta = SKB_DATA_ALIGN(min_headroom - |
349 | ++ skb_headroom(skb) + |
350 | ++ 16); |
351 | ++ err = pskb_expand_head(skb, max_t(int, head_delta, 0), |
352 | ++ 0, GFP_ATOMIC); |
353 | ++ if (unlikely(err)) |
354 | ++ goto err_free_rt; |
355 | ++ } |
356 | ++ |
357 | ++ if (vlan_tx_tag_present(skb)) { |
358 | ++ if (unlikely(!__vlan_put_tag(skb, |
359 | ++ skb->vlan_proto, |
360 | ++ vlan_tx_tag_get(skb)))) { |
361 | ++ err = -ENOMEM; |
362 | ++ goto err_free_rt; |
363 | ++ } |
364 | ++ vlan_set_tci(skb, 0); |
365 | ++ } |
366 | ++ |
367 | ++ /* Push Tunnel header. */ |
368 | ++ skb = __build_header(skb, tunnel_hlen, seq, gre64_flag); |
369 | ++ if (unlikely(!skb)) { |
370 | ++ err = 0; |
371 | ++ goto err_free_rt; |
372 | ++ } |
373 | ++ |
374 | ++ df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? |
375 | ++ htons(IP_DF) : 0; |
376 | ++ |
377 | ++ skb->local_df = 1; |
378 | ++ |
379 | ++ return iptunnel_xmit(net, rt, skb, saddr, |
380 | ++ OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE, |
381 | ++ OVS_CB(skb)->tun_key->ipv4_tos, |
382 | ++ OVS_CB(skb)->tun_key->ipv4_ttl, df); |
383 | ++err_free_rt: |
384 | ++ ip_rt_put(rt); |
385 | ++error: |
386 | ++ return err; |
387 | ++} |
388 | ++ |
389 | ++static struct gre_cisco_protocol gre_protocol = { |
390 | ++ .handler = gre_rcv, |
391 | ++ .priority = 1, |
392 | ++}; |
393 | ++ |
394 | ++static int gre_ports; |
395 | ++static int gre_init(void) |
396 | ++{ |
397 | ++ int err; |
398 | ++ |
399 | ++ gre_ports++; |
400 | ++ if (gre_ports > 1) |
401 | ++ return 0; |
402 | ++ |
403 | ++ err = gre_cisco_register(&gre_protocol); |
404 | ++ if (err) |
405 | ++ pr_warn("cannot register gre protocol handler\n"); |
406 | ++ |
407 | ++ return err; |
408 | ++} |
409 | ++ |
410 | ++static void gre_exit(void) |
411 | ++{ |
412 | ++ gre_ports--; |
413 | ++ if (gre_ports > 0) |
414 | ++ return; |
415 | ++ |
416 | ++ gre_cisco_unregister(&gre_protocol); |
417 | ++} |
418 | ++ |
419 | ++static const char *gre_get_name(const struct vport *vport) |
420 | ++{ |
421 | ++ return vport_priv(vport); |
422 | ++} |
423 | ++ |
424 | ++static struct vport *gre_create(const struct vport_parms *parms) |
425 | ++{ |
426 | ++ struct net *net = ovs_dp_get_net(parms->dp); |
427 | ++ struct ovs_net *ovs_net; |
428 | ++ struct vport *vport; |
429 | ++ int err; |
430 | ++ |
431 | ++ err = gre_init(); |
432 | ++ if (err) |
433 | ++ return ERR_PTR(err); |
434 | ++ |
435 | ++ ovs_net = net_generic(net, ovs_net_id); |
436 | ++ if (ovsl_dereference(ovs_net->vport_net.gre_vport)) { |
437 | ++ vport = ERR_PTR(-EEXIST); |
438 | ++ goto error; |
439 | ++ } |
440 | ++ |
441 | ++ vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms); |
442 | ++ if (IS_ERR(vport)) |
443 | ++ goto error; |
444 | ++ |
445 | ++ strncpy(vport_priv(vport), parms->name, IFNAMSIZ); |
446 | ++ rcu_assign_pointer(ovs_net->vport_net.gre_vport, vport); |
447 | ++ return vport; |
448 | ++ |
449 | ++error: |
450 | ++ gre_exit(); |
451 | ++ return vport; |
452 | ++} |
453 | ++ |
454 | ++static void gre_tnl_destroy(struct vport *vport) |
455 | ++{ |
456 | ++ struct net *net = ovs_dp_get_net(vport->dp); |
457 | ++ struct ovs_net *ovs_net; |
458 | ++ |
459 | ++ ovs_net = net_generic(net, ovs_net_id); |
460 | ++ |
461 | ++ rcu_assign_pointer(ovs_net->vport_net.gre_vport, NULL); |
462 | ++ ovs_vport_deferred_free(vport); |
463 | ++ gre_exit(); |
464 | ++} |
465 | ++ |
466 | ++static int gre_send(struct vport *vport, struct sk_buff *skb) |
467 | ++{ |
468 | ++ int hlen; |
469 | ++ |
470 | ++ if (unlikely(!OVS_CB(skb)->tun_key)) |
471 | ++ return -EINVAL; |
472 | ++ |
473 | ++ hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_key->tun_flags); |
474 | ++ |
475 | ++ return __send(vport, skb, hlen, 0, 0); |
476 | ++} |
477 | ++ |
478 | ++const struct vport_ops ovs_gre_vport_ops = { |
479 | ++ .type = OVS_VPORT_TYPE_GRE, |
480 | ++ .create = gre_create, |
481 | ++ .destroy = gre_tnl_destroy, |
482 | ++ .get_name = gre_get_name, |
483 | ++ .send = gre_send, |
484 | ++}; |
485 | ++ |
486 | ++/* GRE64 vport. */ |
487 | ++static struct vport *gre64_create(const struct vport_parms *parms) |
488 | ++{ |
489 | ++ struct net *net = ovs_dp_get_net(parms->dp); |
490 | ++ struct ovs_net *ovs_net; |
491 | ++ struct vport *vport; |
492 | ++ int err; |
493 | ++ |
494 | ++ err = gre_init(); |
495 | ++ if (err) |
496 | ++ return ERR_PTR(err); |
497 | ++ |
498 | ++ ovs_net = net_generic(net, ovs_net_id); |
499 | ++ if (ovsl_dereference(ovs_net->vport_net.gre64_vport)) { |
500 | ++ vport = ERR_PTR(-EEXIST); |
501 | ++ goto error; |
502 | ++ } |
503 | ++ |
504 | ++ vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre64_vport_ops, parms); |
505 | ++ if (IS_ERR(vport)) |
506 | ++ goto error; |
507 | ++ |
508 | ++ strncpy(vport_priv(vport), parms->name, IFNAMSIZ); |
509 | ++ rcu_assign_pointer(ovs_net->vport_net.gre64_vport, vport); |
510 | ++ return vport; |
511 | ++error: |
512 | ++ gre_exit(); |
513 | ++ return vport; |
514 | ++} |
515 | ++ |
516 | ++static void gre64_tnl_destroy(struct vport *vport) |
517 | ++{ |
518 | ++ struct net *net = ovs_dp_get_net(vport->dp); |
519 | ++ struct ovs_net *ovs_net; |
520 | ++ |
521 | ++ ovs_net = net_generic(net, ovs_net_id); |
522 | ++ |
523 | ++ rcu_assign_pointer(ovs_net->vport_net.gre64_vport, NULL); |
524 | ++ ovs_vport_deferred_free(vport); |
525 | ++ gre_exit(); |
526 | ++} |
527 | ++ |
528 | ++static __be32 be64_get_high32(__be64 x) |
529 | ++{ |
530 | ++#ifdef __BIG_ENDIAN |
531 | ++ return (__force __be32)((__force u64)x >> 32); |
532 | ++#else |
533 | ++ return (__force __be32)x; |
534 | ++#endif |
535 | ++} |
536 | ++ |
537 | ++static int gre64_send(struct vport *vport, struct sk_buff *skb) |
538 | ++{ |
539 | ++ int hlen = GRE_HEADER_SECTION + /* GRE Hdr */ |
540 | ++ GRE_HEADER_SECTION + /* GRE Key */ |
541 | ++ GRE_HEADER_SECTION; /* GRE SEQ */ |
542 | ++ __be32 seq; |
543 | ++ |
544 | ++ if (unlikely(!OVS_CB(skb)->tun_key)) |
545 | ++ return -EINVAL; |
546 | ++ |
547 | ++ if (OVS_CB(skb)->tun_key->tun_flags & TUNNEL_CSUM) |
548 | ++ hlen += GRE_HEADER_SECTION; |
549 | ++ |
550 | ++ seq = be64_get_high32(OVS_CB(skb)->tun_key->tun_id); |
551 | ++ return __send(vport, skb, hlen, seq, (TUNNEL_KEY|TUNNEL_SEQ)); |
552 | ++} |
553 | ++ |
554 | ++const struct vport_ops ovs_gre64_vport_ops = { |
555 | ++ .type = OVS_VPORT_TYPE_GRE64, |
556 | ++ .create = gre64_create, |
557 | ++ .destroy = gre64_tnl_destroy, |
558 | ++ .get_name = gre_get_name, |
559 | ++ .send = gre64_send, |
560 | ++}; |
561 | ++#endif |
562 | |
563 | === modified file 'debian/patches/series' |
564 | --- debian/patches/series 2014-01-20 12:55:24 +0000 |
565 | +++ debian/patches/series 2014-05-06 21:06:26 +0000 |
566 | @@ -2,3 +2,4 @@ |
567 | fix-3.11-support.patch |
568 | xcp-interface-reconfigure.patch |
569 | kernel-3.12-support.patch |
570 | +1315306-gre-patch.patch |
Hi Mohanjith
Firstly, thanks for the merge proposal.
1) General observations
Looking at bug 1315306, I think that the bug you are hitting resides in the openvswitch module found directly in the in-tree kernel module as well as the dkms package provided by openvswitch itself.
Its worth noting that the dkms package is not compatible with the 3.13 kernel shipped with 14.04 - this was intentional as the in-tree module provides (and in some places exceeds) the function of the dkms provided modules - it was retained for backporting activities only for 3.2 kernel users on 12.04.
2) This proposal
See inline comments
Thanks
James