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